[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH] Implement vol delete for disk pools



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;
 }
 
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]