[libvirt] [PATCH] Allow a zfs pool or dataset as source for zfs storage backend

Gregor Kopka posted 1 patch 4 years, 5 months ago
Test syntax-check passed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20191107040314.2653-1-gregor@kopka.net
src/storage/storage_backend_zfs.c | 40 ++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 11 deletions(-)
[libvirt] [PATCH] Allow a zfs pool or dataset as source for zfs storage backend
Posted by Gregor Kopka 4 years, 5 months ago
Enables hosting a pool on an existing zfs pool without affecting
other datasets there.
Specify dataset instead of pool as source to use.
Parent of dataset must exist for pool-build to succeed.
Beware that pool-delete destroys the source dataset and all children.

Solves: https://www.redhat.com/archives/libvirt-users/2017-April/msg00041.html

Signed-off-by: Gregor Kopka <gregor@kopka.net>
---
 src/storage/storage_backend_zfs.c | 40 ++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/src/storage/storage_backend_zfs.c b/src/storage/storage_backend_zfs.c
index c3057fede6..950c5234e0 100644
--- a/src/storage/storage_backend_zfs.c
+++ b/src/storage/storage_backend_zfs.c
@@ -115,10 +115,10 @@ virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
     if (count != 3)
         goto cleanup;
 
-    if (!(name_tokens = virStringSplit(tokens[0], "/", 2)))
+    if (!(name_tokens = virStringSplitCount(tokens[0], "/", 0, &count)))
         goto cleanup;
 
-    vol_name = name_tokens[1];
+    vol_name = name_tokens[count-1];
 
     if (vol == NULL)
         volume = virStorageVolDefFindByName(pool, vol_name);
@@ -225,6 +225,7 @@ virStorageBackendZFSRefreshPool(virStoragePoolObjPtr pool G_GNUC_UNUSED)
     g_autoptr(virCommand) cmd = NULL;
     VIR_AUTOSTRINGLIST lines = NULL;
     VIR_AUTOSTRINGLIST tokens = NULL;
+    VIR_AUTOSTRINGLIST name_tokens = NULL;
 
     /**
      * $ zpool get -Hp health,size,free,allocated test
@@ -236,10 +237,13 @@ virStorageBackendZFSRefreshPool(virStoragePoolObjPtr pool G_GNUC_UNUSED)
      *
      * Here we just provide a list of properties we want to see
      */
+    if (!(name_tokens = virStringSplit(def->source.name, "/", 0)))
+        goto cleanup;
+
     cmd = virCommandNewArgList(ZPOOL,
                                "get", "-Hp",
                                "health,size,free,allocated",
-                               def->source.name,
+                               name_tokens[0],
                                NULL);
     virCommandSetOutputBuffer(cmd, &zpool_props);
     if (virCommandRun(cmd, NULL) < 0)
@@ -384,20 +388,27 @@ virStorageBackendZFSBuildPool(virStoragePoolObjPtr pool,
     size_t i;
     g_autoptr(virCommand) cmd = NULL;
     int ret = -1;
+    char *tmp;
 
     virCheckFlags(0, -1);
+    tmp = strstr(def->source.name, "/");
+    if (tmp) {
+        cmd = virCommandNewArgList(ZFS, "create", "-o", "mountpoint=none",
+                               def->source.name, NULL);
+    } else {
+        if (def->source.ndevice == 0) {
 
-    if (def->source.ndevice == 0) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        "%s", _("missing source devices"));
-        return -1;
-    }
+            return -1;
+        }
 
-    cmd = virCommandNewArgList(ZPOOL, "create",
+        cmd = virCommandNewArgList(ZPOOL, "create",
                                def->source.name, NULL);
 
-    for (i = 0; i < def->source.ndevice; i++)
-        virCommandAddArg(cmd, def->source.devices[i].path);
+        for (i = 0; i < def->source.ndevice; i++)
+            virCommandAddArg(cmd, def->source.devices[i].path);
+    }
 
     virObjectUnlock(pool);
     ret = virCommandRun(cmd, NULL);
@@ -412,11 +423,18 @@ virStorageBackendZFSDeletePool(virStoragePoolObjPtr pool,
 {
     virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
     g_autoptr(virCommand) cmd = NULL;
+    char *tmp;
 
     virCheckFlags(0, -1);
 
-    cmd = virCommandNewArgList(ZPOOL, "destroy",
+    tmp = strstr(def->source.name, "/");
+    if (tmp) {
+        cmd = virCommandNewArgList(ZFS, "destroy", "-r",
+                               def->source.name, NULL);
+    } else {
+        cmd = virCommandNewArgList(ZPOOL, "destroy",
                                def->source.name, NULL);
+    }
 
     return virCommandRun(cmd, NULL);
 }
-- 
2.22.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH] Allow a zfs pool or dataset as source for zfs storage backend
Posted by Michal Privoznik 4 years, 5 months ago
On 11/7/19 5:03 AM, Gregor Kopka wrote:
> Enables hosting a pool on an existing zfs pool without affecting
> other datasets there.
> Specify dataset instead of pool as source to use.
> Parent of dataset must exist for pool-build to succeed.
> Beware that pool-delete destroys the source dataset and all children.
> 
> Solves: https://www.redhat.com/archives/libvirt-users/2017-April/msg00041.html
> 
> Signed-off-by: Gregor Kopka <gregor@kopka.net>
> ---
>   src/storage/storage_backend_zfs.c | 40 ++++++++++++++++++++++---------
>   1 file changed, 29 insertions(+), 11 deletions(-)

Fixed couple of misalignments, ACKed and pushed.

Congratulations on your first libvirt contribution. If you want the 
second one, you can send a patch that updates docs/news.xml and 
documents this change ;-)

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list