Daniel P. Berrange wrote: > On Mon, Aug 11, 2008 at 03:58:41PM -0400, Cole Robinson wrote: > >> The patch below implements virStorageVolDelete for volumes >> on a disk pool. >> >> The only interesting thing here is that parted wants a >> partition number to delete, so we need to peel off the >> end of the volume's target path which will be of the form >> '/dev/sda1' or similar (I assume. If not, it's still >> better than having nothing implemented). >> >> Thanks, >> Cole >> >> { >> - /* delete a partition */ >> - virStorageReportError(conn, VIR_ERR_NO_SUPPORT, >> - _("Disk pools are not yet supported")); >> - return -1; >> + char *part_num = NULL; >> + int i; >> + >> + /* Strip target path (ex. '/dev/sda1') of its partition number */ >> + for (i = (strlen(vol->target.path)-1); i >= 0; --i) { >> + if (!c_isdigit(vol->target.path[i])) >> + break; >> + part_num = &(vol->target.path[i]); >> + } >> + >> + if (!part_num) { >> + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, >> + _("cannot parse partition number from target " >> + "path '%s'"), vol->target.path); >> + return -1; >> + } >> > > This isn't correct because the target path is not guarenteed to point to > the master device name /dev/sda1. The user could have configured it to > use a stable path such as /dev/disk/by-uuid/4cb23887-0d02-4e4c-bc95-7599c85afc1a > > Hmm, I couldn't actually get /dev/disk/by-uuid to work. Seems like the vol populating code for disks doesn't take into account the the pools target path, and just uses the real partition path. > So, you need to first call 'readlink' on the vol->target.path, ignoring > EINVAL which you'll get if it wasn't a symlink. Once you've done that > you'll need to validate that it is sane by checking that vol->source.devices[0] > is a prefix of the resolved pathname. Finally, you can extract the partition > number. So something along the lines of > > char devname[PATH_MAX]; > > if (readlink(vol->target.path, devname, sizeof(devname)) < 0 && > errno != EINVAL) > virStorageReportError(...) > > if (!STRPREFIX(devname, vol->source.devices[0].path)) > virStorageReportError(....) > > part_num = devname + strlen(vol->source.devices[0].path) > The attached patch uses this approach. It works for the case with vols of the form /dev/sdx123, but as mentioned above I couldn't get by-uuid method to work, so can't be certain about that. Thanks, Cole
diff --git a/src/storage_backend_disk.c b/src/storage_backend_disk.c index 31a35b5..889ed66 100644 --- a/src/storage_backend_disk.c +++ b/src/storage_backend_disk.c @@ -22,6 +22,7 @@ */ #include <config.h> +#include <string.h> #include "internal.h" #include "storage_backend_disk.h" @@ -417,13 +418,6 @@ virStorageBackendDiskBuildPool(virConnectPtr conn, return 0; } - -static int -virStorageBackendDiskDeleteVol(virConnectPtr conn, - virStoragePoolObjPtr pool, - virStorageVolDefPtr vol, - unsigned int flags); - static int virStorageBackendDiskCreateVol(virConnectPtr conn, virStoragePoolObjPtr pool, @@ -487,14 +481,56 @@ virStorageBackendDiskCreateVol(virConnectPtr conn, static int virStorageBackendDiskDeleteVol(virConnectPtr conn, - virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, - virStorageVolDefPtr vol ATTRIBUTE_UNUSED, + virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, unsigned int flags ATTRIBUTE_UNUSED) { - /* delete a partition */ - virStorageReportError(conn, VIR_ERR_NO_SUPPORT, - _("Disk pools are not yet supported")); - return -1; + char *part_num = NULL; + int i, n; + char devname[PATH_MAX]; + + if ((n = readlink(vol->target.path, devname, sizeof(devname))) < 0 && + errno != EINVAL) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Couldn't read volume target path '%s'. %s"), + vol->target.path, strerror(errno)); + return -1; + } else if (n <= 0) { + strncpy(devname, vol->target.path, PATH_MAX); + } else { + devname[n] = '\0'; + } + + if (!STRPREFIX(devname, pool->def->source.devices[0].path)) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Volume path did not start with parent pool " + "path.")); + return -1; + } + + part_num = devname + strlen(pool->def->source.devices[0].path); + + if (!part_num) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("cannot parse partition number from target " + "path '%s'"), vol->target.path); + return -1; + } + + /* eg parted /dev/sda rm 2 */ + const char *prog[] = { + PARTED, + pool->def->source.devices[0].path, + "rm", + "--script", + part_num, + NULL, + }; + + if (virRun(conn, prog, NULL) < 0) + return -1; + + return 0; }
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list