[libvirt] [PATCH 02/22] virsh: Extract common code from cmdCPU{Compare, Baseline}

Jiri Denemark jdenemar at redhat.com
Wed May 23 12:35:01 UTC 2018


On Tue, May 22, 2018 at 17:33:14 -0400, Collin Walling wrote:
> On 05/16/2018 04:39 AM, Jiri Denemark wrote:
> > Both cpu-compare and cpu-baseline commands accept more that just CPU
> > definition XML(s). For users' convenience they are able to extract the
> > CPU definition(s) even from domain XML or capabilities XML. The main
> > differences between the two commands is in the number of CPU definitions
> > they expect: cpu-compare wants only one CPU definition while
> > cpu-baseline expects one or more CPUs.
> > 
> > The extracted code forms a new vshExtractCPUDefXML function.
> > 
> > Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> > ---
> >  tools/virsh-host.c | 160 +++++++++++++++++++++------------------------
> >  1 file changed, 75 insertions(+), 85 deletions(-)
> > 
> > diff --git a/tools/virsh-host.c b/tools/virsh-host.c
> > index 6d6e3cfc85..51497db385 100644
> > --- a/tools/virsh-host.c
> > +++ b/tools/virsh-host.c
> > @@ -1106,6 +1106,72 @@ cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
> >      return true;
> >  }
> >  
> > +
> > +/* Extracts the CPU definition XML strings from a file which may contain either
> > + *  - just the CPU definitions,
> > + *  - domain XMLs, or
> > + *  - capabilities XMLs.
> > + *
> > + * Returns NULL terminated string list.
> > + */
> > +static char **
> > +vshExtractCPUDefXMLs(vshControl *ctl,
> > +                     const char *xmlFile)
> > +{
> > +    char **cpus = NULL;
> > +    char *buffer = NULL;
> > +    char *xmlStr = NULL;
> > +    xmlDocPtr xml = NULL;
> > +    xmlXPathContextPtr ctxt = NULL;
> > +    xmlNodePtr *nodes = NULL;
> > +    size_t i;
> > +    int n;
> > +
> > +    if (virFileReadAll(xmlFile, VSH_MAX_XML_FILE, &buffer) < 0)
> > +        goto error;
> > +
> > +    if (virAsprintf(&xmlStr, "<container>%s</container>", buffer) < 0)
> > +        goto error;
> > +
> 
> Why wrap the xml in the <container> tags?

Because you can only have one root element in an XML document. Thus to
be able to parse a file with several root elements, we need to
encapsulate the content into a container.

> 
> > +    if (!(xml = virXMLParseStringCtxt(xmlStr, xmlFile, &ctxt)))
> > +        goto error;
> > +
> > +    n = virXPathNodeSet("/container/cpu|"
> > +                        "/container/domain/cpu|"
> > +                        "/container/capabilities/host/cpu",
> > +                        ctxt, &nodes);
> > +    if (n < 0)
> > +        goto error;
> > +
> > +    if (n == 0) {
> > +        vshError(ctl, _("File '%s' does not contain any <cpu> element or "
> > +                        "valid domain or capabilities XML"), xmlFile);
> > +        goto error;
> > +    }
> > +
> > +    cpus = vshCalloc(ctl, n + 1, sizeof(const char *));
> > +
> > +    for (i = 0; i < n; i++) {
> > +        if (!(cpus[i] = virXMLNodeToString(xml, nodes[i]))) {
> > +            vshSaveLibvirtError();
> > +            goto error;
> > +        }
> > +    }
> > +
> > + cleanup:
> > +    VIR_FREE(buffer);
> > +    VIR_FREE(xmlStr);
> > +    xmlFreeDoc(xml);
> > +    xmlXPathFreeContext(ctxt);
> > +    VIR_FREE(nodes);
> > +    return cpus;
> > +
> > + error:
> > +    virStringListFree(cpus);
> > +    goto cleanup;
> > +}
> > +
> > +
> >  /*
> >   * "cpu-compare" command
> >   */
> > @@ -1133,13 +1199,9 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd)
> >  {
> >      const char *from = NULL;
> >      bool ret = false;
> > -    char *buffer;
> >      int result;
> > -    char *snippet = NULL;
> > +    char **cpus = NULL;
> >      unsigned int flags = 0;
> > -    xmlDocPtr xml = NULL;
> > -    xmlXPathContextPtr ctxt = NULL;
> > -    xmlNodePtr node;
> >      virshControlPtr priv = ctl->privData;
> >  
> >      if (vshCommandOptBool(cmd, "error"))
> > @@ -1148,27 +1210,10 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd)
> >      if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
> >          return false;
> >  
> > -    if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
> > +    if (!(cpus = vshExtractCPUDefXMLs(ctl, from)))
> >          return false;
> >  
> > -    /* try to extract the CPU element from as it would appear in a domain XML*/
> > -    if (!(xml = virXMLParseStringCtxt(buffer, from, &ctxt)))
> > -        goto cleanup;
> > -
> > -    if ((node = virXPathNode("/cpu|"
> > -                             "/domain/cpu|"
> > -                              "/capabilities/host/cpu", ctxt))) {
> > -        if (!(snippet = virXMLNodeToString(xml, node))) {
> > -            vshSaveLibvirtError();
> > -            goto cleanup;
> > -        }
> > -    } else {
> > -        vshError(ctl, _("File '%s' does not contain a <cpu> element or is not "
> > -                        "a valid domain or capabilities XML"), from);
> > -        goto cleanup;
> > -    }
> > -
> > -    result = virConnectCompareCPU(priv->conn, snippet, flags);
> > +    result = virConnectCompareCPU(priv->conn, cpus[0], flags);
> 
> I wonder if it's worth commenting here or adding to the cpu compare docs that comparison only
> compares the host CPU with the _first_ cpu found in the XML file?

The cpu-compare command is already documented this way. It accepts a CPU
definition and compares it to host CPU, while cpu-baseline accepts a set
of CPU definitions.

Jirka




More information about the libvir-list mailing list