One could use it to eject, insert, or update media of the CDROM or floppy drive. See the documents for more details. --- tools/virsh.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 33 ++++++++++++- 2 files changed, 172 insertions(+), 3 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index eeb2426..11aa042 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -14610,6 +14610,147 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) } /* + * "change-media" command + */ +static const vshCmdInfo info_change_media[] = { + {"help", N_("Change media of CD or floppy drive")}, + {"desc", N_("Change media of CD or floppy drive.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_change_media[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"path", VSH_OT_DATA, VSH_OFLAG_REQ, N_("Fully-qualified path or " + "target of disk device")}, + {"source", VSH_OT_DATA, 0, N_("source of the media")}, + {"eject", VSH_OT_BOOL, 0, N_("Eject the media")}, + {"insert", VSH_OT_BOOL, 0, N_("Insert the media")}, + {"update", VSH_OT_BOOL, 0, N_("Update the media")}, + {"current", VSH_OT_BOOL, 0, N_("can be either or both of --live and --config, " + "depends on implementation of hypervisor driver")}, + {"live", VSH_OT_BOOL, 0, N_("alter live configuration of running domain")}, + {"config", VSH_OT_BOOL, 0, N_("alter persistent configuration, effect observed on next boot")}, + {"force", VSH_OT_BOOL, 0, N_("force media insertion")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdChangeMedia(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + const char *source = NULL; + const char *path = NULL; + const char *doc = NULL; + xmlNodePtr disk_node = NULL; + const char *disk_xml = NULL; + int flags = 0; + int config, live, current, force = 0; + int eject, insert, update = 0; + bool ret = false; + int prepare_type = 0; + const char *action = NULL; + + config = vshCommandOptBool(cmd, "config"); + live = vshCommandOptBool(cmd, "live"); + current = vshCommandOptBool(cmd, "current"); + force = vshCommandOptBool(cmd, "force"); + eject = vshCommandOptBool(cmd, "eject"); + insert = vshCommandOptBool(cmd, "insert"); + update = vshCommandOptBool(cmd, "update"); + + if ((eject && insert) || + (insert && update) || + (eject && update)) { + vshError(ctl, "%s", _("--eject, --insert, and --update must be specified " + "exclusively.")); + return false; + } + + if (eject) { + prepare_type = VSH_PREPARE_DISK_XML_EJECT; + action = "eject"; + } + + if (insert) { + prepare_type = VSH_PREPARE_DISK_XML_INSERT; + action = "insert"; + } + + if (update) { + prepare_type = VSH_PREPARE_DISK_XML_UPDATE; + action = "update"; + } + + /* Defaults to "update" */ + if (!eject && !insert && !update) { + prepare_type = VSH_PREPARE_DISK_XML_UPDATE; + action = "update"; + } + + if (current) { + if (live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return false; + } + flags = VIR_DOMAIN_AFFECT_CURRENT; + } else { + if (config) + flags |= VIR_DOMAIN_AFFECT_CONFIG; + if (live) + flags |= VIR_DOMAIN_AFFECT_LIVE; + } + + if (force) + flags |= VIR_DOMAIN_DEVICE_MODIFY_FORCE; + + if (!vshConnectionUsability(ctl, ctl->conn)) + goto cleanup; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + goto cleanup; + + if (vshCommandOptString(cmd, "path", &path) <= 0) + goto cleanup; + + if (vshCommandOptString(cmd, "source", &source) < 0) + goto cleanup; + + if (insert && !source) { + vshError(ctl, "%s", _("No disk source specified for inserting")); + goto cleanup; + } + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) + doc = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE); + else + doc = virDomainGetXMLDesc(dom, 0); + if (!doc) + goto cleanup; + + if (!(disk_node = vshFindDisk(doc, path, VSH_FIND_DISK_CHANGEABLE))) + goto cleanup; + + if (!(disk_xml = vshPrepareDiskXML(disk_node, source, path, prepare_type))) + goto cleanup; + + if (virDomainUpdateDeviceFlags(dom, disk_xml, flags) != 0) { + vshError(ctl, _("Failed to %s media"), action); + goto cleanup; + } + + vshPrint(ctl, _("succeeded to %s media\n"), action); + ret = true; + +cleanup: + VIR_FREE(doc); + xmlFreeNode(disk_node); + VIR_FREE(disk_xml); + if (dom) + virDomainFree(dom); + return ret; +} + +/* * "cpu-compare" command */ static const vshCmdInfo info_cpu_compare[] = { @@ -16705,6 +16846,7 @@ static const vshCmdDef domManagementCmds[] = { #ifndef WIN32 {"console", cmdConsole, opts_console, info_console, 0}, #endif + {"change-media", cmdChangeMedia, opts_change_media, info_change_media, 0}, {"cpu-baseline", cmdCPUBaseline, opts_cpu_baseline, info_cpu_baseline, 0}, {"cpu-compare", cmdCPUCompare, opts_cpu_compare, info_cpu_compare, 0}, {"create", cmdCreate, opts_create, info_create, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 2956c81..162d046 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1490,9 +1490,10 @@ from the domain. =item B<detach-interface> I<domain-id> I<type> [I<--mac mac>] Detach a network interface from a domain. -I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device. -It is recommended to use the I<mac> option to distinguish between the interfaces -if more than one are present on the domain. +I<type> can be either I<network> to indicate a physical network device or +I<bridge> to indicate a bridge to a device. It is recommended to use the +I<mac> option to distinguish between the interfaces if more than one are +present on the domain. =item B<update-device> I<domain-id> I<file> [I<--persistent>] [I<--force>] @@ -1503,6 +1504,32 @@ option can be used to force device update, e.g., to eject a CD-ROM even if it is locked/mounted in the domain. See the documentation to learn about libvirt XML format for a device. +=item B<change-media> I<domain-id> I<path> [I<--eject>] [I<--insert>] +[I<--update>] [I<source>] [I<--force>] [I<--current>] [I<--live>] [I<--config>] + +Change media of CDROM or floppy drive. I<path> can be the fully-qualified path +or the unique target name (<target dev='hdc'>) of the disk device. I<source> +specifies the path of the media to be inserted or updated. + +I<--eject> indicates the media will be ejected. +I<--insert> indicates the media will be inserted. I<source> must be specified. +If the device has source (e.g. <source file='media'>), and I<source> is not +specified, I<--update> is equal to I<--eject>. If the device has no source, +and I<source> is specified, I<--update> is equal to I<--insert>. If the device +has source, and I<source> is specified, I<--update> behaves like combination +of I<--eject> and I<--insert>. +If none of I<--eject>, I<--insert>, and I<--update> is specified, I<--update> +is used by default. +The I<--force> option can be used to force media changing. +If I<--live> is specified, alter live configuration of running guest. +If I<--config> is specified, alter persistent configuration, effect observed +on next boot. +I<--current> can be either or both of I<live> and I<config>, depends on +the hypervisor's implementation. +Both I<--live> and I<--config> flags may be given, but I<--current> is +exclusive. If no flag is specified, behavior is different depending +on hypervisor. + =back =head1 NODEDEV COMMANDS -- 1.7.7.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list