[libvirt] [PATCH 2/2] virsh: Add a new command "confcpu-model"

Ken ICHIKAWA ichikawa.ken at jp.fujitsu.com
Tue Dec 25 08:52:15 UTC 2012


From: Ken ICHIKAWA <ichikawa.ken at jp.fujitsu.com>

This patch adds a new virsh command "confcpu-model", that allows to show
and modify cpu model, fallback attribute and vendor_id attribute of a
model node of a domain XML. If cpu model is specified, mode attribute
of the cpu node will be "custom" automatically.
Modification is supported for only persistent configuration.

Examples of usage:
   change cpu model to "core2duo" and fallback attribute to "forbid"
     virsh # confcpu-model <domain> --model core2duo --fallback forbid

   reset all cpu model configuration under a model node of a domain XML
     virsh # confcpu-model <domain> --reset

   show model node information of a running guest
     virsh # confcpu-model <domain> --live

Signed-off-by: Ken ICHIKAWA <ichikawa.ken at jp.fujitsu.com>
---
  tools/virsh-domain.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++
  tools/virsh.pod      |  27 +++++++
  2 files changed, 252 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 913a1b4..762d50b 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -5711,6 +5711,230 @@ cmdConfCPU(vshControl *ctl, const vshCmd *cmd)
  }
  
  /*
+ * "confcpu-model" command
+ */
+static const vshCmdInfo info_confcpu_model[] = {
+    {"help", N_("show or modify domain cpu model")},
+    {"desc", N_("Show or modify model node information of a domain XML")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_confcpu_model[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"model", VSH_OT_DATA, 0, N_("cpu model")},
+    {"fallback", VSH_OT_DATA, 0,
+     N_("fallback attribute, one of allow or forbid")},
+    {"vendor_id", VSH_OT_DATA, 0,
+     N_("vendor_id attribute, must be exactly 12 characters long")},
+    {"reset", VSH_OT_BOOL, 0,
+     N_("remove a model node 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
+cmdConfCPUModel(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom = NULL;
+    virDomainPtr dom_edited = NULL;
+    const char *newModel = NULL;
+    char *curModel = NULL;
+    char *escedModel = NULL;
+    const char *newFallback = NULL;
+    char *curFallback = NULL;
+    const char *newVendorID = NULL;
+    char *curVendorID =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;
+    xmlNodePtr modelNode = NULL;
+
+    if (current + config + live > 1) {
+        vshError(ctl, "%s",
+                 _("--config, --live, and --current are mutually exclusive"));
+        return false;
+    }
+
+    if (vshCommandOptString(cmd, "model", &newModel) < 0 ||
+        vshCommandOptString(cmd, "fallback", &newFallback) < 0 ||
+        vshCommandOptString(cmd, "vendor_id", &newVendorID) < 0) {
+        vshError(ctl, "%s", _("missing argument"));
+        return false;
+    }
+
+    modify = reset || newModel || newFallback || newVendorID;
+
+    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 model 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 model node info then exit. */
+    if (!modify) {
+        curModel = virXPathString("string(./cpu[1]/model[1])", ctxt);
+        curFallback = virXPathString("string(./cpu[1]/model[1]/@fallback)",
+                                     ctxt);
+        curVendorID = virXPathString("string(./cpu[1]/model[1]/@vendor_id)",
+                                      ctxt);
+
+        vshPrint(ctl, "model     : %s\n", curModel? curModel : "");
+        vshPrint(ctl, "fallback  : %s\n", curFallback? curFallback : "");
+        vshPrint(ctl, "vendor_id : %s\n", curVendorID? curVendorID : "");
+
+        ret = true;
+        goto cleanup;
+    }
+
+    /* Modification mode: modify model node. */
+
+    if (reset) {
+        /* remove model node */
+        if ((modelNode = virXPathNode("./cpu[1]/model[1]", ctxt))) {
+            xmlUnlinkNode(modelNode);
+            xmlFreeNode(modelNode);
+            modelNode = NULL;
+        }
+    }
+
+    if (newModel || newFallback || newVendorID) {
+        /* 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;
+            }
+        }
+        /* get model node */
+        if (!(modelNode = virXPathNode("./cpu[1]/model[1]", ctxt))) {
+            /* create a new model node */
+            if (!(modelNode = xmlNewChild(cpuNode,
+                                          NULL,
+                                          (const xmlChar*)"model",
+                                          NULL))) {
+                vshError(ctl, "%s", _("Could not create new model node."));
+                goto cleanup;
+            }
+        }
+    }
+
+    if (newModel) {
+        /* modify mode attribute of the cpu node*/
+        if (!xmlSetProp(cpuNode,
+                        (const xmlChar*)"mode",
+                        (const xmlChar*)"custom")) {
+            vshError(ctl, "%s", _("Could not modify mode attribute."));
+            goto cleanup;
+        }
+
+        escedModel = (char*)xmlEncodeEntitiesReentrant(NULL,
+                                                       (const xmlChar*)newModel);
+        /* modify model node content */
+        xmlNodeSetContent(modelNode, (const xmlChar*)escedModel);
+    }
+
+    if (newFallback) {
+        /* modify fallback attribute of the model node */
+        if (!xmlSetProp(modelNode,
+                        (const xmlChar*)"fallback",
+                        (const xmlChar*)newFallback)) {
+            vshError(ctl, "%s", _("Could not modify fallback attribute."));
+            goto cleanup;
+        }
+    }
+
+    if (newVendorID) {
+        /* modify vendor_id attribute of the model node */
+        if (!xmlSetProp(modelNode,
+                        (const xmlChar*)"vendor_id",
+                        (const xmlChar*)newVendorID)) {
+            vshError(ctl, "%s", _("Could not modify vendor_id 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 model node."));
+        goto cleanup;
+    }
+    virDomainFree(dom_edited);
+
+    vshPrint(ctl, "%s", _("Configuration redefined successfully.\n"));
+    ret = true;
+
+ cleanup:
+    VIR_FREE(doc_edited);
+    VIR_FREE(escedModel);
+    VIR_FREE(curVendorID);
+    VIR_FREE(curFallback);
+    VIR_FREE(curModel);
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(ctxt);
+    VIR_FREE(doc);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
   * "create" command
   */
  static const vshCmdInfo info_create[] = {
@@ -8693,6 +8917,7 @@ const vshCmdDef domManagementCmds[] = {
      {"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},
+    {"confcpu-model", cmdConfCPUModel, opts_confcpu_model, info_confcpu_model, 0},
  #ifndef WIN32
      {"console", cmdConsole, opts_console, info_console, 0},
  #endif
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 6374993..accf975 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -562,6 +562,33 @@ 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<confcpu-mode> I<domain> [I<--model> I<model>] [I<--fallback> I<fallback>] [I<--vendor_id> I<vendor_id>] [I<--reset>] [[I<--current>] | [I<--live>] | [I<--config>]]
+
+Get or set a model node of a domain XML.
+I<model> is cpu model name. If I<model> is specified, content of a model
+node is modified and mode attribute of the cpu node is specified as
+"custom" automatically.
+I<fallback> is fallback attribute of a model node, one of "allow" and
+"forbid". If I<fallback> is specified, fallback attribute is modified.
+I<vendor_id> is vendor_id attribute of a model node, must be exactly
+12 characters long. If I<vendor_id> is specified, vendor_id attribute
+is modified.
+If I<--reset> is specified, a model node is removed so that the cpu model
+configuration under the model node of the domain XML will be default.
+If I<model>, I<fallback> or I<vendor_id> is specified with I<--reset>,
+these are added to a new model 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, information
+about a model node is 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





More information about the libvir-list mailing list