static int virInterfaceDefParseMtu(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { unsigned long mtu; int ret; ret = virXPathULong("string(./mtu/@size)", ctxt, &mtu); if ((ret == -2) || ((ret == 0) && (mtu > 100000))) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("interface mtu value is improper")); return -1; } else if (ret == 0) { def->mtu = (unsigned int) mtu; } return 0; }
static int virNodeDevCapsDefParseULong(const char *xpath, xmlXPathContextPtr ctxt, unsigned *value, virNodeDeviceDefPtr def, const char *missing_error_fmt, const char *invalid_error_fmt) { int ret; unsigned long val; ret = virXPathULong(xpath, ctxt, &val); if (ret < 0) { virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, ret == -1 ? missing_error_fmt : invalid_error_fmt, def->name); return -1; } *value = val; return 0; }
int virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr def) { int ret = -1; xmlNodePtr save = ctxt->node; char *trunk = NULL; char *nativeMode = NULL; xmlNodePtr *tagNodes = NULL; int nTags; size_t i; ctxt->node = node; nTags = virXPathNodeSet("./tag", ctxt, &tagNodes); if (nTags < 0) goto cleanup; if (nTags == 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing tag id - each <vlan> must have " "at least one <tag id='n'/> subelement")); goto cleanup; } if (VIR_ALLOC_N(def->tag, nTags) < 0) goto cleanup; def->nativeMode = 0; def->nativeTag = 0; for (i = 0; i < nTags; i++) { unsigned long id; ctxt->node = tagNodes[i]; if (virXPathULong("string(./@id)", ctxt, &id) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing or invalid vlan tag id attribute")); goto cleanup; } if (id > 4095) { virReportError(VIR_ERR_XML_ERROR, _("vlan tag id %lu too large (maximum 4095)"), id); goto cleanup; } if ((nativeMode = virXPathString("string(./@nativeMode)", ctxt))) { if (def->nativeMode != 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("duplicate native vlan setting")); goto cleanup; } if ((def->nativeMode = virNativeVlanModeTypeFromString(nativeMode)) <= 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid \"nativeMode='%s'\" " "in vlan <tag> element"), nativeMode); goto cleanup; } VIR_FREE(nativeMode); def->nativeTag = id; } def->tag[i] = id; } def->nTags = nTags; /* now that we know how many tags there are, look for an explicit * trunk setting. */ if (nTags > 1) def->trunk = true; ctxt->node = node; if ((trunk = virXPathString("string(./@trunk)", ctxt)) != NULL) { def->trunk = STRCASEEQ(trunk, "yes"); if (!def->trunk) { if (nTags > 1) { virReportError(VIR_ERR_XML_ERROR, _("invalid \"trunk='%s'\" in <vlan> - trunk='yes' " "is required for more than one vlan tag"), trunk); goto cleanup; } if (def->nativeMode != 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid configuration in <vlan> - \"trunk='no'\" is " "not allowed with a native vlan id")); goto cleanup; } /* allow (but discard) "trunk='no' if there is a single tag */ if (STRCASENEQ(trunk, "no")) { virReportError(VIR_ERR_XML_ERROR, _("invalid \"trunk='%s'\" in <vlan> " "- must be yes or no"), trunk); goto cleanup; } } } ret = 0; cleanup: ctxt->node = save; VIR_FREE(tagNodes); VIR_FREE(trunk); VIR_FREE(nativeMode); if (ret < 0) virNetDevVlanClear(def); return ret; }
virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, xmlXPathContextPtr ctxt, enum virCPUType mode) { virCPUDefPtr def; xmlNodePtr *nodes = NULL; int n; unsigned int i; char *cpuMode; if (!xmlStrEqual(node->name, BAD_CAST "cpu")) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("XML does not contain expected 'cpu' element")); return NULL; } if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (mode == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virCPUReportError(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); virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Attribute mode is only allowed for guest CPU")); goto error; } else { def->mode = virCPUModeTypeFromString(cpuMode); if (def->mode < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid match attribute for CPU specification")); goto error; } } } if (def->type == VIR_CPU_TYPE_HOST) { def->arch = virXPathString("string(./arch[1])", ctxt); if (!def->arch) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU architecture")); goto error; } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && def->type == VIR_CPU_TYPE_HOST) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto error; } if (def->type == VIR_CPU_TYPE_GUEST && def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH && virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) { const char *fallback; fallback = virXPathString("string(./model[1]/@fallback)", ctxt); if (fallback) { def->fallback = virCPUFallbackTypeFromString(fallback); VIR_FREE(fallback); if (def->fallback < 0) { virCPUReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid fallback attribute")); goto error; } } } def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto error; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU topology")); goto error; } } n = virXPathNodeSet("./feature", ctxt, &nodes); if (n < 0) goto error; if (n > 0) { if (!def->model) { virCPUReportError(VIR_ERR_INTERNAL_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 no_memory; def->nfeatures = n; } for (i = 0 ; i < n ; i++) { char *name; int policy; /* enum virDomainCPUFeaturePolicy */ unsigned int 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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature policy")); goto error; } } else { policy = -1; } if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { VIR_FREE(name); virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature name")); goto error; } for (j = 0 ; j < i ; j++) { if (STREQ(name, def->features[j].name)) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("NUMA topology defined without NUMA cells")); goto error; } if (VIR_RESIZE_N(def->cells, def->ncells_max, def->ncells, n) < 0) goto no_memory; def->ncells = n; for (i = 0 ; i < n ; i++) { char *cpus, *memory; int cpumasklen = VIR_DOMAIN_CPUMASK_LEN; int ret, ncpus = 0; def->cells[i].cellid = i; cpus = virXMLPropString(nodes[i], "cpus"); if (!cpus) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'cpus' attribute in NUMA cell")); goto error; } def->cells[i].cpustr = cpus; if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0) goto no_memory; ncpus = virDomainCpuSetParse(cpus, 0, def->cells[i].cpumask, cpumasklen); if (ncpus <= 0) goto error; def->cells_cpus += ncpus; memory = virXMLPropString(nodes[i], "memory"); if (!memory) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'memory' attribute in NUMA cell")); goto error; } ret = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem); if (ret == -1) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid 'memory' attribute in NUMA cell")); VIR_FREE(memory); goto error; } VIR_FREE(memory); } } cleanup: VIR_FREE(nodes); return def; no_memory: virReportOOMError(); error: virCPUDefFree(def); def = NULL; goto cleanup; }
virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, xmlXPathContextPtr ctxt, enum virCPUType mode) { virCPUDefPtr def; xmlNodePtr *nodes = NULL; int n; unsigned int i; if (!xmlStrEqual(node->name, BAD_CAST "cpu")) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("XML does not contain expected 'cpu' element")); return NULL; } if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (mode == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virCPUReportError(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 (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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid match attribute for CPU specification")); goto error; } } } if (def->type == VIR_CPU_TYPE_HOST) { def->arch = virXPathString("string(./arch[1])", ctxt); if (!def->arch) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU architecture")); goto error; } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && def->type == VIR_CPU_TYPE_HOST) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto error; } def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto error; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU topology")); goto error; } } n = virXPathNodeSet("./feature", ctxt, &nodes); if (n < 0) goto error; if (n > 0) { if (!def->model) { virCPUReportError(VIR_ERR_INTERNAL_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 no_memory; def->nfeatures = n; } for (i = 0 ; i < n ; i++) { char *name; int policy; /* enum virDomainCPUFeaturePolicy */ unsigned int 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) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature policy")); goto error; } } else policy = -1; if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { VIR_FREE(name); virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature name")); goto error; } for (j = 0 ; j < i ; j++) { if (STREQ(name, def->features[j].name)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU feature `%s' specified more than once"), name); VIR_FREE(name); goto error; } } def->features[i].name = name; def->features[i].policy = policy; } cleanup: VIR_FREE(nodes); return def; no_memory: virReportOOMError(); error: virCPUDefFree(def); def = NULL; goto cleanup; }
static int virInterfaceDefParseBond(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { int ret = -1; unsigned long tmp; def->data.bond.mode = virInterfaceDefParseBondMode(ctxt); if (def->data.bond.mode < 0) goto error; ret = virInterfaceDefParseBondItfs(def, ctxt); if (ret != 0) goto error; if (virXPathNode("./miimon[1]", ctxt) != NULL) { def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII; ret = virXPathULong("string(./miimon/@freq)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface miimon freq missing or invalid")); goto error; } def->data.bond.frequency = (int) tmp; ret = virXPathULong("string(./miimon/@downdelay)", ctxt, &tmp); if (ret == -2) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface miimon downdelay invalid")); goto error; } else if (ret == 0) { def->data.bond.downdelay = (int) tmp; } ret = virXPathULong("string(./miimon/@updelay)", ctxt, &tmp); if (ret == -2) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface miimon updelay invalid")); goto error; } else if (ret == 0) { def->data.bond.updelay = (int) tmp; } def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(ctxt); if (def->data.bond.carrier < 0) { ret = -1; goto error; } } else if (virXPathNode("./arpmon[1]", ctxt) != NULL) { def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP; ret = virXPathULong("string(./arpmon/@interval)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface arpmon interval missing or invalid")); goto error; } def->data.bond.interval = (int) tmp; def->data.bond.target = virXPathString("string(./arpmon/@target)", ctxt); if (def->data.bond.target == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface arpmon target missing")); ret = -1; goto error; } def->data.bond.validate = virInterfaceDefParseBondArpValid(ctxt); if (def->data.bond.validate < 0) { ret = -1; goto error; } } error: return ret; }
/* * Parses CPU definition XML from a node pointed to by @xpath. If @xpath is * NULL, the current node of @ctxt is used (i.e., it is a shortcut to "."). * * Missing <cpu> element in the XML document is not considered an error unless * @xpath is NULL in which case the function expects it was provided with a * valid <cpu> element already. In other words, the function returns success * and sets @cpu to NULL if @xpath is not NULL and the node pointed to by * @xpath is not found. * * Returns 0 on success, -1 on error. */ int virCPUDefParseXML(xmlXPathContextPtr ctxt, const char *xpath, virCPUType type, virCPUDefPtr *cpu) { virCPUDefPtr def = NULL; xmlNodePtr *nodes = NULL; xmlNodePtr oldnode = ctxt->node; int n; size_t i; char *cpuMode; char *fallback = NULL; char *vendor_id = NULL; int ret = -1; *cpu = NULL; if (xpath && !(ctxt->node = virXPathNode(xpath, ctxt))) { ret = 0; goto cleanup; } if (!virXMLNodeNameEqual(ctxt->node, "cpu")) { virReportError(VIR_ERR_XML_ERROR, "%s", _("XML does not contain expected 'cpu' element")); goto cleanup; } if (VIR_ALLOC(def) < 0) goto cleanup; if (type == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("'arch' element cannot be used inside 'cpu'" " element with 'match' attribute'")); goto cleanup; } def->type = VIR_CPU_TYPE_HOST; } else { def->type = VIR_CPU_TYPE_GUEST; } } else { def->type = type; } if ((cpuMode = virXMLPropString(ctxt->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 cleanup; } else { def->mode = virCPUModeTypeFromString(cpuMode); if (def->mode < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid mode attribute '%s'"), cpuMode); VIR_FREE(cpuMode); goto cleanup; } 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(ctxt->node, "match"); char *check; 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 cleanup; } } if ((check = virXMLPropString(ctxt->node, "check"))) { int value = virCPUCheckTypeFromString(check); VIR_FREE(check); if (value < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid check attribute for CPU " "specification")); goto cleanup; } def->check = value; } } 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 cleanup; } if ((def->arch = virArchFromString(arch)) == VIR_ARCH_NONE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown architecture %s"), arch); VIR_FREE(arch); goto cleanup; } VIR_FREE(arch); if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 && virXPathUInt("string(./microcode[1]/@version)", ctxt, &def->microcodeVersion) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("invalid microcode version")); goto cleanup; } } 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 cleanup; } 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 cleanup; } } 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 cleanup; } /* ensure that the string can be passed to qemu*/ if (strchr(vendor_id, ',')) { virReportError(VIR_ERR_XML_ERROR, "%s", _("vendor id is invalid")); goto cleanup; } 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 cleanup; } if (virXPathNode("./topology[1]", ctxt)) { unsigned long ul; if (virXPathULong("string(./topology[1]/@sockets)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'sockets' attribute in CPU topology")); goto cleanup; } def->sockets = (unsigned int) ul; if (virXPathULong("string(./topology[1]/@cores)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'cores' attribute in CPU topology")); goto cleanup; } def->cores = (unsigned int) ul; if (virXPathULong("string(./topology[1]/@threads)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto cleanup; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid CPU topology")); goto cleanup; } } if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0) goto cleanup; if (n > 0) { if (!def->model && def->mode == VIR_CPU_MODE_CUSTOM) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Non-empty feature list specified without " "CPU model")); goto cleanup; } if (VIR_RESIZE_N(def->features, def->nfeatures_max, def->nfeatures, n) < 0) goto cleanup; 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 cleanup; } } 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 cleanup; } 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 cleanup; } } def->features[i].name = name; def->features[i].policy = policy; } if (virXPathInt("count(./cache)", ctxt, &n) < 0) { goto cleanup; } else if (n > 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("at most one CPU cache element may be specified")); goto cleanup; } else if (n == 1) { int level = -1; char *strmode; int mode; if (virXPathBoolean("boolean(./cache[1]/@level)", ctxt) == 1 && (virXPathInt("string(./cache[1]/@level)", ctxt, &level) < 0 || level < 1 || level > 3)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid CPU cache level, must be in range [1,3]")); goto cleanup; } if (!(strmode = virXPathString("string(./cache[1]/@mode)", ctxt)) || (mode = virCPUCacheModeTypeFromString(strmode)) < 0) { VIR_FREE(strmode); virReportError(VIR_ERR_XML_ERROR, "%s", _("missing or invalid CPU cache mode")); goto cleanup; } VIR_FREE(strmode); if (VIR_ALLOC(def->cache) < 0) goto cleanup; def->cache->level = level; def->cache->mode = mode; } VIR_STEAL_PTR(*cpu, def); ret = 0; cleanup: ctxt->node = oldnode; VIR_FREE(fallback); VIR_FREE(vendor_id); VIR_FREE(nodes); virCPUDefFree(def); return ret; }
virNetDevIPRoutePtr virNetDevIPRouteParseXML(const char *errorDetail, xmlNodePtr node, xmlXPathContextPtr ctxt) { /* * virNetDevIPRoute object is already allocated as part * of an array. On failure clear: it out, but don't free it. */ virNetDevIPRoutePtr def = NULL; xmlNodePtr save; char *family = NULL; char *address = NULL, *netmask = NULL; char *gateway = NULL; unsigned long prefix = 0, metric = 0; int prefixRc, metricRc; bool hasPrefix = false; bool hasMetric = false; save = ctxt->node; ctxt->node = node; /* grab raw data from XML */ family = virXPathString("string(./@family)", ctxt); address = virXPathString("string(./@address)", ctxt); netmask = virXPathString("string(./@netmask)", ctxt); gateway = virXPathString("string(./@gateway)", ctxt); prefixRc = virXPathULong("string(./@prefix)", ctxt, &prefix); if (prefixRc == -2) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid prefix specified " "in route definition"), errorDetail); goto cleanup; } hasPrefix = (prefixRc == 0); metricRc = virXPathULong("string(./@metric)", ctxt, &metric); if (metricRc == -2) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid metric specified " "in route definition"), errorDetail); goto cleanup; } if (metricRc == 0) { hasMetric = true; if (metric == 0) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid metric value, must be > 0 " "in route definition"), errorDetail); goto cleanup; } } def = virNetDevIPRouteCreate(errorDetail, family, address, netmask, gateway, prefix, hasPrefix, metric, hasMetric); cleanup: ctxt->node = save; VIR_FREE(family); VIR_FREE(address); VIR_FREE(netmask); VIR_FREE(gateway); return def; }