[libvirt PATCH v2 12/16] qemu: use nbdkit to serve network disks if available

Jonathon Jongsma jjongsma at redhat.com
Wed Aug 31 18:40:57 UTC 2022


For virStorageSource objects that contain an nbdkitProcess, start that
nbdkit process to serve that network drive and then pass the nbdkit
socket to qemu rather than sending the network url to qemu directly.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 src/qemu/qemu_block.c                         | 168 +++++++++++-------
 src/qemu/qemu_command.c                       |   4 +-
 src/qemu/qemu_domain.c                        |  21 ++-
 src/qemu/qemu_extdevice.c                     |  84 +++++++++
 src/qemu/qemu_nbdkit.c                        |   9 +
 src/qemu/qemu_nbdkit.h                        |   2 +
 ...sk-cdrom-network-nbdkit.x86_64-latest.args |  42 +++++
 .../disk-cdrom-network-nbdkit.xml             |   1 +
 ...isk-network-http-nbdkit.x86_64-latest.args |  45 +++++
 .../disk-network-http-nbdkit.xml              |   1 +
 ...rce-curl-nbdkit-backing.x86_64-latest.args |  38 ++++
 ...isk-network-source-curl-nbdkit-backing.xml |  45 +++++
 ...work-source-curl-nbdkit.x86_64-latest.args |  50 ++++++
 .../disk-network-source-curl-nbdkit.xml       |   1 +
 ...isk-network-source-curl.x86_64-latest.args |  53 ++++++
 .../disk-network-source-curl.xml              |  71 ++++++++
 ...disk-network-ssh-nbdkit.x86_64-latest.args |  36 ++++
 .../disk-network-ssh-nbdkit.xml               |   1 +
 tests/qemuxml2argvtest.c                      |   6 +
 19 files changed, 605 insertions(+), 73 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.x86_64-latest.args
 create mode 120000 tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.xml
 create mode 100644 tests/qemuxml2argvdata/disk-network-http-nbdkit.x86_64-latest.args
 create mode 120000 tests/qemuxml2argvdata/disk-network-http-nbdkit.xml
 create mode 100644 tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.x86_64-latest.args
 create mode 100644 tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.xml
 create mode 100644 tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.x86_64-latest.args
 create mode 120000 tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.xml
 create mode 100644 tests/qemuxml2argvdata/disk-network-source-curl.x86_64-latest.args
 create mode 100644 tests/qemuxml2argvdata/disk-network-source-curl.xml
 create mode 100644 tests/qemuxml2argvdata/disk-network-ssh-nbdkit.x86_64-latest.args
 create mode 120000 tests/qemuxml2argvdata/disk-network-ssh-nbdkit.xml

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index b82e3311e1..4849d68039 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -439,6 +439,33 @@ qemuBlockStorageSourceGetCURLProps(virStorageSource *src,
 }
 
 
+static virJSONValue *
+qemuBlockStorageSourceGetNbdkitProps(virStorageSource *src)
+{
+    qemuDomainStorageSourcePrivate *srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+    virJSONValue *ret = NULL;
+    g_autoptr(virJSONValue) serverprops = NULL;
+    virStorageNetHostDef host = { .transport = VIR_STORAGE_NET_HOST_TRANS_UNIX };
+
+    /* srcPriv->nbdkitProcess will already be initialized if we can use nbdkit
+     * to proxy this storage source */
+    if (!(srcPriv  && srcPriv->nbdkitProcess))
+        return NULL;
+
+    host.transport = VIR_STORAGE_NET_HOST_TRANS_UNIX;
+    host.socket = srcPriv->nbdkitProcess->socketfile;
+    serverprops = qemuBlockStorageSourceBuildJSONSocketAddress(&host);
+
+    if (!serverprops)
+        return NULL;
+
+    if (virJSONValueObjectAdd(&ret, "a:server", &serverprops, NULL) < 0)
+        return NULL;
+
+    return ret;
+}
+
+
 static virJSONValue *
 qemuBlockStorageSourceGetISCSIProps(virStorageSource *src,
                                     bool onlytarget)
