示例#1
0
static int
lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties)
{
    VIR_AUTOFREE(char *) value = NULL;
    virBitmapPtr nodeset = NULL;

    if (virConfGetValueString(properties, "lxc.cgroup.cpuset.cpus",
                              &value) > 0) {
        if (virBitmapParse(value, &def->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0)
            return -1;
        def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC;
        VIR_FREE(value);
    }

    if (virConfGetValueString(properties, "lxc.cgroup.cpuset.mems",
                              &value) > 0) {
        if (virBitmapParse(value, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
            return -1;
        if (virDomainNumatuneSet(def->numa,
                                 def->placement_mode ==
                                 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
                                 VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC,
                                 VIR_DOMAIN_NUMATUNE_MEM_STRICT,
                                 nodeset) < 0) {
            virBitmapFree(nodeset);
            return -1;
        }
        virBitmapFree(nodeset);
    }

    return 0;
}
示例#2
0
static int
lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties)
{
    virConfValuePtr value;
    virBitmapPtr nodeset = NULL;

    if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.cpus")) &&
            value->str) {
        if (virBitmapParse(value->str, 0, &def->cpumask,
                           VIR_DOMAIN_CPUMASK_LEN) < 0)
            return -1;

        def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC;
    }

    if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.mems")) &&
        value->str) {
        if (virBitmapParse(value->str, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
            return -1;
        if (virDomainNumatuneSet(def->numa,
                                 def->placement_mode ==
                                 VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
                                 VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC,
                                 VIR_DOMAIN_NUMATUNE_MEM_STRICT,
                                 nodeset) < 0) {
            virBitmapFree(nodeset);
            return -1;
        }
        virBitmapFree(nodeset);
    }

    return 0;
}
示例#3
0
/*
 * Linux maintains cpu bit map. For example, if cpuid=5's flag is not set
 * and max cpu is 7. The map file shows 0-4,6-7. This function parses
 * it and returns cpumap.
 */
static virBitmapPtr
linuxParseCPUmap(int *max_cpuid, const char *path)
{
    virBitmapPtr map = NULL;
    char *str = NULL;
    int max_id = 0, i;

    if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0) {
        virReportOOMError();
        goto error;
    }

    if (virBitmapParse(str, 0, &map,
                       VIR_DOMAIN_CPUMASK_LEN) < 0) {
        goto error;
    }

    i = -1;
    while ((i = virBitmapNextSetBit(map, i)) >= 0) {
        max_id = i;
    }

    *max_cpuid = max_id;

    VIR_FREE(str);
    return map;

error:
    VIR_FREE(str);
    virBitmapFree(map);
    return NULL;
}
示例#4
0
/*
 * Linux maintains cpu bit map under cpu/online. For example, if
 * cpuid=5's flag is not set and max cpu is 7, the map file shows
 * 0-4,6-7. This function parses it and returns cpumap.
 */
static virBitmapPtr
linuxParseCPUmap(int max_cpuid, const char *path)
{
    virBitmapPtr map = NULL;
    char *str = NULL;

    if (virFileReadAll(path, 5 * VIR_DOMAIN_CPUMASK_LEN, &str) < 0)
        goto error;

    if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
        goto error;

    VIR_FREE(str);
    return map;

error:
    VIR_FREE(str);
    virBitmapFree(map);
    return NULL;
}
示例#5
0
/*
 * Linux maintains cpu bit map under cpu/online. For example, if
 * cpuid=5's flag is not set and max cpu is 7, the map file shows
 * 0-4,6-7. This function parses it and returns cpumap.
 */
static virBitmapPtr
virHostCPUParseMapLinux(int max_cpuid, const char *path)
{
    virBitmapPtr map = NULL;
    char *str = NULL;

    if (virFileReadAll(path, 5 * VIR_HOST_CPU_MASK_LEN, &str) < 0)
        goto error;

    if (virBitmapParse(str, 0, &map, max_cpuid) < 0)
        goto error;

    VIR_FREE(str);
    return map;

 error:
    VIR_FREE(str);
    virBitmapFree(map);
    return NULL;
}
示例#6
0
virCPUDefPtr
virCPUDefParseXML(xmlNodePtr node,
                  xmlXPathContextPtr ctxt,
                  enum virCPUType mode)
{
    virCPUDefPtr def;
    xmlNodePtr *nodes = NULL;
    int n;
    size_t i;
    char *cpuMode;
    char *fallback = NULL;
    char *vendor_id = NULL;

    if (!xmlStrEqual(node->name, BAD_CAST "cpu")) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("XML does not contain expected 'cpu' element"));
        return NULL;
    }

    if (VIR_ALLOC(def) < 0)
        return NULL;

    if (mode == VIR_CPU_TYPE_AUTO) {
        if (virXPathBoolean("boolean(./arch)", ctxt)) {
            if (virXPathBoolean("boolean(./@match)", ctxt)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("'arch' element element cannot be used inside 'cpu'"
                                 " element with 'match' attribute'"));
                goto error;
            }
            def->type = VIR_CPU_TYPE_HOST;
        } else {
            def->type = VIR_CPU_TYPE_GUEST;
        }
    } else {
        def->type = mode;
    }

    if ((cpuMode = virXMLPropString(node, "mode"))) {
        if (def->type == VIR_CPU_TYPE_HOST) {
            VIR_FREE(cpuMode);
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Attribute mode is only allowed for guest CPU"));
            goto error;
        } else {
            def->mode = virCPUModeTypeFromString(cpuMode);

            if (def->mode < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Invalid mode attribute '%s'"),
                               cpuMode);
                VIR_FREE(cpuMode);
                goto error;
            }
            VIR_FREE(cpuMode);
        }
    } else {
        if (def->type == VIR_CPU_TYPE_HOST)
            def->mode = -1;
        else
            def->mode = VIR_CPU_MODE_CUSTOM;
    }

    if (def->type == VIR_CPU_TYPE_GUEST) {
        char *match = virXMLPropString(node, "match");

        if (!match) {
            if (virXPathBoolean("boolean(./model)", ctxt))
                def->match = VIR_CPU_MATCH_EXACT;
            else
                def->match = -1;
        } else {
            def->match = virCPUMatchTypeFromString(match);
            VIR_FREE(match);

            if (def->match < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Invalid match attribute for CPU "
                                 "specification"));
                goto error;
            }
        }
    }

    if (def->type == VIR_CPU_TYPE_HOST) {
        char *arch = virXPathString("string(./arch[1])", ctxt);
        if (!arch) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing CPU architecture"));
            goto error;
        }
        if ((def->arch = virArchFromString(arch)) == VIR_ARCH_NONE) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unknown architecture %s"), arch);
            VIR_FREE(arch);
            goto error;
        }
        VIR_FREE(arch);
    }

    if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
        def->type == VIR_CPU_TYPE_HOST) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                        _("Missing CPU model name"));
        goto error;
    }

    if (def->type == VIR_CPU_TYPE_GUEST &&
        def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {

        if ((fallback = virXPathString("string(./model[1]/@fallback)", ctxt))) {
            if ((def->fallback = virCPUFallbackTypeFromString(fallback)) < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Invalid fallback attribute"));
                goto error;
            }
        }

        if ((vendor_id = virXPathString("string(./model[1]/@vendor_id)",
                                        ctxt))) {
            if (strlen(vendor_id) != VIR_CPU_VENDOR_ID_LENGTH) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("vendor_id must be exactly %d characters long"),
                               VIR_CPU_VENDOR_ID_LENGTH);
                goto error;
            }

            /* ensure that the string can be passed to qemu*/
            if (strchr(vendor_id, ',')) {
                    virReportError(VIR_ERR_XML_ERROR, "%s",
                                   _("vendor id is invalid"));
                    goto error;
            }

            def->vendor_id = vendor_id;
            vendor_id = NULL;
        }
    }

    def->vendor = virXPathString("string(./vendor[1])", ctxt);
    if (def->vendor && !def->model) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("CPU vendor specified without CPU model"));
        goto error;
    }

    if (virXPathNode("./topology[1]", ctxt)) {
        int ret;
        unsigned long ul;

        ret = virXPathULong("string(./topology[1]/@sockets)",
                            ctxt, &ul);
        if (ret < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing 'sockets' attribute in CPU topology"));
            goto error;
        }
        def->sockets = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@cores)",
                            ctxt, &ul);
        if (ret < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing 'cores' attribute in CPU topology"));
            goto error;
        }
        def->cores = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@threads)",
                            ctxt, &ul);
        if (ret < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing 'threads' attribute in CPU topology"));
            goto error;
        }
        def->threads = (unsigned int) ul;

        if (!def->sockets || !def->cores || !def->threads) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Invalid CPU topology"));
            goto error;
        }
    }

    if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0)
        goto error;

    if (n > 0) {
        if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Non-empty feature list specified without "
                             "CPU model"));
            goto error;
        }

        if (VIR_RESIZE_N(def->features, def->nfeatures_max,
                         def->nfeatures, n) < 0)
            goto error;

        def->nfeatures = n;
    }

    for (i = 0; i < n; i++) {
        char *name;
        int policy; /* enum virDomainCPUFeaturePolicy */
        size_t j;

        if (def->type == VIR_CPU_TYPE_GUEST) {
            char *strpolicy;

            strpolicy = virXMLPropString(nodes[i], "policy");
            if (strpolicy == NULL)
                policy = VIR_CPU_FEATURE_REQUIRE;
            else
                policy = virCPUFeaturePolicyTypeFromString(strpolicy);
            VIR_FREE(strpolicy);

            if (policy < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("Invalid CPU feature policy"));
                goto error;
            }
        } else {
            policy = -1;
        }

        if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) {
            VIR_FREE(name);
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Invalid CPU feature name"));
            goto error;
        }

        for (j = 0; j < i; j++) {
            if (STREQ(name, def->features[j].name)) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("CPU feature `%s' specified more than once"),
                               name);
                VIR_FREE(name);
                goto error;
            }
        }

        def->features[i].name = name;
        def->features[i].policy = policy;
    }

    if (virXPathNode("./numa[1]", ctxt)) {
        VIR_FREE(nodes);
        n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes);
        if (n <= 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("NUMA topology defined without NUMA cells"));
            goto error;
        }

        if (VIR_RESIZE_N(def->cells, def->ncells_max,
                         def->ncells, n) < 0)
            goto error;

        def->ncells = n;

        for (i = 0; i < n; i++) {
            char *cpus, *memory;
            int ret, ncpus = 0;

            def->cells[i].cellid = i;
            cpus = virXMLPropString(nodes[i], "cpus");
            if (!cpus) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("Missing 'cpus' attribute in NUMA cell"));
                goto error;
            }
            def->cells[i].cpustr = cpus;

            ncpus = virBitmapParse(cpus, 0, &def->cells[i].cpumask,
                                   VIR_DOMAIN_CPUMASK_LEN);
            if (ncpus <= 0)
                goto error;
            def->cells_cpus += ncpus;

            memory = virXMLPropString(nodes[i], "memory");
            if (!memory) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("Missing 'memory' attribute in NUMA cell"));
                goto error;
            }

            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
            if (ret == -1) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("Invalid 'memory' attribute in NUMA cell"));
                VIR_FREE(memory);
                goto error;
            }
            VIR_FREE(memory);
        }
    }

