
From: Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com> This patch adds a new virsh command "confcpu", that allows to show and modify mode attribute and match attribute of a cpu node of a domain XML. Modification is supported for only persistent configuration. Examples of usage: change cpu mode to "host-passthrough" virsh # confcpu <domain> --mode host-passthrough change match attribute to "minimum" virsh # confcpu <domain> --match minimum reset all cpu configuration under a cpu node of a domain XML virsh # confcpu <domain> --reset show cpu node attirbutes of a running guest virsh # confcpu <domain> --live Signed-off-by: Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com> --- tools/virsh-domain.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 24 +++++++ 2 files changed, 210 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index f3da1d5..913a1b4 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5526,6 +5526,191 @@ failed_stats: } /* + * "confcpu" command + */ +static const vshCmdInfo info_confcpu[] = { + {"help", N_("show or modify domain cpu node attributes")}, + {"desc", N_("Show or modify cpu node attributes of a domain XML")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_confcpu[] = { + {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, + {"mode", VSH_OT_DATA, 0, + N_("mode attribute, one of custom, host-model and host-passthrough")}, + {"match", VSH_OT_DATA, 0, + N_("match attribute, one of minimum, exact and strict")}, + {"reset", VSH_OT_BOOL, 0, + N_("remove a cpu node including child nodes and redefine the domain XML")}, + {"live", VSH_OT_BOOL, 0, N_("affect running state")}, + {"config", VSH_OT_BOOL, 0, N_("affect persistent configuration")}, + {"current", VSH_OT_BOOL, 0, N_("affect current state configuration")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdConfCPU(vshControl *ctl, const vshCmd *cmd) +{ + virDomainPtr dom = NULL; + virDomainPtr dom_edited = NULL; + const char *newMode = NULL; + char *curMode = NULL; + const char *newMatch = NULL; + char *curMatch = NULL; + bool reset = vshCommandOptBool(cmd, "reset"); + bool config = vshCommandOptBool(cmd, "config"); + bool live = vshCommandOptBool(cmd, "live"); + bool current = vshCommandOptBool(cmd, "current"); + int running = -1; + bool modify = false; /* Modification mode */ + unsigned int flags = 0; + bool ret = false; + char *doc = NULL; + char *doc_edited = NULL; + xmlXPathContextPtr ctxt = NULL; + xmlDocPtr xml = NULL; + xmlNodePtr domNode = NULL; + xmlNodePtr cpuNode = NULL; + + if (current + config + live > 1) { + vshError(ctl, "%s", + _("--config, --live, and --current are mutually exclusive")); + return false; + } + + if (vshCommandOptString(cmd, "mode", &newMode) < 0 || + vshCommandOptString(cmd, "match", &newMatch) < 0) { + vshError(ctl, "%s", _("missing argument")); + return false; + } + + modify = reset || newMode || newMatch; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if ((running = virDomainIsActive(dom)) < 0) { + vshError(ctl, "%s", _("Coud not check domain state.")); + goto cleanup; + } + + if (live && !running) { + vshError(ctl, "%s", _("--live affects only a running domain")); + goto cleanup; + } + if (modify) { + if (live || (current && running)) { + vshError(ctl, "%s", _("Cannot modify a running guest.")); + goto cleanup; + } + } + /* If modification is needed, get persistent conf regardless of + other flags because modification of cpu node is supported + for only persistent config. */ + if (config || (current && !running) || modify) + flags = VIR_DOMAIN_XML_INACTIVE; + + /* get domain XML */ + if (!(doc = virDomainGetXMLDesc(dom, flags))) { + vshError(ctl, "%s", _("Could not get domain XML.")); + goto cleanup; + } + + if (!(xml = virXMLParseStringCtxt(doc, _("(domain_definition)"), &ctxt))) { + vshError(ctl, "%s", _("Could not parse domain XML.")); + goto cleanup; + } + + /* Query mode: show cpu node attributes then exit. */ + if (!modify) { + curMode = virXPathString("string(./cpu[1]/@mode)", ctxt); + curMatch = virXPathString("string(./cpu[1]/@match)", ctxt); + vshPrint(ctl, "mode : %s\n", curMode? curMode : ""); + vshPrint(ctl, "match : %s\n", curMatch? curMatch : ""); + + ret = true; + goto cleanup; + } + + /* Modification mode: modify cpu node. */ + + if (reset) { + /* remove cpu node */ + if ((cpuNode = virXPathNode("./cpu[1]", ctxt))) { + xmlUnlinkNode(cpuNode); + xmlFreeNode(cpuNode); + cpuNode = NULL; + } + } + + if (newMode || newMatch) { + /* get cpu node */ + if (!(cpuNode = virXPathNode("./cpu[1]", ctxt))) { + /* get domain node to create a new cpu node */ + if (!(domNode = virXPathNode("/domain[1]", ctxt))) { + vshError(ctl, "%s", _("Could not find domain node.")); + goto cleanup; + } + /* create a new cpu node */ + if (!(cpuNode = xmlNewChild(domNode, + NULL, + (const xmlChar*)"cpu", + NULL))) { + vshError(ctl, "%s", _("Could not create new cpu node.")); + goto cleanup; + } + } + } + + if (newMode) { + /* modify mode attribute of the cpu node*/ + if (!xmlSetProp(cpuNode, + (const xmlChar*)"mode", + (const xmlChar*)newMode)) { + vshError(ctl, "%s", _("Could not modify mode attribute.")); + goto cleanup; + } + } + + if (newMatch) { + /* modify match attribute of the cpu node*/ + if (!xmlSetProp(cpuNode, + (const xmlChar*)"match", + (const xmlChar*)newMatch)) { + vshError(ctl, "%s", _("Could not modify match attribute.")); + goto cleanup; + } + } + + /* get modified domain XML */ + xmlDocDumpMemory(xml, (xmlChar**)&doc_edited, NULL); + if (!doc_edited) { + vshError(ctl, "%s", _("Could not dump edited XML doc.")); + goto cleanup; + } + + /* update domain XML */ + if (!(dom_edited = virDomainDefineXML(ctl->conn, doc_edited))) { + vshError(ctl, "%s", _("Failed to update cpu node.")); + goto cleanup; + } + virDomainFree(dom_edited); + + vshPrint(ctl, "%s", _("Configuration redefined successfully.\n")); + ret = true; + + cleanup: + VIR_FREE(doc_edited); + VIR_FREE(curMatch); + VIR_FREE(curMode); + xmlFreeDoc(xml); + xmlXPathFreeContext(ctxt); + VIR_FREE(doc); + virDomainFree(dom); + return ret; +} + +/* * "create" command */ static const vshCmdInfo info_create[] = { @@ -8507,6 +8692,7 @@ const vshCmdDef domManagementCmds[] = { {"blockpull", cmdBlockPull, opts_block_pull, info_block_pull, 0}, {"blockresize", cmdBlockResize, opts_block_resize, info_block_resize, 0}, {"change-media", cmdChangeMedia, opts_change_media, info_change_media, 0}, + {"confcpu", cmdConfCPU, opts_confcpu, info_confcpu, 0}, #ifndef WIN32 {"console", cmdConsole, opts_console, info_console, 0}, #endif diff --git a/tools/virsh.pod b/tools/virsh.pod index 3687a4d..6374993 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -538,6 +538,30 @@ the server has to ensure exclusive access to console devices. Optionally the I<--force> flag may be specified, requesting to disconnect any existing sessions, such as in a case of a broken connection. +=item B<confcpu> I<domain> [I<--mode> I<mode>] [I<--match> I<match>] [I<--reset>] [[I<--current>] | [I<--live>] | [I<--config>]] + +Get or set cpu node attributes of a domain XML. +I<mode> is mode attribute of a cpu node, one of "custom", "host-model" +and "host-passthrough". If I<mode> is specified, mode attribute is modified. +I<match> is match attribute of a cpu node, one of "minimum", "exact", +and "strict". If I<match> is specified, match attribute is modified. +If I<--reset> is specified, a cpu node is removed including the child +nodes, so that the cpu configuration under the cpu node of the domain XML +will be default. +If I<mode> or I<match> is specified with I<--reset>, these attributes +are added to a new cpu node after I<--reset> behavior. + +These modifications don't affect a running guest state but affects a +persistent configuration. + +If neither of I<mode>, I<match> and I<--reset> are specified, attributes +of a cpu node are displayed instead of being modified. + +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +These three flags are mutually exclusive. + =item B<create> I<FILE> [I<--console>] [I<--paused>] [I<--autodestroy>] Create a domain from an XML <file>. An easy way to create the XML -- 1.7.11.7