@@ -851,69 +878,75 @@ qemuBlockStorageSourceGetBackendProps(virStorageSource *src,
         return NULL;
 
     case VIR_STORAGE_TYPE_NETWORK:
-        switch ((virStorageNetProtocol) src->protocol) {
-        case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
-            driver = "gluster";
-            if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, onlytarget)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_VXHS:
-            driver = "vxhs";
-            if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, onlytarget)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_HTTP:
-        case VIR_STORAGE_NET_PROTOCOL_HTTPS:
-        case VIR_STORAGE_NET_PROTOCOL_FTP:
-        case VIR_STORAGE_NET_PROTOCOL_FTPS:
-        case VIR_STORAGE_NET_PROTOCOL_TFTP:
-            driver = virStorageNetProtocolTypeToString(src->protocol);
-            if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, onlytarget)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_ISCSI:
-            driver = "iscsi";
-            if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, onlytarget)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_NBD:
+        /* prefer using nbdkit for sources that are supported */
+        if ((fileprops = qemuBlockStorageSourceGetNbdkitProps(src))) {
             driver = "nbd";
-            if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src, onlytarget)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_RBD:
-            driver = "rbd";
-            if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src, onlytarget)))
-                return NULL;
             break;
-
-        case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
-            driver = "sheepdog";
-            if (!(fileprops = qemuBlockStorageSourceGetSheepdogProps(src)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_SSH:
-            driver = "ssh";
-            if (!(fileprops = qemuBlockStorageSourceGetSshProps(src)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_NFS:
-            driver = "nfs";
-            if (!(fileprops = qemuBlockStorageSourceGetNFSProps(src)))
-                return NULL;
-            break;
-
-        case VIR_STORAGE_NET_PROTOCOL_NONE:
-        case VIR_STORAGE_NET_PROTOCOL_LAST:
-            virReportEnumRangeError(virStorageNetProtocol, src->protocol);
-            return NULL;
+        } else {
+            switch ((virStorageNetProtocol) src->protocol) {
+                case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
+                    driver = "gluster";
+                    if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_VXHS:
+                    driver = "vxhs";
+                    if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_HTTP:
+                case VIR_STORAGE_NET_PROTOCOL_HTTPS:
+                case VIR_STORAGE_NET_PROTOCOL_FTP:
+                case VIR_STORAGE_NET_PROTOCOL_FTPS:
+                case VIR_STORAGE_NET_PROTOCOL_TFTP:
+                    driver = virStorageNetProtocolTypeToString(src->protocol);
+                    if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_ISCSI:
+                    driver = "iscsi";
+                    if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_NBD:
+                    driver = "nbd";
+                    if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_RBD:
+                    driver = "rbd";
+                    if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src, onlytarget)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
+                    driver = "sheepdog";
+                    if (!(fileprops = qemuBlockStorageSourceGetSheepdogProps(src)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_SSH:
+                    driver = "ssh";
+                    if (!(fileprops = qemuBlockStorageSourceGetSshProps(src)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_NFS:
+                    driver = "nfs";
+                    if (!(fileprops = qemuBlockStorageSourceGetNFSProps(src)))
+                        return NULL;
+                    break;
+
+                case VIR_STORAGE_NET_PROTOCOL_NONE:
+                case VIR_STORAGE_NET_PROTOCOL_LAST:
+                    virReportEnumRangeError(virStorageNetProtocol, src->protocol);
+                    return NULL;
+            }
         }
         break;
     }
@@ -1799,6 +1832,8 @@ qemuBlockGetBackingStoreString(virStorageSource *src,
     virJSONValue *props = NULL;
     g_autoptr(virURI) uri = NULL;
     g_autofree char *backingJSON = NULL;
+    qemuDomainStorageSourcePrivate *srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+    bool useNbdkit = srcPriv && srcPriv->nbdkitProcess;
 
     if (!src->sliceStorage) {
         if (virStorageSourceIsLocalStorage(src)) {
@@ -1817,7 +1852,8 @@ qemuBlockGetBackingStoreString(virStorageSource *src,
             src->ncookies == 0 &&
             src->sslverify == VIR_TRISTATE_BOOL_ABSENT &&
             src->timeout == 0 &&
-            src->readahead == 0) {
+            src->readahead == 0 &&
+            !useNbdkit) {
 
             switch ((virStorageNetProtocol) src->protocol) {
             case VIR_STORAGE_NET_PROTOCOL_NBD:
@@ -2196,6 +2232,7 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSource *src,
     g_autoptr(virJSONValue) location = NULL;
     const char *driver = NULL;
     const char *filename = NULL;
+    qemuDomainStorageSourcePrivate *srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
 
     switch (actualType) {
     case VIR_STORAGE_TYPE_FILE:
@@ -2224,6 +2261,13 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSource *src,
             break;
 
         case VIR_STORAGE_NET_PROTOCOL_SSH:
+            if (srcPriv->nbdkitProcess) {
+                /* disk creation not yet supported with nbdkit, and even if it
+                 * was supported, it would not be done with blockdev-create
+                 * props */
+                return 0;
+            }
+
             driver = "ssh";
             if (!(location = qemuBlockStorageSourceGetSshProps(src)))
                 return -1;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a31b8ee438..b941f0b3ac 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -10372,7 +10372,7 @@ qemuBuildStorageSourceAttachPrepareCommon(virStorageSource *src,
         return -1;
 
     if (srcpriv) {
-        if (srcpriv->secinfo &&
+        if (!srcpriv->nbdkitProcess && srcpriv->secinfo &&
             qemuBuildSecretInfoProps(srcpriv->secinfo, &data->authsecretProps) < 0)
             return -1;
 
@@ -10380,7 +10380,7 @@ qemuBuildStorageSourceAttachPrepareCommon(virStorageSource *src,
             qemuBuildSecretInfoProps(srcpriv->encinfo, &data->encryptsecretProps) < 0)
             return -1;
 
-        if (srcpriv->httpcookie &&
+        if (!srcpriv->nbdkitProcess && srcpriv->httpcookie &&
             qemuBuildSecretInfoProps(srcpriv->httpcookie, &data->httpcookiesecretProps) < 0)
             return -1;
 
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 1fd1db2f11..f69cfee0cf 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10821,21 +10821,24 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk,
     if (qemuDomainSecretStorageSourcePrepareEncryption(priv, src,
                                                        src->nodeformat) < 0)
         return -1;
-    if (qemuDomainSecretStorageSourcePrepareAuth(priv, src,
-                                                 src->nodestorage) < 0)
-        return -1;
 
     if (qemuDomainPrepareStorageSourcePR(src, priv, src->nodestorage) < 0)
         return -1;
 
-    if (qemuDomainPrepareStorageSourceTLS(src, cfg, src->nodestorage,
-                                          priv) < 0)
-        return -1;
+    if (!qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, priv)) {
+        /* If we're using nbdkit to serve the storage source, we don't pass
+         * authentication secrets to qemu, but will pass them to nbdkit instead */
+        if (qemuDomainSecretStorageSourcePrepareAuth(priv, src,
+                                                     src->nodestorage) < 0)
+            return -1;
 
-    if (qemuDomainPrepareStorageSourceNFS(src) < 0)
-        return -1;
+        if (qemuDomainPrepareStorageSourceTLS(src, cfg, src->nodestorage,
+                                              priv) < 0)
+            return -1;
 
-    qemuDomainPrepareStorageSourceNbdkit(src, cfg, src->nodestorage, priv);
+        if (qemuDomainPrepareStorageSourceNFS(src) < 0)
+            return -1;
+    }
 
     return 0;
 }
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index b8e3c1000a..ffab7d048b 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -164,6 +164,25 @@ qemuExtDevicesCleanupHost(virQEMUDriver *driver,
 }
 
 
+/* recursively start nbdkit for backing chain of src */
+static int qemuExtDevicesStartNbdkit(virQEMUDriver *driver,
+                                     virDomainObj *vm,
+                                     virStorageSource *src)
+{
+    qemuDomainStorageSourcePrivate *priv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+
+    if (src->backingStore)
+        if (qemuExtDevicesStartNbdkit(driver, vm, src->backingStore) < 0)
+            return -1;
+
+    if (priv && priv->nbdkitProcess &&
+        qemuNbdkitProcessStart(priv->nbdkitProcess, vm, driver) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 int
 qemuExtDevicesStart(virQEMUDriver *driver,
                     virDomainObj *vm,
@@ -218,6 +237,34 @@ qemuExtDevicesStart(virQEMUDriver *driver,
             return -1;
     }
 
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDef *disk = def->disks[i];
+        if (qemuExtDevicesStartNbdkit(driver, vm, disk->src) < 0)
+            return -1;
+    }
+
+    if (def->os.loader && def->os.loader->nvram) {
+        if (qemuExtDevicesStartNbdkit(driver, vm, def->os.loader->nvram) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+
+/* recursively stop nbdkit processes for backing chain of src */
+static int qemuExtDevicesStopNbdkit(virStorageSource *src)
+{
+    qemuDomainStorageSourcePrivate *priv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+
+    if (src->backingStore)
+        if (qemuExtDevicesStopNbdkit(src->backingStore) < 0)
+            return -1;
+
+    if (priv && priv->nbdkitProcess &&
+        qemuNbdkitProcessStop(priv->nbdkitProcess) < 0)
+        return -1;
+
     return 0;
 }
 
@@ -262,6 +309,14 @@ qemuExtDevicesStop(virQEMUDriver *driver,
             fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS)
             qemuVirtioFSStop(driver, vm, fs);
     }
+
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDef *disk = def->disks[i];
+        qemuExtDevicesStopNbdkit(disk->src);
+    }
+
+    if (def->os.loader && def->os.loader->nvram)
+        qemuExtDevicesStopNbdkit(def->os.loader->nvram);
 }
 
 
@@ -291,6 +346,24 @@ qemuExtDevicesHasDevice(virDomainDef *def)
 }
 
 
+/* recursively setup nbdkit cgroups for backing chain of src */
+static int qemuExtDevicesSetupCgroupNbdkit(virStorageSource *src,
+                                           virCgroup *cgroup)
+{
+        qemuDomainStorageSourcePrivate *priv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src);
+
+        if (src->backingStore)
+            if (qemuExtDevicesSetupCgroupNbdkit(src->backingStore, cgroup) < 0)
+                return -1;
+
+        if (priv && priv->nbdkitProcess &&
+            qemuNbdkitProcessSetupCgroup(priv->nbdkitProcess, cgroup) < 0)
+            return -1;
+
+        return 0;
+}
+
+
 int
 qemuExtDevicesSetupCgroup(virQEMUDriver *driver,
                           virDomainObj *vm,
@@ -324,6 +397,17 @@ qemuExtDevicesSetupCgroup(virQEMUDriver *driver,
             return -1;
     }
 
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDef *disk = def->disks[i];
+        if (qemuExtDevicesSetupCgroupNbdkit(disk->src, cgroup) < 0)
+            return -1;
+    }
+
+    if (def->os.loader && def->os.loader->nvram) {
+        if (qemuExtDevicesSetupCgroupNbdkit(def->os.loader->nvram, cgroup) < 0)
+            return -1;
+    }
+
     for (i = 0; i < def->nfss; i++) {
         virDomainFSDef *fs = def->fss[i];
 
diff --git a/src/qemu/qemu_nbdkit.c b/src/qemu/qemu_nbdkit.c
index df3a691bff..46d4a8a7ac 100644
--- a/src/qemu/qemu_nbdkit.c
+++ b/src/qemu/qemu_nbdkit.c
@@ -827,6 +827,15 @@ qemuNbdkitProcessFree(qemuNbdkitProcess *proc)
 }
 
 
+int
+qemuNbdkitProcessSetupCgroup(qemuNbdkitProcess *proc,
+                             virCgroup *cgroup)
+{
+    return virCgroupAddProcess(cgroup, proc->pid);
+}
+
+
+/* FIXME: selinux permissions errors */
 int
 qemuNbdkitProcessStart(qemuNbdkitProcess *proc,
                        virDomainObj *vm,
diff --git a/src/qemu/qemu_nbdkit.h b/src/qemu/qemu_nbdkit.h
index 07ae0eead4..4fda5113a2 100644
--- a/src/qemu/qemu_nbdkit.h
+++ b/src/qemu/qemu_nbdkit.h
@@ -81,4 +81,6 @@ int qemuNbdkitProcessStop(qemuNbdkitProcess *proc);
 
 void qemuNbdkitProcessFree(qemuNbdkitProcess *proc);
 
+int qemuNbdkitProcessSetupCgroup(qemuNbdkitProcess *proc, virCgroup *cgroup);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuNbdkitProcess, qemuNbdkitProcessFree);
diff --git a/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.x86_64-latest.args b/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.x86_64-latest.args
new file mode 100644
index 0000000000..eec7ef2af7
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.x86_64-latest.args
@@ -0,0 +1,42 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel kvm \
+-cpu qemu64 \
+-m 1024 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-3-storage.socket"},"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-3-format","read-only":true,"driver":"raw","file":"libvirt-3-storage"}' \
+-device '{"driver":"ide-cd","bus":"ide.0","unit":0,"drive":"libvirt-3-format","id":"ide0-0-0","bootindex":1}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-2-storage.socket"},"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}' \
+-device '{"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-2-format","id":"ide0-0-1"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-1-storage.socket"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"raw","file":"libvirt-1-storage"}' \
+-device '{"driver":"ide-cd","bus":"ide.1","unit":0,"drive":"libvirt-1-format","id":"ide0-1-0"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.xml b/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.xml
new file mode 120000
index 0000000000..55f677546f
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-cdrom-network-nbdkit.xml
@@ -0,0 +1 @@
+disk-cdrom-network.xml
\ No newline at end of file
diff --git a/tests/qemuxml2argvdata/disk-network-http-nbdkit.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-http-nbdkit.x86_64-latest.args
new file mode 100644
index 0000000000..25d476d3ce
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-http-nbdkit.x86_64-latest.args
@@ -0,0 +1,45 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel kvm \
+-cpu qemu64 \
+-m 214 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-4-storage.socket"},"node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"raw","file":"libvirt-4-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-4-format","id":"virtio-disk0","bootindex":1}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-3-storage.socket"},"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"raw","file":"libvirt-3-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-3-format","id":"virtio-disk1"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-2-storage.socket"},"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw","file":"libvirt-2-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-2-format","id":"virtio-disk2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-1-storage.socket"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-1-format","id":"virtio-disk3"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-network-http-nbdkit.xml b/tests/qemuxml2argvdata/disk-network-http-nbdkit.xml
new file mode 120000
index 0000000000..6a05204e8a
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-http-nbdkit.xml
@@ -0,0 +1 @@
+disk-network-http.xml
\ No newline at end of file
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.x86_64-latest.args
new file mode 100644
index 0000000000..98cfcd219a
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.x86_64-latest.args
@@ -0,0 +1,38 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel tcg \
+-cpu qemu64 \
+-m 214 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-2-storage.socket"},"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"qcow2","file":"libvirt-2-storage"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-1-storage.socket"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"qcow2","file":"libvirt-1-storage","backing":"libvirt-2-format"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-1-format","id":"virtio-disk0","bootindex":1}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.xml b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.xml
new file mode 100644
index 0000000000..37a30fcbd6
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit-backing.xml
@@ -0,0 +1,45 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='network' device='disk'>
+      <driver name='qemu' type='qcow2'/>
+      <source protocol='https' name='path/to/disk1.qcow2'>
+        <host name='https.example.org' port='8443'/>
+        <cookies>
+            <cookie name='cookie1'>cookievalue1</cookie>
+            <cookie name='cookie2'>cookievalue2</cookie>
+        </cookies>
+      </source>
+      <backingStore type='network'>
+          <format type='qcow2'/>
+          <source protocol='https' name='path/to/backing.qcow2'>
+              <host name='https.example2.org' port='8444'/>
+              <cookies>
+                  <cookie name='cookie3'>cookievalue3</cookie>
+                  <cookie name='cookie4'>cookievalue4</cookie>
+              </cookies>
+          </source>
+      </backingStore>
+      <target dev='vda' bus='virtio'/>
+      <readonly/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.x86_64-latest.args
new file mode 100644
index 0000000000..ec193bb10a
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.x86_64-latest.args
@@ -0,0 +1,50 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel tcg \
+-cpu qemu64 \
+-m 214 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-device '{"driver":"ahci","id":"sata0","bus":"pci.0","addr":"0x2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-5-storage.socket"},"node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-5-format","read-only":true,"driver":"raw","file":"libvirt-5-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-5-format","id":"virtio-disk0","bootindex":1}' \
+-object '{"qom-type":"secret","id":"libvirt-4-format-encryption-secret0","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-4-storage.socket"},"node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"luks","key-secret":"libvirt-4-format-encryption-secret0","file":"libvirt-4-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-4-format","id":"virtio-disk4"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-3-storage.socket"},"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-3-format","read-only":true,"driver":"raw","file":"libvirt-3-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.1","drive":"libvirt-3-format","id":"sata0-0-1"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-2-storage.socket"},"node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.2","drive":"libvirt-2-format","id":"sata0-0-2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-1-storage.socket"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"raw","file":"libvirt-1-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.3","drive":"libvirt-1-format","id":"sata0-0-3"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.xml b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.xml
new file mode 120000
index 0000000000..4a1e40bd70
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl-nbdkit.xml
@@ -0,0 +1 @@
+disk-network-source-curl.xml
\ No newline at end of file
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-source-curl.x86_64-latest.args
new file mode 100644
index 0000000000..ec6dd13f6c
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl.x86_64-latest.args
@@ -0,0 +1,53 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel tcg \
+-cpu qemu64 \
+-m 214 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-device '{"driver":"ahci","id":"sata0","bus":"pci.0","addr":"0x2"}' \
+-object '{"qom-type":"secret","id":"libvirt-5-storage-httpcookie-secret0","data":"BUU0KmnWfonHdjzhYhwVQZ5iTI1KweTJ22q8XWUVoBCVu1z70reDuczPBIabZtC3","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
+-blockdev '{"driver":"https","url":"https://https.example.org:8443/path/to/disk1.iso","cookie-secret":"libvirt-5-storage-httpcookie-secret0","node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-5-format","read-only":true,"driver":"raw","file":"libvirt-5-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-5-format","id":"virtio-disk0","bootindex":1}' \
+-object '{"qom-type":"secret","id":"libvirt-4-format-encryption-secret0","data":"9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
+-object '{"qom-type":"secret","id":"libvirt-4-storage-httpcookie-secret0","data":"BUU0KmnWfonHdjzhYhwVQZ5iTI1KweTJ22q8XWUVoBCVu1z70reDuczPBIabZtC3","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
+-blockdev '{"driver":"https","url":"https://https.example.org:8443/path/to/disk5.iso?foo=bar","sslverify":false,"cookie-secret":"libvirt-4-storage-httpcookie-secret0","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"luks","key-secret":"libvirt-4-format-encryption-secret0","file":"libvirt-4-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-4-format","id":"virtio-disk4"}' \
+-object '{"qom-type":"secret","id":"libvirt-3-storage-httpcookie-secret0","data":"BUU0KmnWfonHdjzhYhwVQZ5iTI1KweTJ22q8XWUVoBBv7TuTgTkyAyOPpC2P5qLbOIypLoHpppjz+u5O+X8oT+jA1m7q/OJQ8dk2EFD5c0A=","keyid":"masterKey0","iv":"AAECAwQFBgcICQoLDA0ODw==","format":"base64"}' \
+-blockdev '{"driver":"http","url":"http://http.example.org:8080/path/to/disk2.iso","cookie-secret":"libvirt-3-storage-httpcookie-secret0","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-3-format","read-only":true,"driver":"raw","file":"libvirt-3-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.1","drive":"libvirt-3-format","id":"sata0-0-1"}' \
+-blockdev '{"driver":"ftp","url":"ftp://ftp.example.org:20/path/to/disk3.iso","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"raw","file":"libvirt-2-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.2","drive":"libvirt-2-format","id":"sata0-0-2"}' \
+-blockdev '{"driver":"ftps","url":"ftps://ftps.example.org:22/path/to/disk4.iso","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"raw","file":"libvirt-1-storage"}' \
+-device '{"driver":"ide-cd","bus":"sata0.3","drive":"libvirt-1-format","id":"sata0-0-3"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-network-source-curl.xml b/tests/qemuxml2argvdata/disk-network-source-curl.xml
new file mode 100644
index 0000000000..1e50314abe
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-source-curl.xml
@@ -0,0 +1,71 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='network' device='disk'>
+      <source protocol='https' name='path/to/disk1.iso'>
+        <host name='https.example.org' port='8443'/>
+        <cookies>
+            <cookie name='cookie1'>cookievalue1</cookie>
+            <cookie name='cookie2'>cookievalue2</cookie>
+        </cookies>
+      </source>
+      <target dev='vda' bus='virtio'/>
+      <readonly/>
+    </disk>
+    <disk type='network' device='cdrom'>
+        <source protocol='http' name='path/to/disk2.iso'>
+        <host name='http.example.org' port='8080'/>
+        <cookies>
+            <cookie name='cookie1'>cookievalue1</cookie>
+            <cookie name='cookie2'>cookievalue2</cookie>
+            <cookie name='cookie3'>cookievalue3</cookie>
+        </cookies>
+      </source>
+      <target dev='hdb' bus='sata'/>
+    </disk>
+    <disk type='network' device='cdrom'>
+        <source protocol='ftp' name='path/to/disk3.iso'>
+        <host name='ftp.example.org' port='20'/>
+      </source>
+      <target dev='hdc' bus='sata'/>
+    </disk>
+    <disk type='network' device='cdrom'>
+        <source protocol='ftps' name='path/to/disk4.iso'>
+        <host name='ftps.example.org' port='22'/>
+      </source>
+      <target dev='hdd' bus='sata'/>
+    </disk>
+    <disk type='network' device='disk'>
+      <source protocol='https' name='path/to/disk5.iso' query='foo=bar'>
+        <host name='https.example.org' port='8443'/>
+        <ssl verify='no'/>
+        <cookies>
+            <cookie name='cookie1'>cookievalue1</cookie>
+            <cookie name='cookie2'>cookievalue2</cookie>
+        </cookies>
+        <encryption format='luks'>
+          <secret type='passphrase' uuid='1148b693-0843-4cef-9f97-8feb4e1ae365'/>
+        </encryption>
+      </source>
+      <target dev='vde' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.x86_64-latest.args
new file mode 100644
index 0000000000..e22ba095b1
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.x86_64-latest.args
@@ -0,0 +1,36 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram \
+-accel kvm \
+-cpu qemu64 \
+-m 214 \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/tmp/lib/domain--1-QEMUGuest1/nbdkit-libvirt-1-storage.socket"},"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-1-format","id":"virtio-disk0","bootindex":1}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.xml b/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.xml
new file mode 120000
index 0000000000..b0589bdfb5
--- /dev/null
+++ b/tests/qemuxml2argvdata/disk-network-ssh-nbdkit.xml
@@ -0,0 +1 @@
+disk-network-ssh.xml
\ No newline at end of file
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 4890c3b01b..afbc35b08b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1326,6 +1326,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("disk-cdrom-empty-network-invalid");
     DO_TEST_CAPS_LATEST("disk-cdrom-bus-other");
     DO_TEST_CAPS_LATEST("disk-cdrom-network");
+    DO_TEST_CAPS_LATEST_NBDKIT("disk-cdrom-network-nbdkit", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
     DO_TEST_CAPS_LATEST("disk-cdrom-tray");
     DO_TEST_CAPS_LATEST("disk-floppy");
     DO_TEST_CAPS_LATEST("disk-floppy-q35");
@@ -1366,6 +1367,9 @@ mymain(void)
     /* qemu-6.0 is the last qemu version supporting sheepdog */
     DO_TEST_CAPS_VER("disk-network-sheepdog", "6.0.0");
     DO_TEST_CAPS_LATEST("disk-network-source-auth");
+    DO_TEST_CAPS_LATEST("disk-network-source-curl");
+    DO_TEST_CAPS_LATEST_NBDKIT("disk-network-source-curl-nbdkit", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
+    DO_TEST_CAPS_LATEST_NBDKIT("disk-network-source-curl-nbdkit-backing", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
     DO_TEST_CAPS_LATEST("disk-network-nfs");
     driver.config->vxhsTLS = 1;
     driver.config->nbdTLSx509secretUUID = g_strdup("6fd3f62d-9fe7-4a4e-a869-7acd6376d8ea");
@@ -1376,7 +1380,9 @@ mymain(void)
     DO_TEST_CAPS_LATEST("disk-network-tlsx509-nbd-hostname");
     DO_TEST_CAPS_VER("disk-network-tlsx509-vxhs", "5.0.0");
     DO_TEST_CAPS_LATEST("disk-network-http");
+    DO_TEST_CAPS_LATEST_NBDKIT("disk-network-http-nbdkit", QEMU_NBDKIT_CAPS_PLUGIN_CURL);
     DO_TEST_CAPS_LATEST("disk-network-ssh");
+    DO_TEST_CAPS_LATEST_NBDKIT("disk-network-ssh-nbdkit", QEMU_NBDKIT_CAPS_PLUGIN_SSH);
     driver.config->vxhsTLS = 0;
     VIR_FREE(driver.config->vxhsTLSx509certdir);
     DO_TEST_CAPS_LATEST("disk-no-boot");
-- 
2.37.1



More information about the libvir-list mailing list