cleanup:
    VIR_FREE(fallback);
    VIR_FREE(vendor_id);
    VIR_FREE(nodes);
    return def;

error:
    virCPUDefFree(def);
    def = NULL;
    goto cleanup;
}
示例#7
0
static int
virDomainNumatuneNodeParseXML(virDomainNumaPtr numa,
                              xmlXPathContextPtr ctxt)
{
    char *tmp = NULL;
    int n = 0;
    int ret = -1;
    size_t i = 0;
    xmlNodePtr *nodes = NULL;

    if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot extract memnode nodes"));
        goto cleanup;
    }

    if (!n)
        return 0;

    if (numa->memory.specified &&
        numa->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Per-node binding is not compatible with "
                         "automatic NUMA placement."));
        goto cleanup;
    }

    if (!numa->nmem_nodes) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Element 'memnode' is invalid without "
                         "any guest NUMA cells"));
        goto cleanup;
    }

    for (i = 0; i < n; i++) {
        int mode = 0;
        unsigned int cellid = 0;
        virDomainNumaNodePtr mem_node = NULL;
        xmlNodePtr cur_node = nodes[i];

        tmp = virXMLPropString(cur_node, "cellid");
        if (!tmp) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing required cellid attribute "
                             "in memnode element"));
            goto cleanup;
        }
        if (virStrToLong_uip(tmp, NULL, 10, &cellid) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Invalid cellid attribute in memnode element: %s"),
                           tmp);
            goto cleanup;
        }
        VIR_FREE(tmp);

        if (cellid >= numa->nmem_nodes) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Argument 'cellid' in memnode element must "
                             "correspond to existing guest's NUMA cell"));
            goto cleanup;
        }

        mem_node = &numa->mem_nodes[cellid];

        if (mem_node->nodeset) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Multiple memnode elements with cellid %u"),
                           cellid);
            goto cleanup;
        }

        tmp = virXMLPropString(cur_node, "mode");
        if (!tmp) {
            mem_node->mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
        } else {
            if ((mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("Invalid mode attribute in memnode element"));
                goto cleanup;
            }
            VIR_FREE(tmp);
            mem_node->mode = mode;
        }

        tmp = virXMLPropString(cur_node, "nodeset");
        if (!tmp) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing required nodeset attribute "
                             "in memnode element"));
            goto cleanup;
        }
        if (virBitmapParse(tmp, 0, &mem_node->nodeset,
                           VIR_DOMAIN_CPUMASK_LEN) < 0)
            goto cleanup;

        if (virBitmapIsAllClear(mem_node->nodeset)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Invalid value of 'nodeset': %s"), tmp);
            goto cleanup;
        }
        VIR_FREE(tmp);
    }

    ret = 0;
 cleanup:
    VIR_FREE(nodes);
    VIR_FREE(tmp);
    return ret;
}
示例#8
0
int
virDomainNumaDefCPUParseXML(virDomainNumaPtr def,
                            xmlXPathContextPtr ctxt)
{
    xmlNodePtr *nodes = NULL;
    xmlNodePtr oldNode = ctxt->node;
    char *tmp = NULL;
    int n;
    size_t i;
    int ret = -1;

    /* check if NUMA definition is present */
    if (!virXPathNode("./cpu/numa[1]", ctxt))
        return 0;

    if ((n = virXPathNodeSet("./cpu/numa[1]/cell", ctxt, &nodes)) <= 0) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("NUMA topology defined without NUMA cells"));
        goto cleanup;
    }

    if (VIR_ALLOC_N(def->mem_nodes, n) < 0)
        goto cleanup;
    def->nmem_nodes = n;

    for (i = 0; i < n; i++) {
        size_t j;
        int rc;
        unsigned int cur_cell = i;

        /* cells are in order of parsing or explicitly numbered */
        if ((tmp = virXMLPropString(nodes[i], "id"))) {
            if (virStrToLong_uip(tmp, NULL, 10, &cur_cell) < 0) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("Invalid 'id' attribute in NUMA cell: '%s'"),
                               tmp);
                goto cleanup;
            }

            if (cur_cell >= n) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("Exactly one 'cell' element per guest "
                                 "NUMA cell allowed, non-contiguous ranges or "
                                 "ranges not starting from 0 are not allowed"));
                goto cleanup;
            }
        }
        VIR_FREE(tmp);

        if (def->mem_nodes[cur_cell].cpumask) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Duplicate NUMA cell info for cell id '%u'"),
                           cur_cell);
            goto cleanup;
        }

        if (!(tmp = virXMLPropString(nodes[i], "cpus"))) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("Missing 'cpus' attribute in NUMA cell"));
            goto cleanup;
        }

        if (virBitmapParse(tmp, 0, &def->mem_nodes[cur_cell].cpumask,
                           VIR_DOMAIN_CPUMASK_LEN) < 0)
            goto cleanup;

        if (virBitmapIsAllClear(def->mem_nodes[cur_cell].cpumask)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                          _("NUMA cell %d has no vCPUs assigned"), cur_cell);
            goto cleanup;
        }
        VIR_FREE(tmp);

        for (j = 0; j < i; j++) {
            if (virBitmapOverlaps(def->mem_nodes[j].cpumask,
                                  def->mem_nodes[i].cpumask)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("NUMA cells %zu and %zu have overlapping vCPU ids"), i, j);
                goto cleanup;
            }
        }

        ctxt->node = nodes[i];
        if (virDomainParseMemory("./@memory", "./@unit", ctxt,
                                 &def->mem_nodes[cur_cell].mem, true, false) < 0)
            goto cleanup;

        if ((tmp = virXMLPropString(nodes[i], "memAccess"))) {
            if ((rc = virNumaMemAccessTypeFromString(tmp)) <= 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Invalid 'memAccess' attribute value '%s'"),
                               tmp);
                goto cleanup;
            }

            def->mem_nodes[cur_cell].memAccess = rc;
            VIR_FREE(tmp);
        }
    }

    ret = 0;

 cleanup:
    ctxt->node = oldNode;
    VIR_FREE(nodes);
    VIR_FREE(tmp);
    return ret;
}
示例#9
0
int
virDomainNumatuneParseXML(virDomainNumaPtr numa,
                          bool placement_static,
                          xmlXPathContextPtr ctxt)
{
    char *tmp = NULL;
    int mode = -1;
    int n = 0;
    int placement = -1;
    int ret = -1;
    virBitmapPtr nodeset = NULL;
    xmlNodePtr node = NULL;

    if (virXPathInt("count(./numatune)", ctxt, &n) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot extract numatune nodes"));
        goto cleanup;
    } else if (n > 1) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("only one numatune is supported"));
        goto cleanup;
    }

    node = virXPathNode("./numatune/memory[1]", ctxt);

    if (!placement_static && !node)
        placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO;

    if (node) {
        if ((tmp = virXMLPropString(node, "mode")) &&
            (mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported NUMA memory tuning mode '%s'"), tmp);
            goto cleanup;
        }
        VIR_FREE(tmp);

        if ((tmp = virXMLPropString(node, "placement")) &&
            (placement = virDomainNumatunePlacementTypeFromString(tmp)) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported NUMA memory placement mode '%s'"), tmp);
            goto cleanup;
        }
        VIR_FREE(tmp);

        tmp = virXMLPropString(node, "nodeset");
        if (tmp) {
            if (virBitmapParse(tmp, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
                goto cleanup;

            if (virBitmapIsAllClear(nodeset)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Invalid value of 'nodeset': %s"), tmp);
                goto cleanup;
            }

            VIR_FREE(tmp);
        }
    }

    if (virDomainNumatuneSet(numa,
                             placement_static,
                             placement,
                             mode,
                             nodeset) < 0)
        goto cleanup;

    if (virDomainNumatuneNodeParseXML(numa, ctxt) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virBitmapFree(nodeset);
    VIR_FREE(tmp);
    return ret;
}
int
virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr,
                          bool placement_static,
                          size_t ncells,
                          xmlXPathContextPtr ctxt)
{
    char *tmp = NULL;
    int mode = -1;
    int n = 0;
    int placement = -1;
    int ret = -1;
    virBitmapPtr nodeset = NULL;
    xmlNodePtr node = NULL;

    if (virXPathInt("count(./numatune)", ctxt, &n) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot extract numatune nodes"));
        goto cleanup;
    } else if (n > 1) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("only one numatune is supported"));
        goto cleanup;
    }

    node = virXPathNode("./numatune/memory[1]", ctxt);

    if (*numatunePtr) {
        virDomainNumatuneFree(*numatunePtr);
        *numatunePtr = NULL;
    }

    if (!node && placement_static) {
        if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0)
            goto cleanup;
        return 0;
    }

    if (!node) {
        /* We know that placement_mode is "auto" if we're here */
        ret = virDomainNumatuneSet(numatunePtr,
                                   placement_static,
                                   VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO,
                                   -1,
                                   NULL);
        goto cleanup;
    }

    tmp = virXMLPropString(node, "mode");
    if (tmp) {
        mode = virDomainNumatuneMemModeTypeFromString(tmp);
        if (mode < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported NUMA memory tuning mode '%s'"),
                           tmp);
            goto cleanup;
        }
    }
    VIR_FREE(tmp);

    tmp = virXMLPropString(node, "placement");
    if (tmp) {
        placement = virDomainNumatunePlacementTypeFromString(tmp);
        if (placement < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported NUMA memory placement mode '%s'"),
                           tmp);
            goto cleanup;
        }
    }
    VIR_FREE(tmp);

    tmp = virXMLPropString(node, "nodeset");
    if (tmp && virBitmapParse(tmp, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0)
        goto cleanup;
    VIR_FREE(tmp);

    if (virDomainNumatuneSet(numatunePtr,
                             placement_static,
                             placement,
                             mode,
                             nodeset) < 0)
        goto cleanup;

    if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    virBitmapFree(nodeset);
    VIR_FREE(tmp);
    return ret;
}
示例#11
0
int lxctoolsReadConfig(struct lxc_container* cont, virDomainDefPtr def)
{
    char* item_str = NULL;
    virNodeInfoPtr nodeinfo = NULL;
    lxctoolsConffilePtr conffile = NULL;

    if (VIR_ALLOC(nodeinfo) < 0) {
        goto error;
    }
    
    if (virCapabilitiesGetNodeInfo(nodeinfo) < 0) {
        goto error;
    }
    
    if (VIR_ALLOC(conffile) < 0)
        goto error;

    if (lxctoolsConffileRead(conffile, cont->config_file_name(cont)) < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED, "'%s'", _("failed to read conffile"));
        goto error;
    }
    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.arch")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        if (strcmp(item_str, "x86") == 0 || strcmp(item_str, "i686")  == 0) {
            def->os.arch = VIR_ARCH_I686;
        }
        else if (strcmp(item_str, "x86_64") == 0 || strcmp(item_str, "amd64") == 0) {
            def->os.arch = VIR_ARCH_X86_64;
        } else {
            virReportError(VIR_ERR_OPERATION_FAILED, "Unknown architecture '%s'.", item_str);
            goto error;
        }
    }
    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpuset.cpus")) == NULL){
        goto error;
    }
    if (item_str[0] == '\0') {
        if (virDomainDefSetVcpusMax(def, nodeinfo->cpus, NULL) < 0)
            goto error;
        def->cpumask = virBitmapNew(nodeinfo->cpus);
        virBitmapSetAll(def->cpumask);
    } else {
        int cpunum;
        if ( (cpunum = virBitmapParse(item_str, &def->cpumask, nodeinfo->cpus) ) < 0) {
            goto error;
        }  
        if (virDomainDefSetVcpusMax(def, cpunum, NULL) < 0)
            goto error;
    }

    if (virDomainDefSetVcpus(def, virDomainDefGetVcpusMax(def)) < 0)
        goto error;
   
    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.shares")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        unsigned long shares;
        sscanf(item_str, "%lu", &shares);
        def->cputune.shares = shares;
        def->cputune.sharesSpecified = true;
    }

    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.cfs_period_us")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        unsigned long long period;
        sscanf(item_str, "%llu", &period);
        def->cputune.period = period;
    }

    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpu.cfs_quota_us")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        long long quota;
        sscanf(item_str, "%llu", &quota);
        def->cputune.quota = quota;
    }

    VIR_FREE(item_str);
    item_str = NULL;


    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.memory.limit_in_bytes")) == NULL) {
        goto error;
    }
    if (item_str[0] == '\0') {
        virDomainDefSetMemoryTotal(def, nodeinfo->memory);
    } else {
        virDomainDefSetMemoryTotal(def, memToULL(item_str)); 
    }


    def->mem.cur_balloon = virDomainDefGetMemoryTotal(def);
