static int virInterfaceDefParseProtoIPv6(virInterfaceProtocolDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr dhcp, autoconf; xmlNodePtr *ipNodes = NULL; int nIpNodes, ii, ret = -1; char *tmp; tmp = virXPathString("string(./route[1]/@gateway)", ctxt); def->gateway = tmp; autoconf = virXPathNode("./autoconf", ctxt); if (autoconf != NULL) def->autoconf = 1; dhcp = virXPathNode("./dhcp", ctxt); if (dhcp != NULL) { ret = virInterfaceDefParseDhcp(def, dhcp, ctxt); if (ret != 0) return ret; } nIpNodes = virXPathNodeSet("./ip", ctxt, &ipNodes); if (nIpNodes < 0) return -1; if (ipNodes == NULL) return 0; if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) { virReportOOMError(); goto error; } def->nips = 0; for (ii = 0; ii < nIpNodes; ii++) { virInterfaceIpDefPtr ip; if (VIR_ALLOC(ip) < 0) { virReportOOMError(); goto error; } ctxt->node = ipNodes[ii]; ret = virInterfaceDefParseIp(ip, ctxt); if (ret != 0) { virInterfaceIpDefFree(ip); goto error; } def->ips[def->nips++] = ip; } ret = 0; error: VIR_FREE(ipNodes); return ret; }
static char * getMetadataFromXML(virDomainPtr dom) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr node; char *xml = NULL; char *ret = NULL; if (!(xml = virDomainGetXMLDesc(dom, 0))) goto cleanup; if (!(doc = virXMLParseStringCtxt(xml, "(domain_definition)", &ctxt))) goto cleanup; if (!(node = virXPathNode("//metadata/*", ctxt))) goto cleanup; ret = virXMLNodeToString(node->doc, node); cleanup: VIR_FREE(xml); xmlFreeDoc(doc); xmlXPathFreeContext(ctxt); return ret; }
static int virInterfaceDefParseProtoIPv4(virInterfaceProtocolDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr dhcp; xmlNodePtr *ipNodes = NULL; int nIpNodes, ret = -1; size_t i; char *tmp; tmp = virXPathString("string(./route[1]/@gateway)", ctxt); def->gateway = tmp; dhcp = virXPathNode("./dhcp", ctxt); if (dhcp != NULL) { if (virInterfaceDefParseDhcp(def, dhcp, ctxt) < 0) return -1; } nIpNodes = virXPathNodeSet("./ip", ctxt, &ipNodes); if (nIpNodes < 0) return -1; if (ipNodes == NULL) return 0; if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) goto error; def->nips = 0; for (i = 0; i < nIpNodes; i++) { virInterfaceIpDefPtr ip; if (VIR_ALLOC(ip) < 0) goto error; ctxt->node = ipNodes[i]; if (virInterfaceDefParseIp(ip, ctxt) < 0) { virInterfaceIpDefFree(ip); goto error; } def->ips[def->nips++] = ip; } ret = 0; error: VIR_FREE(ipNodes); return ret; }
/* flags is bitwise-or of virDomainSnapshotParseFlags. * If flags does not include VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE, then * caps and expectedVirtTypes are ignored. */ virDomainSnapshotDefPtr virDomainSnapshotDefParseString(const char *xmlStr, virCapsPtr caps, unsigned int expectedVirtTypes, unsigned int flags) { xmlXPathContextPtr ctxt = NULL; xmlDocPtr xml = NULL; virDomainSnapshotDefPtr def = NULL; virDomainSnapshotDefPtr ret = NULL; xmlNodePtr *nodes = NULL; int i; char *creation = NULL, *state = NULL; struct timeval tv; int active; char *tmp; int keepBlanksDefault = xmlKeepBlanksDefault(0); char *memorySnapshot = NULL; char *memoryFile = NULL; bool offline = !!(flags & VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE); xml = virXMLParseCtxt(NULL, xmlStr, _("(domain_snapshot)"), &ctxt); if (!xml) { xmlKeepBlanksDefault(keepBlanksDefault); return NULL; } xmlKeepBlanksDefault(keepBlanksDefault); if (VIR_ALLOC(def) < 0) { virReportOOMError(); goto cleanup; } if (!xmlStrEqual(ctxt->node->name, BAD_CAST "domainsnapshot")) { virReportError(VIR_ERR_XML_ERROR, "%s", _("domainsnapshot")); goto cleanup; } gettimeofday(&tv, NULL); def->name = virXPathString("string(./name)", ctxt); if (def->name == NULL) { if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) { virReportError(VIR_ERR_XML_ERROR, "%s", _("a redefined snapshot must have a name")); goto cleanup; } if (virAsprintf(&def->name, "%lld", (long long)tv.tv_sec) < 0) { virReportOOMError(); goto cleanup; } } def->description = virXPathString("string(./description)", ctxt); if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) { if (virXPathLongLong("string(./creationTime)", ctxt, &def->creationTime) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing creationTime from existing snapshot")); goto cleanup; } def->parent = virXPathString("string(./parent/name)", ctxt); state = virXPathString("string(./state)", ctxt); if (state == NULL) { /* there was no state in an existing snapshot; this * should never happen */ virReportError(VIR_ERR_XML_ERROR, "%s", _("missing state from existing snapshot")); goto cleanup; } def->state = virDomainSnapshotStateTypeFromString(state); if (def->state < 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid state '%s' in domain snapshot XML"), state); goto cleanup; } offline = (def->state == VIR_DOMAIN_SHUTOFF || def->state == VIR_DOMAIN_DISK_SNAPSHOT); /* Older snapshots were created with just <domain>/<uuid>, and * lack domain/@type. In that case, leave dom NULL, and * clients will have to decide between best effort * initialization or outright failure. */ if ((tmp = virXPathString("string(./domain/@type)", ctxt))) { xmlNodePtr domainNode = virXPathNode("./domain", ctxt); VIR_FREE(tmp); if (!domainNode) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing domain in snapshot")); goto cleanup; } def->dom = virDomainDefParseNode(caps, xml, domainNode, expectedVirtTypes, (VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE)); if (!def->dom) goto cleanup; } else { VIR_WARN("parsing older snapshot that lacks domain"); } } else { def->creationTime = tv.tv_sec; } memorySnapshot = virXPathString("string(./memory/@snapshot)", ctxt); memoryFile = virXPathString("string(./memory/@file)", ctxt); if (memorySnapshot) { def->memory = virDomainSnapshotLocationTypeFromString(memorySnapshot); if (def->memory <= 0) { virReportError(VIR_ERR_XML_ERROR, _("unknown memory snapshot setting '%s'"), memorySnapshot); goto cleanup; } if (memoryFile && def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { virReportError(VIR_ERR_XML_ERROR, _("memory filename '%s' requires external snapshot"), memoryFile); goto cleanup; } if (!memoryFile && def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { virReportError(VIR_ERR_XML_ERROR, "%s", _("external memory snapshots require a filename")); goto cleanup; } } else if (memoryFile) { def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL; } else if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) { def->memory = (offline ? VIR_DOMAIN_SNAPSHOT_LOCATION_NONE : VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL); } if (offline && def->memory && def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) { virReportError(VIR_ERR_XML_ERROR, "%s", _("memory state cannot be saved with offline or " "disk-only snapshot")); goto cleanup; } def->file = memoryFile; memoryFile = NULL; if ((i = virXPathNodeSet("./disks/*", ctxt, &nodes)) < 0) goto cleanup; if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_DISKS) { def->ndisks = i; if (def->ndisks && VIR_ALLOC_N(def->disks, def->ndisks) < 0) { virReportOOMError(); goto cleanup; } for (i = 0; i < def->ndisks; i++) { if (virDomainSnapshotDiskDefParseXML(nodes[i], &def->disks[i]) < 0) goto cleanup; } VIR_FREE(nodes); } else if (i) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("unable to handle disk requests in snapshot")); goto cleanup; } if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL) { if (virXPathInt("string(./active)", ctxt, &active) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find 'active' element")); goto cleanup; } def->current = active != 0; } ret = def; cleanup: VIR_FREE(creation); VIR_FREE(state); VIR_FREE(nodes); VIR_FREE(memorySnapshot); VIR_FREE(memoryFile); xmlXPathFreeContext(ctxt); if (ret == NULL) virDomainSnapshotDefFree(def); xmlFreeDoc(xml); 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; }
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; }
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; }
static virSecretDefPtr secretXMLParseNode(xmlDocPtr xml, xmlNodePtr root) { xmlXPathContextPtr ctxt = NULL; virSecretDefPtr def = NULL, ret = NULL; char *prop = NULL; char *uuidstr = NULL; if (!xmlStrEqual(root->name, BAD_CAST "secret")) { virReportError(VIR_ERR_XML_ERROR, _("unexpected root element <%s>, " "expecting <secret>"), root->name); goto cleanup; } ctxt = xmlXPathNewContext(xml); if (ctxt == NULL) { virReportOOMError(); goto cleanup; } ctxt->node = root; if (VIR_ALLOC(def) < 0) goto cleanup; prop = virXPathString("string(./@ephemeral)", ctxt); if (prop != NULL) { if (STREQ(prop, "yes")) { def->isephemeral = true; } else if (STREQ(prop, "no")) { def->isephemeral = false; } else { virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid value of 'ephemeral'")); goto cleanup; } VIR_FREE(prop); } prop = virXPathString("string(./@private)", ctxt); if (prop != NULL) { if (STREQ(prop, "yes")) { def->isprivate = true; } else if (STREQ(prop, "no")) { def->isprivate = false; } else { virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid value of 'private'")); goto cleanup; } VIR_FREE(prop); } uuidstr = virXPathString("string(./uuid)", ctxt); if (!uuidstr) { if (virUUIDGenerate(def->uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to generate UUID")); goto cleanup; } } else { if (virUUIDParse(uuidstr, def->uuid) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed uuid element")); goto cleanup; } VIR_FREE(uuidstr); } def->description = virXPathString("string(./description)", ctxt); if (virXPathNode("./usage", ctxt) != NULL && virSecretDefParseUsage(ctxt, def) < 0) goto cleanup; ret = def; def = NULL; cleanup: VIR_FREE(prop); VIR_FREE(uuidstr); virSecretDefFree(def); xmlXPathFreeContext(ctxt); return ret; }
static virInterfaceDefPtr virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { virInterfaceDefPtr def; int type; char *tmp; xmlNodePtr cur = ctxt->node; /* check @type */ tmp = virXPathString("string(./@type)", ctxt); if (tmp == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("interface misses the type attribute")); return NULL; } type = virInterfaceTypeFromString(tmp); if (type == -1) { virInterfaceReportError(VIR_ERR_XML_ERROR, _("unknown interface type %s"), tmp); VIR_FREE(tmp); return NULL; } VIR_FREE(tmp); if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (((parentIfType == VIR_INTERFACE_TYPE_BOND) && (type != VIR_INTERFACE_TYPE_ETHERNET)) || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE) && (type != VIR_INTERFACE_TYPE_ETHERNET) && (type != VIR_INTERFACE_TYPE_BOND) && (type != VIR_INTERFACE_TYPE_VLAN)) || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(VIR_ERR_XML_ERROR, _("interface has unsupported type '%s'"), virInterfaceTypeToString(type)); goto error; } def->type = type; switch (type) { case VIR_INTERFACE_TYPE_ETHERNET: if (virInterfaceDefParseName(def, ctxt) < 0) goto error; tmp = virXPathString("string(./mac/@address)", ctxt); if (tmp != NULL) def->mac = tmp; if (parentIfType == VIR_INTERFACE_TYPE_LAST) { /* only recognize these in toplevel bond interfaces */ if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; } break; case VIR_INTERFACE_TYPE_BRIDGE: { xmlNodePtr bridge; if (virInterfaceDefParseName(def, ctxt) < 0) goto error; if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; bridge = virXPathNode("./bridge[1]", ctxt); if (bridge == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bridge interface misses the bridge element")); goto error; } tmp = virXMLPropString(bridge, "stp"); def->data.bridge.stp = -1; if (tmp != NULL) { if (STREQ(tmp, "on")) { def->data.bridge.stp = 1; } else if (STREQ(tmp, "off")) { def->data.bridge.stp = 0; } else { virInterfaceReportError(VIR_ERR_XML_ERROR, _("bridge interface stp should be on or off got %s"), tmp); VIR_FREE(tmp); goto error; } VIR_FREE(tmp); } def->data.bridge.delay = virXMLPropString(bridge, "delay"); ctxt->node = bridge; virInterfaceDefParseBridge(def, ctxt); break; } case VIR_INTERFACE_TYPE_BOND: { xmlNodePtr bond; if (virInterfaceDefParseName(def, ctxt) < 0) goto error; if (parentIfType == VIR_INTERFACE_TYPE_LAST) { /* only recognize these in toplevel bond interfaces */ if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; } bond = virXPathNode("./bond[1]", ctxt); if (bond == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface misses the bond element")); goto error; } ctxt->node = bond; if (virInterfaceDefParseBond(def, ctxt) < 0) goto error; break; } case VIR_INTERFACE_TYPE_VLAN: { xmlNodePtr vlan; tmp = virXPathString("string(./@name)", ctxt); if (tmp != NULL) def->name = tmp; if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; vlan = virXPathNode("./vlan[1]", ctxt); if (vlan == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("vlan interface misses the vlan element")); goto error; } ctxt->node = vlan; if (virInterfaceDefParseVlan(def, ctxt) < 0) goto error; break; } } ctxt->node = cur; return def; error: ctxt->node = cur; virInterfaceDefFree(def); return NULL; }
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; }
static virStorageEncryptionPtr virStorageEncryptionParseXML(xmlXPathContextPtr ctxt) { xmlNodePtr *nodes = NULL; virStorageEncryptionPtr ret; char *format_str = NULL; int n; size_t i; if (VIR_ALLOC(ret) < 0) return NULL; if (!(format_str = virXPathString("string(./@format)", ctxt))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("unknown volume encryption format")); goto cleanup; } if ((ret->format = virStorageEncryptionFormatTypeFromString(format_str)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown volume encryption format type %s"), format_str); goto cleanup; } VIR_FREE(format_str); if ((n = virXPathNodeSet("./secret", ctxt, &nodes)) < 0) goto cleanup; if (n > 0) { if (VIR_ALLOC_N(ret->secrets, n) < 0) goto cleanup; ret->nsecrets = n; for (i = 0; i < n; i++) { if (!(ret->secrets[i] = virStorageEncryptionSecretParse(ctxt, nodes[i]))) goto cleanup; } VIR_FREE(nodes); } if (ret->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) { xmlNodePtr tmpnode; if ((tmpnode = virXPathNode("./cipher[1]", ctxt))) { if (virStorageEncryptionInfoParseCipher(tmpnode, &ret->encinfo) < 0) goto cleanup; } if ((tmpnode = virXPathNode("./ivgen[1]", ctxt))) { /* If no cipher node, then fail */ if (!ret->encinfo.cipher_name) { virReportError(VIR_ERR_XML_ERROR, "%s", _("ivgen element found, but cipher is missing")); goto cleanup; } if (virStorageEncryptionInfoParseIvgen(tmpnode, &ret->encinfo) < 0) goto cleanup; } } return ret; cleanup: VIR_FREE(format_str); VIR_FREE(nodes); virStorageEncryptionFree(ret); return NULL; }
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; }
/* * 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; }
static int virDomainNumaDefNodeDistanceParseXML(virDomainNumaPtr def, xmlXPathContextPtr ctxt, unsigned int cur_cell) { int ret = -1; int sibling; char *tmp = NULL; xmlNodePtr *nodes = NULL; size_t i, ndistances = def->nmem_nodes; if (ndistances == 0) return 0; /* check if NUMA distances definition is present */ if (!virXPathNode("./distances[1]", ctxt)) return 0; if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) <= 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("NUMA distances defined without siblings")); goto cleanup; } for (i = 0; i < sibling; i++) { virDomainNumaDistancePtr ldist, rdist; unsigned int sibling_id, sibling_value; /* siblings are in order of parsing or explicitly numbered */ if (!(tmp = virXMLPropString(nodes[i], "id"))) { virReportError(VIR_ERR_XML_ERROR, _("Missing 'id' attribute in NUMA " "distances under 'cell id %d'"), cur_cell); goto cleanup; } /* The "id" needs to be applicable */ if (virStrToLong_uip(tmp, NULL, 10, &sibling_id) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid 'id' attribute in NUMA " "distances for sibling: '%s'"), tmp); goto cleanup; } VIR_FREE(tmp); /* The "id" needs to be within numa/cell range */ if (sibling_id >= ndistances) { virReportError(VIR_ERR_XML_ERROR, _("'sibling_id %d' does not refer to a " "valid cell within NUMA 'cell id %d'"), sibling_id, cur_cell); goto cleanup; } /* We need a locality value. Check and correct * distance to local and distance to remote node. */ if (!(tmp = virXMLPropString(nodes[i], "value"))) { virReportError(VIR_ERR_XML_ERROR, _("Missing 'value' attribute in NUMA distances " "under 'cell id %d' for 'sibling id %d'"), cur_cell, sibling_id); goto cleanup; } /* The "value" needs to be applicable */ if (virStrToLong_uip(tmp, NULL, 10, &sibling_value) < 0) { virReportError(VIR_ERR_XML_ERROR, _("'value %s' is invalid for " "'sibling id %d' under NUMA 'cell id %d'"), tmp, sibling_id, cur_cell); goto cleanup; } VIR_FREE(tmp); /* Assure LOCAL_DISTANCE <= "value" <= UNREACHABLE * and correct LOCAL_DISTANCE setting if such applies. */ if ((sibling_value < LOCAL_DISTANCE || sibling_value > UNREACHABLE) || (sibling_id == cur_cell && sibling_value != LOCAL_DISTANCE) || (sibling_id != cur_cell && sibling_value == LOCAL_DISTANCE)) { virReportError(VIR_ERR_XML_ERROR, _("'value %d' is invalid for " "'sibling id %d' under NUMA 'cell id %d'"), sibling_value, sibling_id, cur_cell); goto cleanup; } /* Apply the local / remote distance */ ldist = def->mem_nodes[cur_cell].distances; if (!ldist) { if (VIR_ALLOC_N(ldist, ndistances) < 0) goto cleanup; ldist[cur_cell].value = LOCAL_DISTANCE; ldist[cur_cell].cellid = cur_cell; def->mem_nodes[cur_cell].ndistances = ndistances; def->mem_nodes[cur_cell].distances = ldist; } ldist[sibling_id].cellid = sibling_id; ldist[sibling_id].value = sibling_value; /* Apply symmetry if none given */ rdist = def->mem_nodes[sibling_id].distances; if (!rdist) { if (VIR_ALLOC_N(rdist, ndistances) < 0) goto cleanup; rdist[sibling_id].value = LOCAL_DISTANCE; rdist[sibling_id].cellid = sibling_id; def->mem_nodes[sibling_id].ndistances = ndistances; def->mem_nodes[sibling_id].distances = rdist; } rdist[cur_cell].cellid = cur_cell; if (!rdist[cur_cell].value) rdist[cur_cell].value = sibling_value; } ret = 0; cleanup: if (ret < 0) { for (i = 0; i < ndistances; i++) VIR_FREE(def->mem_nodes[i].distances); def->mem_nodes[i].ndistances = 0; } VIR_FREE(nodes); VIR_FREE(tmp); return ret; }
static qemuDomainJobInfoPtr qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt) { qemuDomainJobInfoPtr jobInfo = NULL; qemuMonitorMigrationStats *stats; xmlNodePtr save_ctxt = ctxt->node; if (!(ctxt->node = virXPathNode("./statistics", ctxt))) goto cleanup; if (VIR_ALLOC(jobInfo) < 0) goto cleanup; stats = &jobInfo->stats; jobInfo->status = QEMU_DOMAIN_JOB_STATUS_COMPLETED; virXPathULongLong("string(./started[1])", ctxt, &jobInfo->started); virXPathULongLong("string(./stopped[1])", ctxt, &jobInfo->stopped); virXPathULongLong("string(./sent[1])", ctxt, &jobInfo->sent); if (virXPathLongLong("string(./delta[1])", ctxt, &jobInfo->timeDelta) == 0) jobInfo->timeDeltaSet = true; virXPathULongLong("string(./" VIR_DOMAIN_JOB_TIME_ELAPSED "[1])", ctxt, &jobInfo->timeElapsed); if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_DOWNTIME "[1])", ctxt, &stats->downtime) == 0) stats->downtime_set = true; if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_SETUP_TIME "[1])", ctxt, &stats->setup_time) == 0) stats->setup_time_set = true; virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_TOTAL "[1])", ctxt, &stats->ram_total); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_PROCESSED "[1])", ctxt, &stats->ram_transferred); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_REMAINING "[1])", ctxt, &stats->ram_remaining); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_BPS "[1])", ctxt, &stats->ram_bps); if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_CONSTANT "[1])", ctxt, &stats->ram_duplicate) == 0) stats->ram_duplicate_set = true; virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_NORMAL "[1])", ctxt, &stats->ram_normal); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES "[1])", ctxt, &stats->ram_normal_bytes); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_DIRTY_RATE "[1])", ctxt, &stats->ram_dirty_rate); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_ITERATION "[1])", ctxt, &stats->ram_iteration); virXPathULongLong("string(./" VIR_DOMAIN_JOB_MEMORY_PAGE_SIZE "[1])", ctxt, &stats->ram_page_size); virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_TOTAL "[1])", ctxt, &stats->disk_total); virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_PROCESSED "[1])", ctxt, &stats->disk_transferred); virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_REMAINING "[1])", ctxt, &stats->disk_remaining); virXPathULongLong("string(./" VIR_DOMAIN_JOB_DISK_BPS "[1])", ctxt, &stats->disk_bps); if (virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_CACHE "[1])", ctxt, &stats->xbzrle_cache_size) == 0) stats->xbzrle_set = true; virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_BYTES "[1])", ctxt, &stats->xbzrle_bytes); virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_PAGES "[1])", ctxt, &stats->xbzrle_pages); virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES "[1])", ctxt, &stats->xbzrle_cache_miss); virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW "[1])", ctxt, &stats->xbzrle_overflow); virXPathInt("string(./" VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE "[1])", ctxt, &stats->cpu_throttle_percentage); cleanup: ctxt->node = save_ctxt; return jobInfo; }