Signed-off-by: Ryan Gahagan <rgahagan@xxxxxxxxxxxxx> --- 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