[PATCH] virsh: Added attach-disk support for network disk

Ryan Gahagan posted 1 patch 3 years, 5 months ago
Test syntax-check failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/20201118234813.28384-1-rgahagan@cs.utexas.edu
docs/manpages/virsh.rst |  31 ++++++---
tools/virsh-domain.c    | 135 +++++++++++++++++++++++++++++++++++-----
2 files changed, 145 insertions(+), 21 deletions(-)
[PATCH] virsh: Added attach-disk support for network disk
Posted by Ryan Gahagan 3 years, 5 months ago
Related issue: https://gitlab.com/libvirt/libvirt/-/issues/16
Added in support for the following parameters in attach-disk:
--source-protocol
--source-host-name
--source-host-socket
--source-host-transport

Added documentation to virsh.rst specifying usage.

Signed-off-by: Ryan Gahagan <rgahagan@cs.utexas.edu>
---
 docs/manpages/virsh.rst |  31 ++++++---
 tools/virsh-domain.c    | 135 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 145 insertions(+), 21 deletions(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 1ae6d1a0d4..36c868a3e6 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -4538,14 +4538,18 @@ attach-disk
       [--current]] | [--persistent]] [--targetbus bus]
       [--driver driver] [--subdriver subdriver] [--iothread iothread]
       [--cache cache] [--io io] [--type type] [--alias alias]
-      [--mode mode] [--sourcetype sourcetype] [--serial serial]
-      [--wwn wwn] [--rawio] [--address address] [--multifunction]
-      [--print-xml]
+      [--mode mode] [--sourcetype sourcetype]
+      [--source-protocol protocol] [--source-host-name hostname:port]
+      [--source-host-transport transport] [--source-host-socket socket]
+      [--serial serial] [--wwn wwn] [--rawio] [--address address]
+      [--multifunction] [--print-xml]
 
 Attach a new disk device to the domain.
