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

Peter Krempa pkrempa at redhat.com
Thu Nov 19 16:26:20 UTC 2020


From: Ryan Gahagan <rgahagan at cs.utexas.edu>

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 at cs.utexas.edu>
Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 docs/manpages/virsh.rst     | 31 ++++++++++---
 tests/virsh-output-commands | 14 ++++++
 tests/virsh-output.out      | 88 +++++++++++++++++++++++++++++++++++++
 tools/virsh-domain.c        | 84 ++++++++++++++++++++++++++++++-----
 4 files changed, 200 insertions(+), 17 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/tests/virsh-output-commands b/tests/virsh-output-commands
index 43f87bee0f..d8e73fc1ac 100755
--- a/tests/virsh-output-commands
+++ b/tests/virsh-output-commands
@@ -78,3 +78,17 @@ attach_disk --target sda --sourcetype file --type disk --address ccw:12.34.56
 attach_disk --target vda --sourcetype file --type disk --address test:12.34.56
 attach_disk --target vda --sourcetype file --type disk --address test:12:34:56
 attach_disk --target vda --sourcetype file --type disk --address test:12.34.56
+
+./virsh attach-disk --print-xml --domain testdom $@ --source "" --source-protocol AAA
+./virsh attach-disk --print-xml --domain testdom $@ --source "" --source-protocol AAA
+attach_disk --target hda --source-protocol AAA --sourcetype file
+attach_disk --target hda --sourcetype network
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name :port
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name :
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port --source-host-transport trnsp
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp --source-host-socket /nonexistent/socket
+attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-socket /nonexistent/socket
diff --git a/tests/virsh-output.out b/tests/virsh-output.out
index 6af7600a9c..d8ef641c2a 100644
--- a/tests/virsh-output.out
+++ b/tests/virsh-output.out
@@ -405,4 +405,92 @@ error: Invalid address.
 + ./virsh attach-disk --print-xml --domain testdom --target vda --sourcetype file --type disk --address test:12.34.56 --source /nonexistent/file
 error: Invalid address.

++ ./virsh attach-disk --print-xml --domain testdom --source '' --source-protocol AAA
+error: command 'attach-disk' requires <target> option
++ ./virsh attach-disk --print-xml --domain testdom --source '' --source-protocol AAA
+error: command 'attach-disk' requires <target> option
++ attach_disk --target hda --source-protocol AAA --sourcetype file
++ ./virsh attach-disk --print-xml --domain testdom --target hda --source-protocol AAA --sourcetype file --source /nonexistent/file
+error: --source-protocol option requires --sourcetype network
+
++ attach_disk --target hda --sourcetype network
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source /nonexistent/file
+error: --source-protocol option requires --sourcetype network
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name hostname --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host name='hostname'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host name='hostname' port='port'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name hostname: --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host name='hostname' port=''/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name :port
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name :port --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host name='' port='port'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name :
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name : --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host name='' port=''/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port --source-host-transport trnsp
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-name hostname:port --source-host-transport trnsp --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host transport='trnsp' name='hostname' port='port'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host transport='trnsp'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp --source-host-socket /nonexistent/socket
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-transport trnsp --source-host-socket /nonexistent/socket --source /nonexistent/file
+<disk type='network'>
+  <source protocol='TEST' name='/nonexistent/file'>
+    <host transport='trnsp' socket='/nonexistent/socket'/>
+  </source>
+  <target dev='hda'/>
+</disk>
+
++ attach_disk --target hda --sourcetype network --source-protocol TEST --source-host-socket /nonexistent/socket
++ ./virsh attach-disk --print-xml --domain testdom --target hda --sourcetype network --source-protocol TEST --source-host-socket /nonexistent/socket --source /nonexistent/file
+error: Option --source-host-transport is required by option --source-host-socket
+
 end
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index b0e1c6e6f7..7203403b31 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -394,7 +394,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,
@@ -440,7 +440,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,
@@ -470,6 +470,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,
@@ -523,6 +539,7 @@ enum virshAttachDiskSourceType {
     VIRSH_ATTACH_DISK_SOURCE_TYPE_NONE,
     VIRSH_ATTACH_DISK_SOURCE_TYPE_FILE,
     VIRSH_ATTACH_DISK_SOURCE_TYPE_BLOCK,
+    VIRSH_ATTACH_DISK_SOURCE_TYPE_NETWORK,

     VIRSH_ATTACH_DISK_SOURCE_TYPE_LAST
 };
