[PATCH 7/8] Re-wrote attach-disk to support multiple hosts

Ryan Gahagan rgahagan at cs.utexas.edu
Tue Nov 10 21:56:19 UTC 2020


Signed-off-by: Ryan Gahagan <rgahagan at cs.utexas.edu>
---
 tools/virsh-domain.c | 70 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index ae9a2b1101..64c7c454bd 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -578,6 +578,49 @@ static int str2DiskAddress(const char *str, struct DiskAddress *diskAddr)
     return -1;
 }
 
+static void attachDiskHostGen(virBufferPtr buf, const vshCmd *cmd)
+{
+    // Can be multiple hosts so we have to scan
+    // the cmd options to find all the host params
+    // <source tag in XML not yet closed
+    vshCmdOpt *candidate = cmd->opts;
+    char *host_name = NULL, *host_port = NULL;
+    int closeTag = 0;
+
+    while (candidate) {
+        // Iterate candidates to find each host-name
+        if (STREQ(candidate->def->name, "source-host-name")) {
+            // After the first host-name, we need to terminate
+            // the <host ... tag
+            // It's left open so socket and transport can be added later
+            if (closeTag)
+                virBufferAddLit(buf, "/>\n");
+            else
+                closeTag = 1;
+
+            host_name = candidate->data;
+            host_port = strchr(host_name, ':');
+
+            if (!host_port) {
+                // If port isn't provided, only print name
+                virBufferAsprintf(buf, "<host name='%s'", host_name);
+            } else {
+                // If port is provided, manipulate strings and print both
+                host_name[(int)(host_port - host_name)] = '\0';
+                virBufferAsprintf(buf, "<host name='%s' port='%s'", host_name, host_port + 1);
+            }
+        } else if (STREQ(candidate->def->name, "source-host-socket")) {
+            virBufferAsprintf(buf, " socket='%s'", candidate->data);
+        } else if (STREQ(candidate->def->name, "source-host-transport")) {
+            virBufferAsprintf(buf, " transport='%s'", candidate->data);
+        }
+
+        candidate = candidate->next;
+    }
+    // Close final <host tag
+    virBufferAddLit(buf, "/>\n");
+}
+
 static bool
 cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
 {
@@ -587,7 +630,7 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
                 *mode = NULL, *iothread = NULL, *cache = NULL,
                 *io = NULL, *serial = NULL, *straddr = NULL,
                 *wwn = NULL, *targetbus = NULL, *alias = NULL,
-                *host_transport = NULL, *host_port = NULL, *host_socket = NULL;
+                *host_transport = NULL, *host_name = NULL, *host_socket = NULL;
     struct DiskAddress diskAddr;
     bool isFile = false, functionReturn = false;
     int ret;
@@ -595,7 +638,6 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
     const char *stype = NULL;
     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
     char *xml = NULL;
-    char *host_name = NULL;
     struct stat st;
     bool current = vshCommandOptBool(cmd, "current");
     bool config = vshCommandOptBool(cmd, "config");
@@ -698,27 +740,25 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
         if (source_name)
             virBufferAsprintf(&buf, " name='%s'", source_name);
 
-        if (host_name || host_transport || host_socket) {
+        if (!(host_name || host_transport || host_socket)) {
+            // Close source if no host is provided
+            virBufferAddLit(&buf, "/>\n");
+        } else if (!host_name) {
+            // If no host name is provided but there is a host,
+            // we have a single host with params
             virBufferAddLit(&buf, ">\n<host");
 
-            if (host_name) {
-                host_port = strchr(host_name, ':');
-
-                if (!host_port) {
-                    virBufferAsprintf(&buf, " name='%s'", host_name);
-                } else {
-                    host_name[(int)(host_port - host_name)] = '\0';
-                    virBufferAsprintf(&buf, " name='%s' port='%s'", host_name, host_port + 1);
-                }
-            }
             if (host_transport)
                 virBufferAsprintf(&buf, " transport='%s'", host_transport);
             if (host_socket)
                 virBufferAsprintf(&buf, " socket='%s'", host_socket);
 
-            virBufferAddLit(&buf, " />\n</source>\n");
+            virBufferAddLit(&buf, "/>\n</source>\n");
         } else {
-            virBufferAddLit(&buf, " />\n");
+            // May have multiple hosts, use helper method
+            virBufferAddLit(&buf, ">\n");
+            attachDiskHostGen(&buf, cmd);
+            virBufferAddLit(&buf, "</source>\n");
         }
     }
 
-- 
2.29.0




More information about the libvir-list mailing list