Implement an idea originally requested 22 Mar 2010.
* tools/virsh.c (cmdChangeDisk): New command, providing
convenience wrapper around update-device.
(commands): List it.
* tools/virsh.pod (change-disk): Document it.
(attach-disk): Update cross-reference.
---
tools/virsh.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 13 +++++-
2 files changed, 124 insertions(+), 2 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index fab4b74..ba130bf 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -7646,6 +7646,118 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
}
/*
+ * "change-disk" command
+ */
+static const vshCmdInfo info_change_disk[] = {
+ {"help", N_("change disk device")},
+ {"desc", N_("Update attributes of existing disk device.")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_change_disk[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or
uuid")},
+ {"source", VSH_OT_DATA, VSH_OFLAG_REQ, N_("source of disk
device")},
+ {"target", VSH_OT_DATA, VSH_OFLAG_REQ, N_("target of disk
device")},
+ {"driver", VSH_OT_STRING, 0, N_("driver of disk device")},
+ {"subdriver", VSH_OT_STRING, 0, N_("subdriver of disk device")},
+ {"type", VSH_OT_STRING, 0, N_("target device type")},
+ {"mode", VSH_OT_STRING, 0, N_("mode of device reading and
writing")},
+ {"persistent", VSH_OT_BOOL, 0, N_("persist disk attachment")},
+ {NULL, 0, 0, NULL}
+};
+
+static int
+cmdChangeDisk(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ char *source, *target, *driver, *subdriver, *type, *mode;
+ int isFile = 0, ret = FALSE;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *xml;
+ unsigned int flags;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ goto cleanup;
+
+ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
+ goto cleanup;
+
+ if (!(source = vshCommandOptString(cmd, "source", NULL)))
+ goto cleanup;
+
+ if (!(target = vshCommandOptString(cmd, "target", NULL)))
+ goto cleanup;
+
+ driver = vshCommandOptString(cmd, "driver", NULL);
+ subdriver = vshCommandOptString(cmd, "subdriver", NULL);
+ type = vshCommandOptString(cmd, "type", NULL);
+ mode = vshCommandOptString(cmd, "mode", NULL);
+
+ if (driver) {
+ if (STREQ(driver, "file") || STREQ(driver, "tap")) {
+ isFile = 1;
+ } else if (STRNEQ(driver, "phy")) {
+ vshError(ctl, _("No support for %s in command
'change-disk'"),
+ driver);
+ goto cleanup;
+ }
+ }
+
+ if (mode) {
+ if (STRNEQ(mode, "readonly") && STRNEQ(mode,
"shareable")) {
+ vshError(ctl, _("No support for %s in command
'attach-disk'"),
+ mode);
+ goto cleanup;
+ }
+ }
+
+ /* Make XML of disk */
+ virBufferVSprintf(&buf, " <disk type='%s'", isFile ?
"file" : "block");
+ if (type)
+ virBufferVSprintf(&buf, " device='%s'", type);
+ virBufferVSprintf(&buf, ">\n"
+ " <driver name='%s'", driver ? driver :
"phy");
+ if (subdriver)
+ virBufferVSprintf(&buf, " type='%s'", subdriver);
+ virBufferVSprintf(&buf, "/>\n"
+ " <source %s='%s'/>\n", isFile ?
"file" : "dev",
+ source);
+ virBufferVSprintf(&buf, "<target dev='%s'/>\n", target);
+ if (mode != NULL)
+ virBufferVSprintf(&buf, " <%s/>\n", mode);
+ virBufferAddLit(&buf, " </disk>\n");
+
+ if ((xml = virBufferContentAndReset(&buf)) == NULL) {
+ vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
+ return FALSE;
+ }
+
+ if (vshCommandOptBool(cmd, "persistent")) {
+ flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
+ if (virDomainIsActive(dom) == 1)
+ flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
+ } else {
+ flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
+ }
+ ret = virDomainUpdateDeviceFlags(dom, xml, flags);
+ VIR_FREE(xml);
+
+ if (ret != 0) {
+ vshError(ctl, "%s", _("Failed to change disk"));
+ ret = FALSE;
+ } else {
+ vshPrint(ctl, "%s", _("Disk changed successfully\n"));
+ ret = TRUE;
+ }
+
+ cleanup:
+ if (dom)
+ virDomainFree(dom);
+ virBufferFreeAndReset(&buf);
+ return ret;
+}
+
+/*
* "detach-disk" command
*/
static const vshCmdInfo info_detach_disk[] = {
@@ -8758,6 +8870,7 @@ static const vshCmdDef commands[] = {
#ifndef WIN32
{"cd", cmdCd, opts_cd, info_cd},
#endif
+ {"change-disk", cmdChangeDisk, opts_change_disk, info_change_disk},
{"connect", cmdConnect, opts_connect, info_connect},
#ifndef WIN32
{"console", cmdConsole, opts_console, info_console},
diff --git a/tools/virsh.pod b/tools/virsh.pod
index b195b67..ca6b1c6 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -535,8 +535,8 @@ I<source> and I<target> are paths for the files and
devices.
I<driver> can be I<file>, I<tap> or I<phy> depending on the kind
of access.
I<type> can indicate I<cdrom> or I<floppy> as alternative to the disk
default,
although this use only replaces the media within the existing virtual cdrom or
-floppy device; consider using B<update-device> for this usage instead.
-I<mode> can specify the two specific mode I<readonly> or I<shareable>.
+floppy device; consider using B<change-disk> for this usage instead.
+I<mode> can specify the two specific modes I<readonly> or
I<shareable>.
=item B<attach-interface> I<domain-id> I<type> I<source> optional
I<--target target> I<--mac mac> I<--script script>
@@ -548,6 +548,15 @@ I<mac> allows to specify the MAC address of the network
interface.
I<script> allows to specify a path to a script handling a bridge instead of
the default one.
+=item B<change-disk> I<domain-id> I<source> I<target> optional
I<--driver driver> I<--subdriver subdriver> I<--type type> I<--mode
mode>
+
+Change an existing disk device of the domain, such as hot-plugging a disk
+or changing the media in a cdrom.
+I<source> and I<target> are paths for the files and devices.
+I<driver> can be I<file>, I<tap> or I<phy> depending on the kind
of access.
+I<type> can indicate I<cdrom> or I<floppy> as alternative to the disk
default.
+I<mode> can specify the two specific modes I<readonly> or
I<shareable>.
+
=item B<detach-device> I<domain-id> I<FILE>
Detach a device from the domain, takes the same kind of XML descriptions
--
1.7.0.1