-*source* is path for the files and devices. *target* controls the bus or
-device under which the disk is exposed to the guest OS. It indicates the
-"logical" device name; the optional *targetbus* attribute specifies the type
+*source* is path for the files and devices unless *--source-protocol*
+is specified, in which case *source* is the name of a network disk.
+*target* controls the bus or device under which the disk is exposed
+to the guest OS. It indicates the "logical" device name;
+the optional *targetbus* attribute specifies the type
 of disk device to emulate; possible values are driver specific, with typical
 values being *ide*, *scsi*, *virtio*, *xen*, *usb*, *sata*, or *sd*, if
 omitted, the bus type is inferred from the style of the device name (e.g.  a
@@ -4563,7 +4567,7 @@ within the existing virtual cdrom or floppy device; consider using
 ``update-device`` for this usage instead.
 *alias* can set user supplied alias.
 *mode* can specify the two specific mode *readonly* or *shareable*.
-*sourcetype* can indicate the type of source (block|file)
+*sourcetype* can indicate the type of source (block|file|network)
 *cache* can be one of "default", "none", "writethrough", "writeback",
 "directsync" or "unsafe".
 *io* controls specific policies on I/O; QEMU guests support "threads",
@@ -4579,6 +4583,19 @@ ccw:cssid.ssid.devno. Virtio-ccw devices must have their cssid set to 0xfe.
 *multifunction* indicates specified pci address is a multifunction pci device
 address.
 
+There is also support for using a network disk. As specified, the user can
+provide a *--source-protocol* in which case the *source* parameter will
+be interpreted as the source name. *--source-protocol* must be provided
+if the user intends to provide a network disk or host information.
+Host information can be provided using the tags
+*--source-host-name*, *--source-host-transport*, and *--source-host-socket*,
+which respectively denote the name of the host, the host's transport method,
+and the socket that the host uses. *--source-host-socket* and
+*--source-host-name* cannot both be provided, and the user must provide a
+*--source-host-transport* if they want to provide a *--source-host-socket*.
+The *--source-host-name* parameter supports host:port syntax
+if the user wants to provide a port as well.
+
 If *--print-xml* is specified, then the XML of the disk that would be attached
 is printed instead.
 
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c999458d72..1303676c33 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -222,7 +222,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
     {.name = "source",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ | VSH_OFLAG_EMPTY_OK,
-     .help = N_("source of disk device")
+     .help = N_("source of disk device or name of network disk")
     },
     {.name = "target",
      .type = VSH_OT_DATA,
@@ -268,7 +268,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
     },
     {.name = "sourcetype",
      .type = VSH_OT_STRING,
-     .help = N_("type of source (block|file)")
+     .help = N_("type of source (block|file|network)")
     },
     {.name = "serial",
      .type = VSH_OT_STRING,
@@ -298,6 +298,22 @@ static const vshCmdOptDef opts_attach_disk[] = {
      .type = VSH_OT_BOOL,
      .help = N_("print XML document rather than attach the disk")
     },
+    {.name = "source-protocol",
+     .type = VSH_OT_STRING,
+     .help = N_("protocol used by disk device source")
+    },
+    {.name = "source-host-name",
+     .type = VSH_OT_STRING,
+     .help = N_("host name for source of disk device")
+    },
+    {.name = "source-host-transport",
+     .type = VSH_OT_STRING,
+     .help = N_("host transport for source of disk device")
+    },
+    {.name = "source-host-socket",
+     .type = VSH_OT_STRING,
+     .help = N_("host socket for source of disk device")
+    },
     VIRSH_COMMON_OPT_DOMAIN_PERSISTENT,
     VIRSH_COMMON_OPT_DOMAIN_CONFIG,
     VIRSH_COMMON_OPT_DOMAIN_LIVE,
@@ -558,6 +574,13 @@ static int str2DiskAddress(const char *str, struct DiskAddress *diskAddr)
     return -1;
 }
 
+typedef enum {
+    VIRSH_SOURCE_TYPE_FILE,
+    VIRSH_SOURCE_TYPE_BLOCK,
+    VIRSH_SOURCE_TYPE_NETWORK,
+    VIRSH_SOURCE_TYPE_UNKNOWN,
+} virshAttachDiskSourceType;
+
 static bool
 cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
 {
@@ -567,8 +590,14 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
                 *iothread = NULL, *cache = NULL, *io = NULL,
                 *serial = NULL, *straddr = NULL, *wwn = NULL,
                 *targetbus = NULL, *alias = NULL;
+    const char *source_protocol = NULL;
+    const char *host_name = NULL;
+    const char *host_transport = NULL;
+    const char *host_socket = NULL;
+    char *host_port = NULL;
     struct DiskAddress diskAddr;
-    bool isFile = false, functionReturn = false;
+    virshAttachDiskSourceType disk_type = VIRSH_SOURCE_TYPE_UNKNOWN;
+    bool functionReturn = false;
     int ret;
     unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
     const char *stype = NULL;
@@ -585,6 +614,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
     VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
 
+    VSH_REQUIRE_OPTION("source-host-name", "source-protocol");
+    VSH_REQUIRE_OPTION("source-host-transport", "source-protocol");
+    VSH_REQUIRE_OPTION("source-host-socket", "source-protocol");
+    VSH_REQUIRE_OPTION("source-host-socket", "source-host-transport");
+
+    VSH_EXCLUSIVE_OPTIONS("source-host-name", "source-host-socket");
+
     if (config || persistent)
         flags |= VIR_DOMAIN_AFFECT_CONFIG;
     if (live)
@@ -604,23 +640,45 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         vshCommandOptStringReq(ctl, cmd, "address", &straddr) < 0 ||
         vshCommandOptStringReq(ctl, cmd, "targetbus", &targetbus) < 0 ||
         vshCommandOptStringReq(ctl, cmd, "alias", &alias) < 0 ||
-        vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0)
+        vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "source-protocol", &source_protocol) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "source-host-name", &host_name) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "source-host-transport", &host_transport) < 0 ||
+        vshCommandOptStringReq(ctl, cmd, "source-host-socket", &host_socket) < 0)
         goto cleanup;
 
     if (!stype) {
         if (driver && (STREQ(driver, "file") || STREQ(driver, "tap"))) {
-            isFile = true;
+            disk_type = VIRSH_SOURCE_TYPE_FILE;
         } else {
-            if (source && !stat(source, &st))
-                isFile = S_ISREG(st.st_mode) ? true : false;
+            if (source && !stat(source, &st)) {
+                if (S_ISREG(st.st_mode))
+                    disk_type = VIRSH_SOURCE_TYPE_FILE;
+                else
+                    disk_type = VIRSH_SOURCE_TYPE_BLOCK;
+            }
         }
     } else if (STREQ(stype, "file")) {
-        isFile = true;
-    } else if (STRNEQ(stype, "block")) {
+        disk_type = VIRSH_SOURCE_TYPE_FILE;
+    } else if (STREQ(stype, "block")) {
+        disk_type = VIRSH_SOURCE_TYPE_BLOCK;
+    } else if (STREQ(stype, "network")) {
+        /* The user must provide a protocol for a network disk */
+        if (!source_protocol) {
+            vshError(ctl, _("A source-protocol must be provided for a network disk"));
+            goto cleanup;
+        }
+    } else {
         vshError(ctl, _("Unknown source type: '%s'"), stype);
         goto cleanup;
     }
 