//    def->mem.max_memory = nodeinfo->memory;
//    def->mem.memory_slots = 1; //maybe delete max_memory alltogether

    VIR_FREE(item_str);
    item_str = NULL;
    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.memory.soft_limit_in_bytes")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        def->mem.soft_limit = memToULL(item_str);
    }

    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.cgroup.cpuset.mems")) == NULL) {
        goto error;
    }
    if (item_str[0] != '\0') {
        virBitmapPtr nodeset;
        if (virBitmapParse(item_str, &nodeset, nodeinfo->nodes) < 0) {
            goto error;
        }  
        if (virDomainNumatuneSet(def->numa,
                             true,
                             VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT,
                             VIR_DOMAIN_NUMATUNE_MEM_STRICT,
                             nodeset) < 0 ) {
            goto error;
        }
    }

    VIR_FREE(item_str);
    item_str = NULL;

    if ((item_str = lxctoolsConffileGetItem(conffile, "lxc.include")) == NULL) {
        goto error;
    }

    //lxc.include is optional!
    if (item_str[0] != '\0') {
        def->metadata = xmlNewNode(NULL, (const xmlChar*) "metadata");
        xmlNewTextChild(def->metadata, NULL, (const xmlChar*) (const xmlChar*)"lxctools:include", (const xmlChar*)item_str);
    }

    VIR_FREE(item_str);
    item_str = NULL;
    if (lxctoolsReadFSConfig(conffile, def) < 0)
        goto error;

    if (lxctoolsReadNetConfig(cont, def) < 0)
        goto error;

    return 0;
 error:
    VIR_FREE(item_str);
    VIR_FREE(nodeinfo);
    return -1;
}