[Libvirt-cim] [PATCH 3/4] libxkutil: Provide easy access to the libvirt capabilities

John Ferlan jferlan at redhat.com
Fri Aug 23 20:20:17 UTC 2013


On 08/15/2013 10:48 AM, Viktor Mihajlovski wrote:
> From: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> 
> Introspecting the libvirt capabilities and creating an internal capabilities
> data structure. Methods are provided for retrieving default values regarding
> architecture, machine and emulator for easy of use in the provider code.
> 
> Further, xml_parse_test was extendend to display hypervisor capabilities
> and defaults.
> 
> Signed-off-by: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
> ---
>  libxkutil/Makefile.am          |    2 +
>  libxkutil/capability_parsing.c |  462 ++++++++++++++++++++++++++++++++++++++++
>  libxkutil/capability_parsing.h |   93 ++++++++
>  libxkutil/xml_parse_test.c     |  134 +++++++++++-
>  4 files changed, 688 insertions(+), 3 deletions(-)
>  create mode 100644 libxkutil/capability_parsing.c
>  create mode 100644 libxkutil/capability_parsing.h
> 

This seems to be missing something as my build fails (Fedora 19):

  CC       xml_parse_test.o
  CCLD     xml_parse_test
xml_parse_test.o: In function `capinfo_for_dom':
/path/to/libxkutil/xml_parse_test.c:263: undefined reference to `get_capabilities'
xml_parse_test.o: In function `main':
/path/to/libxkutil/xml_parse_test.c:431: undefined reference to `get_default_arch'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:433: undefined reference to `get_default_machine'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:435: undefined reference to `get_default_emulator'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:437: undefined reference to `get_default_machine'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:439: undefined reference to `get_default_emulator'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:444: undefined reference to `findDomainInfo'
/path/to/libvirt-cim.coverity/libxkutil/xml_parse_test.c:449: undefined reference to `findDomainInfo'
collect2: error: ld returned 1 exit status
make[2]: *** [xml_parse_test] Error 1
make[2]: Leaving directory `/path/to/libxkutil'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/path/to'
make: *** [all] Error 2


I did not dig deeper into the code

John
> diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
> index 8d436ad..dd7be55 100644
> --- a/libxkutil/Makefile.am
> +++ b/libxkutil/Makefile.am
> @@ -7,6 +7,7 @@ noinst_HEADERS = \
>  	cs_util.h \
>  	misc_util.h \
>  	device_parsing.h \
> +	capability_parsing.h \
>  	xmlgen.h \
>  	infostore.h \
>  	pool_parsing.h \
> @@ -20,6 +21,7 @@ libxkutil_la_SOURCES = \
>  	cs_util_instance.c \
>  	misc_util.c \
>  	device_parsing.c \
> +	capability_parsing.c \
>  	xmlgen.c \
>  	infostore.c \
>  	pool_parsing.c \
> diff --git a/libxkutil/capability_parsing.c b/libxkutil/capability_parsing.c
> new file mode 100644
> index 0000000..2185584
> --- /dev/null
> +++ b/libxkutil/capability_parsing.c
> @@ -0,0 +1,462 @@
> +/*
> + * Copyright IBM Corp. 2013
> + *
> + * Authors:
> + *  Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
> + */
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +#include <sys/stat.h>
> +#include <stdint.h>
> +
> +#include <libcmpiutil/libcmpiutil.h>
> +#include <libvirt/libvirt.h>
> +#include <libxml/xpath.h>
> +#include <libxml/parser.h>
> +#include <libxml/tree.h>
> +
> +#include "misc_util.h"
> +#include "capability_parsing.h"
> +#include "xmlgen.h"
> +#include "../src/svpc_types.h"
> +
> +static void cleanup_cap_machine(struct cap_machine *machine)
> +{
> +        if (machine == NULL)
> +                return;
> +        free(machine->name);
> +        free(machine->canonical_name);
> +}
> +
> +void cleanup_cap_domain_info(struct cap_domain_info *cgdi)
> +{
> +        int i;
> +        if (cgdi == NULL)
> +                return;
> +        free(cgdi->emulator);
> +        free(cgdi->loader);
> +        for (i = 0; i < cgdi->num_machines; i++)
> +                cleanup_cap_machine(&cgdi->machines[i]);
> +        free(cgdi->machines);
> +}
> +
> +static void cleanup_cap_domain(struct cap_domain *cgd)
> +{
> +        if (cgd == NULL)
> +                return;
> +        free(cgd->typestr);
> +        cleanup_cap_domain_info(&cgd->guest_domain_info);
> +}
> +
> +static void cleanup_cap_arch(struct cap_arch *cga)
> +{
> +        int i;
> +        if (cga == NULL)
> +                return;
> +        free(cga->name);
> +        cleanup_cap_domain_info(&cga->default_domain_info);
> +        for (i = 0; i < cga->num_domains; i++)
> +                cleanup_cap_domain(&cga->domains[i]);
> +        free(cga->domains);
> +}
> +
> +void cleanup_cap_guest(struct cap_guest *cg)
> +{
> +        if (cg == NULL)
> +                return;
> +        free(cg->ostype);
> +        cleanup_cap_arch(&cg->arch);
> +}
> +
> +static void extend_cap_machines(struct cap_domain_info *cg_domaininfo,
> +                                char *name, char *canonical_name)
> +{
> +        struct cap_machine *tmp_list = NULL;
> +        tmp_list = realloc(cg_domaininfo->machines,
> +                           (cg_domaininfo->num_machines + 1) *
> +                           sizeof(struct cap_machine));
> +
> +        if (tmp_list == NULL) {
> +                /* Nothing you can do. Just go on. */
> +                CU_DEBUG("Could not alloc space for "
> +                         "guest domain info list");
> +                return;
> +        }
> +        cg_domaininfo->machines = tmp_list;
> +
> +        struct cap_machine *cap_gm =
> +                &cg_domaininfo->machines[cg_domaininfo->num_machines];
> +        cap_gm->name = name;
> +        cap_gm->canonical_name = canonical_name;
> +        cg_domaininfo->num_machines++;
> +}
> +
> +static void parse_cap_domain_info(struct cap_domain_info *cg_domaininfo,
> +                                  xmlNode *domain_child_node)
> +{
> +        CU_DEBUG("Capabilities guest domain info element node: %s",
> +                 domain_child_node->name);
> +
> +        if (XSTREQ(domain_child_node->name, "emulator")) {
> +                cg_domaininfo->emulator =
> +                        get_node_content(domain_child_node);
> +        } else if (XSTREQ(domain_child_node->name, "loader")) {
> +                cg_domaininfo->loader =
> +                        get_node_content(domain_child_node);
> +        } else if (XSTREQ(domain_child_node->name, "machine")) {
> +                extend_cap_machines(cg_domaininfo,
> +                                    get_node_content(domain_child_node),
> +                                    get_attr_value(domain_child_node,
> +                                                   "canonical"));
> +        }
> +}
> +
> +static void parse_cap_domain(struct cap_domain *cg_domain,
> +                             xmlNode *guest_dom)
> +{
> +        CU_DEBUG("Capabilities guest domain node: %s", guest_dom->name);
> +
> +        xmlNode *child;
> +
> +        cg_domain->typestr = get_attr_value(guest_dom, "type");
> +
> +        for (child = guest_dom->children; child != NULL; child = child->next)
> +                parse_cap_domain_info(&cg_domain->guest_domain_info, child);
> +}
> +
> +static void parse_cap_arch(struct cap_arch *cg_archinfo,
> +                           xmlNode *arch)
> +{
> +        CU_DEBUG("Capabilities arch node: %s", arch->name);
> +
> +        xmlNode *child;
> +
> +        cg_archinfo->name = get_attr_value(arch, "name");
> +
> +        for (child = arch->children; child != NULL; child = child->next) {
> +                if (XSTREQ(child->name, "wordsize")) {
> +                        char *wordsize_str;
> +                        unsigned int wordsize;
> +                        wordsize_str = get_node_content(child);
> +                        /* Default to 0 wordsize if garbage */
> +                        if (wordsize_str == NULL ||
> +                            sscanf(wordsize_str, "%i", &wordsize) != 1)
> +                                wordsize = 0;
> +                        free(wordsize_str);
> +                        cg_archinfo->wordsize = wordsize;
> +                } else if (XSTREQ(child->name, "domain")) {
> +                        struct cap_domain *tmp_list = NULL;
> +                        tmp_list = realloc(cg_archinfo->domains,
> +                                           (cg_archinfo->num_domains + 1) *
> +                                           sizeof(struct cap_domain));
> +                        if (tmp_list == NULL) {
> +                                /* Nothing you can do. Just go on. */
> +                                CU_DEBUG("Could not alloc space for "
> +                                         "guest domain");
> +                                continue;
> +                        }
> +                        memset(&tmp_list[cg_archinfo->num_domains],
> +                               0, sizeof(struct cap_domain));
> +                        cg_archinfo->domains = tmp_list;
> +                        parse_cap_domain(&cg_archinfo->
> +                                         domains[cg_archinfo->num_domains],
> +                                         child);
> +                        cg_archinfo->num_domains++;
> +                } else {
> +                        /* Check for the default domain child nodes */
> +                        parse_cap_domain_info(&cg_archinfo->default_domain_info,
> +                                              child);
> +                }
> +        }
> +}
> +
> +static void parse_cap_guests(xmlNodeSet *nsv, struct cap_guest **cap_guests)
> +{
> +        xmlNode **nodes = nsv->nodeTab;
> +        xmlNode *child;
> +        int numGuestNodes = nsv->nodeNr;
> +        int i;
> +
> +        for (i = 0; i < numGuestNodes; i++) {
> +                for (child = nodes[i]->children; child != NULL;
> +                     child = child->next) {
> +                        if (XSTREQ(child->name, "os_type")) {
> +                                STRPROP(cap_guests[i], ostype, child);
> +                        } else if (XSTREQ(child->name, "arch")) {
> +                                parse_cap_arch(&cap_guests[i]->arch, child);
> +                        }
> +                }
> +        }
> +}
> +
> +static void compare_copy_domain_info_machines(
> +        struct cap_domain_info *def_gdomi,
> +        struct cap_domain_info *cap_gadomi)
> +{
> +        int i,j;
> +        int org_l = cap_gadomi->num_machines;
> +        char *cp_name = NULL;
> +        char *cp_canonical_name = NULL;
> +        bool found;
> +
> +        for (i = 0; i < def_gdomi->num_machines; i++) {
> +                found = false;
> +                for (j = 0; j < org_l; j++) {
> +                        if (STREQC(def_gdomi->machines[i].name,
> +                                   cap_gadomi->machines[j].name)) {
> +                                found = true;
> +                                continue;
> +                                /* found match => check next default */
> +                        }
> +                }
> +                if (!found) { /* no match => insert default */
> +                        cp_name = NULL;
> +                        cp_canonical_name = NULL;
> +                        if (def_gdomi->machines[i].name != NULL)
> +                                cp_name = strdup(def_gdomi->machines[i].name);
> +                        if (def_gdomi->machines[i].canonical_name != NULL)
> +                                cp_canonical_name =
> +                                        strdup(def_gdomi->
> +                                               machines[i].canonical_name);
> +
> +                        extend_cap_machines(cap_gadomi,
> +                                            cp_name,
> +                                            cp_canonical_name);
> +                }
> +        }
> +}
> +
> +static void extend_defaults_cap_guests(struct capabilities *caps)
> +{
> +        struct cap_arch *cap_garch;
> +        struct cap_domain_info *cap_gadomi;
> +        struct cap_domain_info *def_gdomi;
> +        int i,j;
> +
> +        if (caps == NULL)
> +                return;
> +
> +        for (i = 0; i < caps->num_guests; i++) {
> +                cap_garch = &caps->guests[i].arch;
> +                def_gdomi = &cap_garch->default_domain_info;
> +
> +                for (j = 0; j < cap_garch->num_domains; j++) {
> +                        /* compare guest_domain_info */
> +                        cap_gadomi = &cap_garch->domains[j].guest_domain_info;
> +                        if (cap_gadomi->emulator == NULL &&
> +                            def_gdomi->emulator != NULL)
> +                                cap_gadomi->emulator =
> +                                        strdup(def_gdomi->emulator);
> +                        if (cap_gadomi->loader == NULL &&
> +                            def_gdomi->loader != NULL)
> +                                cap_gadomi->loader = strdup(def_gdomi->loader);
> +
> +                        compare_copy_domain_info_machines(def_gdomi,
> +                                                          cap_gadomi);
> +                }
> +        }
> +}
> +
> +static int _get_cap_guests(const char *xml, struct capabilities *caps)
> +{
> +        int len;
> +
> +        xmlDoc *xmldoc = NULL;
> +        xmlXPathContext *xpathctx = NULL;
> +        xmlXPathObject *xpathobj = NULL;
> +        const xmlChar *xpathstr = (xmlChar *)"//capabilities//guest";
> +        xmlNodeSet *nsv;
> +
> +        len = strlen(xml) + 1;
> +
> +        if ((xmldoc = xmlParseMemory(xml, len)) == NULL)
> +                goto err;
> +
> +        if ((xpathctx = xmlXPathNewContext(xmldoc)) == NULL)
> +                goto err;
> +
> +        if ((xpathobj = xmlXPathEvalExpression(xpathstr, xpathctx)) == NULL)
> +                goto err;
> +        if (xmlXPathNodeSetIsEmpty(xpathobj->nodesetval)) {
> +                CU_DEBUG("No capabilities guest nodes found!");
> +                goto err;
> +        }
> +
> +        nsv = xpathobj->nodesetval;
> +        caps->guests = calloc(nsv->nodeNr, sizeof(struct cap_guest));
> +        if (caps->guests == NULL)
> +                goto err;
> +        caps->num_guests = nsv->nodeNr;
> +
> +        parse_cap_guests(nsv, &caps->guests);
> +        extend_defaults_cap_guests(caps);
> +        return 1;
> +
> + err:
> +        xmlXPathFreeObject(xpathobj);
> +        xmlXPathFreeContext(xpathctx);
> +        xmlFreeDoc(xmldoc);
> +        return 0;
> +}
> +
> +int get_caps_from_xml(const char *xml, struct capabilities **caps)
> +{
> +        CU_DEBUG("In get_caps_from_xml");
> +
> +        *caps = calloc(1, sizeof(struct capabilities));
> +        if (*caps == NULL)
> +                goto err;
> +
> +        if (_get_cap_guests(xml, *caps) == 0)
> +                goto err;
> +
> +        return 1;
> +
> + err:
> +        free(*caps);
> +        *caps = NULL;
> +        return 0;
> +}
> +
> +int get_capabilities(virConnectPtr conn, struct capabilities **caps)
> +{
> +        char *caps_xml = NULL;
> +        int ret = 0;
> +
> +        if (conn == NULL) {
> +                CU_DEBUG("Unable to connect to libvirt.");
> +                return 0;
> +        }
> +
> +        caps_xml = virConnectGetCapabilities(conn);
> +
> +        if (caps_xml == NULL) {
> +                CU_DEBUG("Unable to get capabilities xml.");
> +                return 0;
> +        }
> +
> +        ret = get_caps_from_xml(caps_xml, caps);
> +
> +        free(caps_xml);
> +
> +        return ret;
> +}
> +
> +struct cap_domain_info *findDomainInfo(struct capabilities *caps,
> +                                       const char *os_type,
> +                                       const char *arch,
> +                                       const char *domain_type)
> +{
> +        int i,j;
> +        struct cap_arch *ar;
> +        for (i = 0; i < caps->num_guests; i++) {
> +                if (os_type == NULL ||
> +                    STREQC(caps->guests[i].ostype, os_type)) {
> +                        ar = &caps->guests[i].arch;
> +                        if (arch == NULL || STREQC(ar->name,arch))
> +                                for (j = 0; j < ar->num_domains; j++)
> +                                        if (domain_type == NULL ||
> +                                            STREQC(ar->domains[j].typestr,
> +                                                   domain_type))
> +                                                return &ar->domains[j].
> +                                                        guest_domain_info;
> +                }
> +        }
> +        return NULL;
> +}
> +
> +char *get_default_arch(struct capabilities *caps,
> +                       const char *os_type)
> +{
> +        char *ret = NULL;
> +        int i;
> +
> +        if (caps != NULL) {
> +                if (os_type == NULL) { /* pick first guest */
> +                        if (caps->num_guests > 0)
> +                                ret = caps->guests[0].arch.name;
> +                } else {   /* search first matching guest */
> +                        for (i = 0; i < caps->num_guests; i++)
> +                                if (STREQC(caps->guests[i].ostype, os_type)) {
> +                                        ret = caps->guests[i].arch.name;
> +                                        break;
> +                                }
> +                }
> +        }
> +        return ret;
> +}
> +
> +char *get_default_machine(
> +        struct capabilities *caps,
> +        const char *os_type,
> +        const char *arch,
> +        const char *domain_type)
> +{
> +        char *ret = NULL;
> +        struct cap_domain_info *di;
> +
> +        if (caps != NULL) {
> +                di = findDomainInfo(caps, os_type, arch, domain_type);
> +                if (di != NULL && di->num_machines > 0)
> +                        ret = di->machines[0].canonical_name;
> +        }
> +        return ret;
> +}
> +
> +char *get_default_emulator(struct capabilities *caps,
> +                           const char *os_type,
> +                           const char *arch,
> +                           const char *domain_type)
> +{
> +        char *ret = NULL;
> +        struct cap_domain_info *di;
> +
> +        if (caps != NULL) {
> +                di = findDomainInfo(caps, os_type, arch, domain_type);
> +                if (di != NULL)
> +                        ret = di->emulator;
> +        }
> +        return ret;
> +}
> +
> +bool use_kvm(struct capabilities *caps) {
> +        if (host_supports_kvm(caps) && !get_disable_kvm())
> +                return true;
> +        else
> +                return false;
> +}
> +
> +bool host_supports_kvm(struct capabilities *caps)
> +{
> +        bool kvm = false;
> +        if (caps != NULL)
> +                if (findDomainInfo(caps, NULL, NULL, "kvm") != NULL)
> +                        kvm = true;
> +        return kvm;
> +}
> +/*
> + * Local Variables:
> + * mode: C
> + * c-set-style: "K&R"
> + * tab-width: 8
> + * c-basic-offset: 8
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/libxkutil/capability_parsing.h b/libxkutil/capability_parsing.h
> new file mode 100644
> index 0000000..13af510
> --- /dev/null
> +++ b/libxkutil/capability_parsing.h
> @@ -0,0 +1,93 @@
> +/*
> + * Copyright IBM Corp. 2013
> + *
> + * Authors:
> + *  Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
> + */
> +#ifndef __CAPABILITY_PARSING_H
> +#define __CAPABILITY_PARSING_H
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +struct cap_machine {
> +        char *name;
> +        char *canonical_name;
> +};
> +
> +struct cap_domain_info {
> +        char *emulator;
> +        char *loader;
> +        int num_machines;
> +        struct cap_machine *machines;
> +};
> +
> +struct cap_domain {
> +        char *typestr;
> +        struct cap_domain_info guest_domain_info;
> +};
> +
> +struct cap_arch {
> +        char *name;
> +        unsigned int wordsize;
> +        struct cap_domain_info default_domain_info;
> +        int num_domains;
> +        struct cap_domain *domains;
> +};
> +
> +struct cap_guest {
> +        char *ostype;
> +        struct cap_arch arch;
> +};
> +
> +struct capabilities {
> +        int num_guests;
> +        struct cap_guest *guests;
> +};
> +
> +int get_caps_from_xml(const char *xml, struct capabilities **caps);
> +int get_capabilities(virConnectPtr conn, struct capabilities **caps);
> +char *get_default_arch(struct capabilities *caps,
> +                       const char *os_type);
> +char *get_default_machine(struct capabilities *caps,
> +                          const char *os_type,
> +                          const char *arch,
> +                          const char *domain_type);
> +char *get_default_emulator(struct capabilities *caps,
> +                           const char *os_type,
> +                           const char *arch,
> +                           const char *domain_type);
> +struct cap_domain_info *findDomainInfo(struct capabilities *caps,
> +                                       const char *os_type,
> +                                       const char *arch,
> +                                       const char *domain_type);
> +bool use_kvm(struct capabilities *caps);
> +bool host_supports_kvm(struct capabilities *caps);
> +void cleanup_cap_guest(struct cap_guest *cg);
> +void cleanup_cap_domain_info(struct cap_domain_info *cgdi);
> +
> +#endif
> +
> +/*
> + * Local Variables:
> + * mode: C
> + * c-set-style: "K&R"
> + * tab-width: 8
> + * c-basic-offset: 8
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/libxkutil/xml_parse_test.c b/libxkutil/xml_parse_test.c
> index 384593d..5c5f2df 100644
> --- a/libxkutil/xml_parse_test.c
> +++ b/libxkutil/xml_parse_test.c
> @@ -6,6 +6,7 @@
>  #include <libvirt/libvirt.h>
>  
>  #include "device_parsing.h"
> +#include "capability_parsing.h"
>  #include "xmlgen.h"
>  
>  static void print_value(FILE *d, const char *name, const char *val)
> @@ -183,6 +184,91 @@ static char *read_from_file(FILE *file)
>          return xml;
>  }
>  
> +static void print_cap_domain_info(struct cap_domain_info *capgdiinfo,
> +                            FILE *d)
> +{
> +        struct cap_machine capgminfo;
> +        int i;
> +
> +        if (capgdiinfo==NULL)
> +                return;
> +
> +        if (capgdiinfo->emulator!=NULL)
> +                print_value(d, "  Emulator", capgdiinfo->emulator);
> +        if (capgdiinfo->loader!=NULL)
> +                print_value(d, "  Loader", capgdiinfo->loader);
> +        for (i=0; i<capgdiinfo->num_machines; i++) {
> +                capgminfo = capgdiinfo->machines[i];
> +                fprintf(d, "  Machine name : %-15s  canonical name : %s\n",
> +                        capgminfo.name, capgminfo.canonical_name);
> +        }
> +        fprintf(d, "\n");
> +}
> +
> +static void print_cap_domains(struct cap_arch caparchinfo,
> +                            FILE *d)
> +{
> +        struct cap_domain capgdinfo;
> +        int i;
> +        for (i=0; i<caparchinfo.num_domains; i++) {
> +                capgdinfo = caparchinfo.domains[i];
> +                print_value(d, "  Type", capgdinfo.typestr);
> +                print_cap_domain_info(&capgdinfo.guest_domain_info, d);
> +        }
> +}
> +
> +static void print_cap_arch(struct cap_arch caparchinfo,
> +                            FILE *d)
> +{
> +        print_value(d, " Arch name", caparchinfo.name);
> +        fprintf(d, " Arch wordsize : %i\n", caparchinfo.wordsize);
> +        fprintf(d, "\n  -- Default guest domain settings --\n");
> +        print_cap_domain_info(&caparchinfo.default_domain_info, d);
> +        fprintf(d, "  -- Guest domains (%i) --\n", caparchinfo.num_domains);
> +        print_cap_domains(caparchinfo, d);
> +}
> +
> +static void print_cap_guest(struct cap_guest *capginfo,
> +                            FILE *d)
> +{
> +        print_value(d, "Guest OS type", capginfo->ostype);
> +        print_cap_arch(capginfo->arch, d);
> +}
> +
> +static void print_capabilities(struct capabilities *capsinfo,
> +                            FILE *d)
> +{
> +        int i;
> +        fprintf(d, "\n### Capabilities ###\n");
> +        fprintf(d, "-- Guest (%i) --\n", capsinfo->num_guests);
> +        for (i=0; i<capsinfo->num_guests; i++) {
> +                print_cap_guest(&capsinfo->guests[i], d);
> +        }
> +}
> +
> +static int capinfo_for_dom(const char *uri,
> +                           struct domain *dominfo,
> +                           struct capabilities **capsinfo)
> +{
> +        virConnectPtr conn = NULL;
> +        char *caps_xml = NULL;
> +        int ret = 0;
> +
> +        conn = virConnectOpen(uri);
> +        if (conn == NULL) {
> +                printf("Unable to connect to libvirt\n");
> +                goto out;
> +        }
> +
> +        ret = get_capabilities(conn, capsinfo);
> +
> + out:
> +        free(caps_xml);
> +        virConnectClose(conn);
> +
> +        return ret;
> +}
> +
>  static int dominfo_from_dom(const char *uri,
>                              const char *domain,
>                              struct domain **d)
> @@ -246,12 +332,13 @@ static int dominfo_from_file(const char *fname, struct domain **d)
>  static void usage(void)
>  {
>          printf("xml_parse_test -f [FILE | -] [--xml]\n"
> -               "xml_parse_test -d domain [--uri URI] [--xml]\n"
> +               "xml_parse_test -d domain [--uri URI] [--xml] [--cap]\n"
>                 "\n"
>                 "-f,--file FILE    Parse domain XML from file (or stdin if -)\n"
>                 "-d,--domain DOM   Display dominfo for a domain from libvirt\n"
>                 "-u,--uri URI      Connect to libvirt with URI\n"
>                 "-x,--xml          Dump generated XML instead of summary\n"
> +               "-c,--cap          Display the libvirt default capability values for the specified domain\n"
>                 "-h,--help         Display this help message\n");
>  }
>  
> @@ -262,7 +349,10 @@ int main(int argc, char **argv)
>          char *uri = "xen";
>          char *file = NULL;
>          bool xml = false;
> +        bool cap = false;
>          struct domain *dominfo = NULL;
> +        struct capabilities *capsinfo = NULL;
> +        struct cap_domain_info *capgdinfo = NULL;
>          int ret;
>  
>          static struct option lopts[] = {
> @@ -270,13 +360,14 @@ int main(int argc, char **argv)
>                  {"uri",    1, 0, 'u'},
>                  {"xml",    0, 0, 'x'},
>                  {"file",   1, 0, 'f'},
> +                {"cap",    0, 0, 'c'},
>                  {"help",   0, 0, 'h'},
>                  {0,        0, 0, 0}};
>  
>          while (1) {
>                  int optidx = 0;
>  
> -                c = getopt_long(argc, argv, "d:u:f:xh", lopts, &optidx);
> +                c = getopt_long(argc, argv, "d:u:f:xch", lopts, &optidx);
>                  if (c == -1)
>                          break;
>  
> @@ -297,11 +388,14 @@ int main(int argc, char **argv)
>                          xml = true;
>                          break;
>  
> +                case 'c':
> +                        cap = true;
> +                        break;
> +
>                  case '?':
>                  case 'h':
>                          usage();
>                          return c == '?';
> -
>                  };
>          }
>  
> @@ -326,6 +420,40 @@ int main(int argc, char **argv)
>                  print_devices(dominfo, stdout);
>          }
>  
> +        if (cap && file == NULL) {
> +                ret = capinfo_for_dom(uri, dominfo, &capsinfo);
> +                if (ret == 0) {
> +                        printf("Unable to get capsinfo\n");
> +                        return 3;
> +                } else {
> +                        print_capabilities(capsinfo, stdout);
> +
> +                        fprintf(stdout, "-- Default Arch is: %s\n",
> +                                get_default_arch(capsinfo,NULL));
> +                        fprintf(stdout, "-- Default Machine is: %s\n",
> +                                get_default_machine(capsinfo,NULL,NULL,NULL));
> +                        fprintf(stdout, "-- Default Emulator is: %s\n",
> +                                get_default_emulator(capsinfo,NULL,NULL,NULL));
> +                        fprintf(stdout, "-- Default Machine for domain type=kvm : %s\n",
> +                                get_default_machine(capsinfo,NULL,NULL,"kvm"));
> +                        fprintf(stdout, "-- Default Emulator for domain type=kvm : %s\n",
> +                                get_default_emulator(capsinfo,NULL,NULL,"kvm"));
> +
> +                        fprintf(stdout, "\n-- Default Domain Search for: \n"
> +                                "guest type=hvm - guest arch=* - guest domain type=kvm\n");
> +                        capgdinfo = findDomainInfo(capsinfo, "hvm", NULL, "kvm");
> +                        print_cap_domain_info(capgdinfo, stdout);
> +
> +                        fprintf(stdout, "-- Default Domain Search for: \n"
> +                                "guest type=* - guest arch=* - guest domain type=*\n");
> +                        capgdinfo = findDomainInfo(capsinfo, NULL, NULL, NULL);
> +                        print_cap_domain_info(capgdinfo, stdout);
> +                }
> +        } else if (cap) {
> +                printf("Need a data source (--domain) to get default capabilities\n");
> +                return 4;
> +        }
> +
>          return 0;
>  }
>  
> 




More information about the Libvirt-cim mailing list