+    /* If a protocol is provided, the disk is assumed to be a network disk.
+     * This overwrites other disk types, such as an explicit
+     * 'sourcetype=file' or comparable parameter. */
+    if (source_protocol)
+        disk_type = VIRSH_SOURCE_TYPE_NETWORK;
+
     if (mode) {
         if (STRNEQ(mode, "readonly") && STRNEQ(mode, "shareable")) {
             vshError(ctl, _("No support for %s in command 'attach-disk'"),
@@ -633,8 +691,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         goto cleanup;
 
     /* Make XML of disk */
-    virBufferAsprintf(&buf, "<disk type='%s'",
-                      isFile ? "file" : "block");
+    if (disk_type == VIRSH_SOURCE_TYPE_FILE)
+        virBufferAddLit(&buf, "<disk type='file'");
+    else if (disk_type == VIRSH_SOURCE_TYPE_BLOCK)
+        virBufferAddLit(&buf, "<disk type='block'");
+    else if (disk_type == VIRSH_SOURCE_TYPE_NETWORK)
+        virBufferAddLit(&buf, "<disk type='network'");
+
     if (type)
         virBufferAsprintf(&buf, " device='%s'", type);
     if (vshCommandOptBool(cmd, "rawio"))
@@ -659,9 +722,53 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         virBufferAddLit(&buf, "/>\n");
     }
 
-    if (source)
-        virBufferAsprintf(&buf, "<source %s='%s'/>\n",
-                          isFile ? "file" : "dev", source);
+    if (source || source_protocol) {
+        virBufferAddLit(&buf, "<source");
+        if (source_protocol) {
+            /* Using a network disk; source is --source-name */
+            virBufferAsprintf(&buf, " protocol='%s'", source_protocol);
+            if (source)
+                virBufferAsprintf(&buf, " name='%s'", source);
+
+            if (host_name || host_socket || host_transport) {
+                /* Host information provided, add a <host> tag */
+                virBufferAddLit(&buf, ">\n");
+                virBufferAdjustIndent(&buf, 2);
+                virBufferAddLit(&buf, "<host");
+
+                if (host_name) {
+                    /* Logic for host:port syntax */
+                    g_autofree char *host_name_copy = g_strdup(host_name);
+                    host_port = strchr(host_name_copy, ':');
+
+                    if (host_port) {
+                        *host_port = '\0';
+                        virBufferAsprintf(&buf,
+                                          " name='%s' port='%s'",
+                                          host_name_copy, host_port + 1);
+                    } else {
+                        virBufferAsprintf(&buf, " name='%s'", host_name);
+                    }
+                }
+
+                if (host_transport)
+                    virBufferAsprintf(&buf, " transport='%s'", host_transport);
+                if (host_socket)
+                    virBufferAsprintf(&buf, " socket='%s'", host_socket);
+                virBufferAddLit(&buf, "/>\n");
+                virBufferAdjustIndent(&buf, -2);
+                virBufferAddLit(&buf, "</source>\n");
+            }
+        } else {
+            /* Using a local disk; source is file or dev */
+            if (disk_type == VIRSH_SOURCE_TYPE_FILE)
+                virBufferAsprintf(&buf, " file='%s'", source);
+            else
+                virBufferAsprintf(&buf, " dev='%s'", source);
+            virBufferAddLit(&buf, "/>\n");
+        }
+    }
+
     virBufferAsprintf(&buf, "<target dev='%s'", target);
     if (targetbus)
         virBufferAsprintf(&buf, " bus='%s'", targetbus);
-- 
2.29.0

Re: [PATCH] virsh: Added attach-disk support for network disk
Posted by Peter Krempa 3 years, 5 months ago
On Wed, Nov 18, 2020 at 17:48:13 -0600, Ryan Gahagan wrote:
> Related issue: https://gitlab.com/libvirt/libvirt/-/issues/16
> Added in support for the following parameters in attach-disk:
> --source-protocol
> --source-host-name
> --source-host-socket
> --source-host-transport
> 
> Added documentation to virsh.rst specifying usage.
> 
> Signed-off-by: Ryan Gahagan <rgahagan@cs.utexas.edu>
> ---
>  docs/manpages/virsh.rst |  31 ++++++---
>  tools/virsh-domain.c    | 135 +++++++++++++++++++++++++++++++++++-----
>  2 files changed, 145 insertions(+), 21 deletions(-)
> 
> diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
> index 1ae6d1a0d4..36c868a3e6 100644
> --- a/docs/manpages/virsh.rst
> +++ b/docs/manpages/virsh.rst
> @@ -4538,14 +4538,18 @@ attach-disk
>        [--current]] | [--persistent]] [--targetbus bus]
>        [--driver driver] [--subdriver subdriver] [--iothread iothread]
>        [--cache cache] [--io io] [--type type] [--alias alias]
> -      [--mode mode] [--sourcetype sourcetype] [--serial serial]
> -      [--wwn wwn] [--rawio] [--address address] [--multifunction]
> -      [--print-xml]
> +      [--mode mode] [--sourcetype sourcetype]
> +      [--source-protocol protocol] [--source-host-name hostname:port]
> +      [--source-host-transport transport] [--source-host-socket socket]
> +      [--serial serial] [--wwn wwn] [--rawio] [--address address]
> +      [--multifunction] [--print-xml]
>  
>  Attach a new disk device to the domain.
> -*source* is path for the files and devices. *target* controls the bus or
> -device under which the disk is exposed to the guest OS. It indicates the
> -"logical" device name; the optional *targetbus* attribute specifies the type
> +*source* is path for the files and devices unless *--source-protocol*
> +is specified, in which case *source* is the name of a network disk.
> +*target* controls the bus or device under which the disk is exposed
> +to the guest OS. It indicates the "logical" device name;
> +the optional *targetbus* attribute specifies the type
>  of disk device to emulate; possible values are driver specific, with typical
>  values being *ide*, *scsi*, *virtio*, *xen*, *usb*, *sata*, or *sd*, if
>  omitted, the bus type is inferred from the style of the device name (e.g.  a
> @@ -4563,7 +4567,7 @@ within the existing virtual cdrom or floppy device; consider using
>  ``update-device`` for this usage instead.
>  *alias* can set user supplied alias.
>  *mode* can specify the two specific mode *readonly* or *shareable*.
> -*sourcetype* can indicate the type of source (block|file)
> +*sourcetype* can indicate the type of source (block|file|network)
>  *cache* can be one of "default", "none", "writethrough", "writeback",
>  "directsync" or "unsafe".
>  *io* controls specific policies on I/O; QEMU guests support "threads",
> @@ -4579,6 +4583,19 @@ ccw:cssid.ssid.devno. Virtio-ccw devices must have their cssid set to 0xfe.
>  *multifunction* indicates specified pci address is a multifunction pci device
>  address.
>  
> +There is also support for using a network disk. As specified, the user can
> +provide a *--source-protocol* in which case the *source* parameter will
> +be interpreted as the source name. *--source-protocol* must be provided
> +if the user intends to provide a network disk or host information.
> +Host information can be provided using the tags
> +*--source-host-name*, *--source-host-transport*, and *--source-host-socket*,
> +which respectively denote the name of the host, the host's transport method,
> +and the socket that the host uses. *--source-host-socket* and
> +*--source-host-name* cannot both be provided, and the user must provide a
> +*--source-host-transport* if they want to provide a *--source-host-socket*.
> +The *--source-host-name* parameter supports host:port syntax
> +if the user wants to provide a port as well.
> +
>  If *--print-xml* is specified, then the XML of the disk that would be attached
>  is printed instead.
>  
> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
> index c999458d72..1303676c33 100644
> --- a/tools/virsh-domain.c
> +++ b/tools/virsh-domain.c
> @@ -222,7 +222,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
>      {.name = "source",
>       .type = VSH_OT_DATA,
>       .flags = VSH_OFLAG_REQ | VSH_OFLAG_EMPTY_OK,
> -     .help = N_("source of disk device")
> +     .help = N_("source of disk device or name of network disk")
>      },
>      {.name = "target",
>       .type = VSH_OT_DATA,
> @@ -268,7 +268,7 @@ static const vshCmdOptDef opts_attach_disk[] = {
>      },
>      {.name = "sourcetype",
>       .type = VSH_OT_STRING,
> -     .help = N_("type of source (block|file)")
> +     .help = N_("type of source (block|file|network)")
>      },
>      {.name = "serial",
>       .type = VSH_OT_STRING,
> @@ -298,6 +298,22 @@ static const vshCmdOptDef opts_attach_disk[] = {
>       .type = VSH_OT_BOOL,
>       .help = N_("print XML document rather than attach the disk")
>      },
> +    {.name = "source-protocol",
> +     .type = VSH_OT_STRING,
> +     .help = N_("protocol used by disk device source")
> +    },
> +    {.name = "source-host-name",
> +     .type = VSH_OT_STRING,
> +     .help = N_("host name for source of disk device")
> +    },
> +    {.name = "source-host-transport",
> +     .type = VSH_OT_STRING,
> +     .help = N_("host transport for source of disk device")
> +    },
> +    {.name = "source-host-socket",
> +     .type = VSH_OT_STRING,
> +     .help = N_("host socket for source of disk device")
> +    },
>      VIRSH_COMMON_OPT_DOMAIN_PERSISTENT,
>      VIRSH_COMMON_OPT_DOMAIN_CONFIG,
>      VIRSH_COMMON_OPT_DOMAIN_LIVE,
> @@ -558,6 +574,13 @@ static int str2DiskAddress(const char *str, struct DiskAddress *diskAddr)
>      return -1;
>  }
>  
> +typedef enum {
> +    VIRSH_SOURCE_TYPE_FILE,
> +    VIRSH_SOURCE_TYPE_BLOCK,
> +    VIRSH_SOURCE_TYPE_NETWORK,
> +    VIRSH_SOURCE_TYPE_UNKNOWN,
> +} virshAttachDiskSourceType;
> +
>  static bool
>  cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
>  {
> @@ -567,8 +590,14 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
>                  *iothread = NULL, *cache = NULL, *io = NULL,
>                  *serial = NULL, *straddr = NULL, *wwn = NULL,
>                  *targetbus = NULL, *alias = NULL;
> +    const char *source_protocol = NULL;
> +    const char *host_name = NULL;
> +    const char *host_transport = NULL;
> +    const char *host_socket = NULL;
> +    char *host_port = NULL;
>      struct DiskAddress diskAddr;
> -    bool isFile = false, functionReturn = false;
> +    virshAttachDiskSourceType disk_type = VIRSH_SOURCE_TYPE_UNKNOWN;
> +    bool functionReturn = false;
>      int ret;
>      unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
>      const char *stype = NULL;
> @@ -585,6 +614,13 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
>      VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
>      VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
>  
> +    VSH_REQUIRE_OPTION("source-host-name", "source-protocol");
> +    VSH_REQUIRE_OPTION("source-host-transport", "source-protocol");
> +    VSH_REQUIRE_OPTION("source-host-socket", "source-protocol");
> +    VSH_REQUIRE_OPTION("source-host-socket", "source-host-transport");
> +
> +    VSH_EXCLUSIVE_OPTIONS("source-host-name", "source-host-socket");
> +
>      if (config || persistent)
>          flags |= VIR_DOMAIN_AFFECT_CONFIG;
>      if (live)
> @@ -604,23 +640,45 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
>          vshCommandOptStringReq(ctl, cmd, "address", &straddr) < 0 ||
>          vshCommandOptStringReq(ctl, cmd, "targetbus", &targetbus) < 0 ||
>          vshCommandOptStringReq(ctl, cmd, "alias", &alias) < 0 ||
> -        vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0)
> +        vshCommandOptStringReq(ctl, cmd, "sourcetype", &stype) < 0 ||
> +        vshCommandOptStringReq(ctl, cmd, "source-protocol", &source_protocol) < 0 ||
> +        vshCommandOptStringReq(ctl, cmd, "source-host-name", &host_name) < 0 ||
> +        vshCommandOptStringReq(ctl, cmd, "source-host-transport", &host_transport) < 0 ||
> +        vshCommandOptStringReq(ctl, cmd, "source-host-socket", &host_socket) < 0)
>          goto cleanup;
>  
>      if (!stype) {
>          if (driver && (STREQ(driver, "file") || STREQ(driver, "tap"))) {
> -            isFile = true;
> +            disk_type = VIRSH_SOURCE_TYPE_FILE;
>          } else {
> -            if (source && !stat(source, &st))
> -                isFile = S_ISREG(st.st_mode) ? true : false;
> +            if (source && !stat(source, &st)) {
> +                if (S_ISREG(st.st_mode))
> +                    disk_type = VIRSH_SOURCE_TYPE_FILE;
> +                else
> +                    disk_type = VIRSH_SOURCE_TYPE_BLOCK;

This won't work properly. As I've noted in previous review, virsh can
run on a different host than the VM. If thus the stat call fails in your
logic here, or source is empty, you wont set 'disk_type' and the disk
element will not be printed.

> +            }
>          }
>      } else if (STREQ(stype, "file")) {
> -        isFile = true;
> -    } else if (STRNEQ(stype, "block")) {
> +        disk_type = VIRSH_SOURCE_TYPE_FILE;
> +    } else if (STREQ(stype, "block")) {
> +        disk_type = VIRSH_SOURCE_TYPE_BLOCK;
> +    } else if (STREQ(stype, "network")) {
> +        /* The user must provide a protocol for a network disk */
> +        if (!source_protocol) {
> +            vshError(ctl, _("A source-protocol must be provided for a network disk"));
> +            goto cleanup;
> +        }
> +    } else {
>          vshError(ctl, _("Unknown source type: '%s'"), stype);
>          goto cleanup;
>      }
>  
> +    /* If a protocol is provided, the disk is assumed to be a network disk.
> +     * This overwrites other disk types, such as an explicit
> +     * 'sourcetype=file' or comparable parameter. */
> +    if (source_protocol)
> +        disk_type = VIRSH_SOURCE_TYPE_NETWORK;

This is not acceptable logic. You need to ensure that --stype file and
--source-protocol are not used together.

Since it's hard to fix the logic in your patch properly without a
refactor of the original code and at the same time it would be unfair
and timeconsuming to ask you to refactor it I'll do that and I'll also
fix your patch up to conform with our new standards.

There's no need to send further versions, I'll CC you on the patchset.