@@ -532,7 +549,8 @@ VIR_ENUM_IMPL(virshAttachDiskSource,
               VIRSH_ATTACH_DISK_SOURCE_TYPE_LAST,
               "",
               "file",
-              "block");
+              "block",
+              "network");


 static bool
@@ -553,6 +571,10 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     const char *wwn = NULL;
     const char *targetbus = NULL;
     const char *alias = NULL;
+    const char *source_protocol = NULL;
+    const char *host_name = NULL;
+    const char *host_transport = NULL;
+    const char *host_socket = NULL;
     int ret;
     unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
     const char *stype = NULL;
@@ -562,6 +584,8 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     g_auto(virBuffer) diskChildBuf = VIR_BUFFER_INIT_CHILD(&buf);
     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
+    g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(&diskChildBuf);
+    g_auto(virBuffer) hostAttrBuf = VIR_BUFFER_INITIALIZER;
     g_autofree char *xml = NULL;
     struct stat st;
     bool current = vshCommandOptBool(cmd, "current");
@@ -575,6 +599,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)
@@ -594,7 +625,11 @@ 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)
         return false;

     if (stype &&
@@ -604,17 +639,24 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     }

     if (type == VIRSH_ATTACH_DISK_SOURCE_TYPE_NONE) {
-        if (STRNEQ_NULLABLE(driver, "file") &&
-            STRNEQ_NULLABLE(driver, "tap") &&
-            source &&
-            stat(source, &st) == 0 &&
-            S_ISBLK(st.st_mode)) {
+        if (source_protocol) {
+            type = VIRSH_ATTACH_DISK_SOURCE_TYPE_NETWORK;
+        } else  if (STRNEQ_NULLABLE(driver, "file") &&
+                    STRNEQ_NULLABLE(driver, "tap") &&
+                    source &&
+                    stat(source, &st) == 0 &&
+                    S_ISBLK(st.st_mode)) {
             type = VIRSH_ATTACH_DISK_SOURCE_TYPE_BLOCK;
         } else {
             type = VIRSH_ATTACH_DISK_SOURCE_TYPE_FILE;
         }
     }

+    if ((type == VIRSH_ATTACH_DISK_SOURCE_TYPE_NETWORK) != !!source_protocol) {
+        vshError(ctl, _("--source-protocol option requires --sourcetype network"));
+        return false;
+    }
+
     if (mode) {
         if (STRNEQ(mode, "readonly") && STRNEQ(mode, "shareable")) {
             vshError(ctl, _("No support for %s in command 'attach-disk'"),
@@ -648,11 +690,33 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         virBufferEscapeString(&sourceAttrBuf, " dev='%s'", source);
         break;

+    case VIRSH_ATTACH_DISK_SOURCE_TYPE_NETWORK:
+        virBufferEscapeString(&sourceAttrBuf, " protocol='%s'", source_protocol);
+        virBufferEscapeString(&sourceAttrBuf, " name='%s'", source);
+
+        virBufferEscapeString(&hostAttrBuf, " transport='%s'", host_transport);
+        virBufferEscapeString(&hostAttrBuf, " socket='%s'", host_socket);
+
+        if (host_name) {
+            g_autofree char *host_name_copy = g_strdup(host_name);
+            char *host_port = strchr(host_name_copy, ':');
+
+            if (host_port) {
+                *host_port = '\0';
+                host_port++;
+            }
+
+            virBufferEscapeString(&hostAttrBuf, " name='%s'", host_name_copy);
+            virBufferEscapeString(&hostAttrBuf, " port='%s'", host_port);
+        }
+        virXMLFormatElement(&sourceChildBuf, "host", &hostAttrBuf, NULL);
+        break;
+
     case VIRSH_ATTACH_DISK_SOURCE_TYPE_NONE:
     case VIRSH_ATTACH_DISK_SOURCE_TYPE_LAST:
         break;
     }
-    virXMLFormatElement(&diskChildBuf, "source", &sourceAttrBuf, NULL);
+    virXMLFormatElement(&diskChildBuf, "source", &sourceAttrBuf, &sourceChildBuf);

     virBufferAsprintf(&diskChildBuf, "<target dev='%s'", target);
     if (targetbus)
-- 
2.28.0




More information about the libvir-list mailing list