diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 3ec1173c6f..6fd2189cd2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -411,6 +411,13 @@ <entry name='version'>0B98401 Pro</entry> <entry name='serial'>W1KS427111E</entry> </baseBoard> + <chassis> + <entry name='manufacturer'>Dell Inc.</entry> + <entry name='version'>2.12</entry> + <entry name='serial'>65X0XF2</entry> + <entry name='asset'>40000101</entry> + <entry name='sku'>Type3Sku1</entry> + </chassis> <oemStrings> <entry>myappname:some arbitrary data</entry> <entry>otherappname:more arbitrary data</entry> @@ -502,6 +509,23 @@ validation and date format checking, all values are passed as strings to the hypervisor driver. +
chassis
+
+ Since 4.1.0, this is block 3 of + SMBIOS, with entry names drawn from: +
+
manufacturer
+
Manufacturer of Chassis
+
version
+
Version of the Chassis
+
serial
+
Serial number
+
asset
+
Asset tag
+
sku
+
SKU number
+
+
oemStrings
This is block 11 of SMBIOS. This element should appear once and diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index ee6f83c96c..8165e699d6 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4895,6 +4895,18 @@ + + + + + + + + + + + + @@ -4940,6 +4952,16 @@ + + + manufacturer + version + serial + asset + sku + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3cfd6de5e0..2b99d32790 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14543,6 +14543,50 @@ virSysinfoOEMStringsParseXML(xmlXPathContextPtr ctxt, return ret; } + +static int +virSysinfoChassisParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virSysinfoChassisDefPtr *chassisdef) +{ + int ret = -1; + virSysinfoChassisDefPtr def; + + if (!xmlStrEqual(node->name, BAD_CAST "chassis")) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("XML does not contain expected 'chassis' element")); + return ret; + } + + if (VIR_ALLOC(def) < 0) + goto cleanup; + + def->manufacturer = + virXPathString("string(entry[@name='manufacturer'])", ctxt); + def->version = + virXPathString("string(entry[@name='version'])", ctxt); + def->serial = + virXPathString("string(entry[@name='serial'])", ctxt); + def->asset = + virXPathString("string(entry[@name='asset'])", ctxt); + def->sku = + virXPathString("string(entry[@name='sku'])", ctxt); + + if (!def->manufacturer && !def->version && + !def->serial && !def->asset && !def->sku) { + virSysinfoChassisDefFree(def); + def = NULL; + } + + *chassisdef = def; + def = NULL; + ret = 0; + cleanup: + virSysinfoChassisDefFree(def); + return ret; +} + + static virSysinfoDefPtr virSysinfoParseXML(xmlNodePtr node, xmlXPathContextPtr ctxt, @@ -14601,6 +14645,17 @@ virSysinfoParseXML(xmlNodePtr node, if (virSysinfoBaseBoardParseXML(ctxt, &def->baseBoard, &def->nbaseBoard) < 0) goto error; + /* Extract chassis related metadata */ + if ((tmpnode = virXPathNode("./chassis[1]", ctxt)) != NULL) { + oldnode = ctxt->node; + ctxt->node = tmpnode; + if (virSysinfoChassisParseXML(tmpnode, ctxt, &def->chassis) < 0) { + ctxt->node = oldnode; + goto error; + } + ctxt->node = oldnode; + } + /* Extract system related metadata */ if ((tmpnode = virXPathNode("./oemStrings[1]", ctxt)) != NULL) { oldnode = ctxt->node; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2524f7bc29..e57e0dc28a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2862,6 +2862,7 @@ virVasprintfInternal; # util/virsysinfo.h virSysinfoBaseBoardDefClear; virSysinfoBIOSDefFree; +virSysinfoChassisDefFree; virSysinfoDefFree; virSysinfoFormat; virSysinfoRead; diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c index e8d3371912..137f14ae44 100644 --- a/src/util/virsysinfo.c +++ b/src/util/virsysinfo.c @@ -108,6 +108,21 @@ void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDefPtr def) VIR_FREE(def->location); } + +void virSysinfoChassisDefFree(virSysinfoChassisDefPtr def) +{ + if (def == NULL) + return; + + VIR_FREE(def->manufacturer); + VIR_FREE(def->version); + VIR_FREE(def->serial); + VIR_FREE(def->asset); + VIR_FREE(def->sku); + VIR_FREE(def); +} + + void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def) { size_t i; @@ -143,6 +158,8 @@ void virSysinfoDefFree(virSysinfoDefPtr def) virSysinfoBaseBoardDefClear(def->baseBoard + i); VIR_FREE(def->baseBoard); + virSysinfoChassisDefFree(def->chassis); + for (i = 0; i < def->nprocessor; i++) { VIR_FREE(def->processor[i].processor_socket_destination); VIR_FREE(def->processor[i].processor_type); @@ -825,6 +842,68 @@ virSysinfoParseX86BaseBoard(const char *base, return ret; } + +static int +virSysinfoParseX86Chassis(const char *base, + virSysinfoChassisDefPtr *chassisdef) +{ + int ret = -1; + const char *cur, *eol = NULL; + virSysinfoChassisDefPtr def; + + if ((cur = strstr(base, "Chassis Information")) == NULL) + return 0; + + if (VIR_ALLOC(def) < 0) + return ret; + + base = cur; + if ((cur = strstr(base, "Manufacturer: ")) != NULL) { + cur += 14; + eol = strchr(cur, '\n'); + if (eol && VIR_STRNDUP(def->manufacturer, cur, eol - cur) < 0) + goto cleanup; + } + if ((cur = strstr(base, "Version: ")) != NULL) { + cur += 9; + eol = strchr(cur, '\n'); + if (eol && VIR_STRNDUP(def->version, cur, eol - cur) < 0) + goto cleanup; + } + if ((cur = strstr(base, "Serial Number: ")) != NULL) { + cur += 15; + eol = strchr(cur, '\n'); + if (eol && VIR_STRNDUP(def->serial, cur, eol - cur) < 0) + goto cleanup; + } + if ((cur = strstr(base, "Asset Tag: ")) != NULL) { + cur += 11; + eol = strchr(cur, '\n'); + if (eol && VIR_STRNDUP(def->sku, cur, eol - cur) < 0) + goto cleanup; + } + if ((cur = strstr(base, "SKU Number: ")) != NULL) { + cur += 12; + eol = strchr(cur, '\n'); + if (eol && VIR_STRNDUP(def->sku, cur, eol - cur) < 0) + goto cleanup; + } + + if (!def->manufacturer && !def->version && + !def->serial && !def->asset && !def->sku) { + virSysinfoChassisDefFree(def); + def = NULL; + } + + *chassisdef = def; + def = NULL; + ret = 0; + cleanup: + virSysinfoChassisDefFree(def); + return ret; +} + + static int virSysinfoParseX86Processor(const char *base, virSysinfoDefPtr ret) { @@ -1047,7 +1126,7 @@ virSysinfoReadX86(void) return NULL; } - cmd = virCommandNewArgList(path, "-q", "-t", "0,1,2,4,17", NULL); + cmd = virCommandNewArgList(path, "-q", "-t", "0,1,2,3,4,17", NULL); VIR_FREE(path); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) @@ -1067,6 +1146,9 @@ virSysinfoReadX86(void) if (virSysinfoParseX86BaseBoard(outbuf, &ret->baseBoard, &ret->nbaseBoard) < 0) goto error; + if (virSysinfoParseX86Chassis(outbuf, &ret->chassis) < 0) + goto error; + ret->nprocessor = 0; ret->processor = NULL; if (virSysinfoParseX86Processor(outbuf, ret) < 0) @@ -1202,6 +1284,31 @@ virSysinfoBaseBoardFormat(virBufferPtr buf, } } + +static void +virSysinfoChassisFormat(virBufferPtr buf, + virSysinfoChassisDefPtr def) +{ + if (!def) + return; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "%s\n", + def->manufacturer); + virBufferEscapeString(buf, "%s\n", + def->version); + virBufferEscapeString(buf, "%s\n", + def->serial); + virBufferEscapeString(buf, "%s\n", + def->asset); + virBufferEscapeString(buf, "%s\n", + def->sku); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + + static void virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def) { @@ -1354,6 +1461,7 @@ virSysinfoFormat(virBufferPtr buf, virSysinfoDefPtr def) virSysinfoBIOSFormat(&childrenBuf, def->bios); virSysinfoSystemFormat(&childrenBuf, def->system); virSysinfoBaseBoardFormat(&childrenBuf, def->baseBoard, def->nbaseBoard); + virSysinfoChassisFormat(&childrenBuf, def->chassis); virSysinfoProcessorFormat(&childrenBuf, def); virSysinfoMemoryFormat(&childrenBuf, def); virSysinfoOEMStringsFormat(&childrenBuf, def->oemStrings); @@ -1466,6 +1574,34 @@ virSysinfoBaseBoardIsEqual(virSysinfoBaseBoardDefPtr src, return identical; } + +static bool +virSysinfoChassisIsEqual(virSysinfoChassisDefPtr src, + virSysinfoChassisDefPtr dst) +{ + bool identical = false; + + if (!src && !dst) + return true; + + if ((src && !dst) || (!src && dst)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Target chassis does not match source")); + goto cleanup; + } + + CHECK_FIELD(manufacturer, "chassis vendor"); + CHECK_FIELD(version, "chassis version"); + CHECK_FIELD(serial, "chassis serial"); + CHECK_FIELD(asset, "chassis asset"); + CHECK_FIELD(sku, "chassis sku"); + + identical = true; + cleanup: + return identical; +} + + #undef CHECK_FIELD bool virSysinfoIsEqual(virSysinfoDefPtr src, @@ -1509,6 +1645,9 @@ bool virSysinfoIsEqual(virSysinfoDefPtr src, dst->baseBoard + i)) goto cleanup; + if (!virSysinfoChassisIsEqual(src->chassis, dst->chassis)) + goto cleanup; + identical = true; cleanup: diff --git a/src/util/virsysinfo.h b/src/util/virsysinfo.h index ecb3a36eb8..00a15dbf0d 100644 --- a/src/util/virsysinfo.h +++ b/src/util/virsysinfo.h @@ -98,6 +98,16 @@ struct _virSysinfoBaseBoardDef { /* XXX board type */ }; +typedef struct _virSysinfoChassisDef virSysinfoChassisDef; +typedef virSysinfoChassisDef *virSysinfoChassisDefPtr; +struct _virSysinfoChassisDef { + char *manufacturer; + char *version; + char *serial; + char *asset; + char *sku; +}; + typedef struct _virSysinfoOEMStringsDef virSysinfoOEMStringsDef; typedef virSysinfoOEMStringsDef *virSysinfoOEMStringsDefPtr; struct _virSysinfoOEMStringsDef { @@ -116,6 +126,8 @@ struct _virSysinfoDef { size_t nbaseBoard; virSysinfoBaseBoardDefPtr baseBoard; + virSysinfoChassisDefPtr chassis; + size_t nprocessor; virSysinfoProcessorDefPtr processor; @@ -130,6 +142,7 @@ virSysinfoDefPtr virSysinfoRead(void); void virSysinfoBIOSDefFree(virSysinfoBIOSDefPtr def); void virSysinfoSystemDefFree(virSysinfoSystemDefPtr def); void virSysinfoBaseBoardDefClear(virSysinfoBaseBoardDefPtr def); +void virSysinfoChassisDefFree(virSysinfoChassisDefPtr def); void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def); void virSysinfoDefFree(virSysinfoDefPtr def); diff --git a/tests/qemuxml2argvdata/smbios.xml b/tests/qemuxml2argvdata/smbios.xml index 319bdf61df..ad8d139375 100644 --- a/tests/qemuxml2argvdata/smbios.xml +++ b/tests/qemuxml2argvdata/smbios.xml @@ -26,6 +26,13 @@ CZC1065993 Upside down + + Dell Inc. + 2.12 + 65X0XF2 + 40000101 + Type3Sku1 + Hello World diff --git a/tests/qemuxml2xmloutdata/smbios.xml b/tests/qemuxml2xmloutdata/smbios.xml index cbe616c7da..d5f1d29610 100644 --- a/tests/qemuxml2xmloutdata/smbios.xml +++ b/tests/qemuxml2xmloutdata/smbios.xml @@ -26,6 +26,13 @@ CZC1065993 Upside down + + Dell Inc. + 2.12 + 65X0XF2 + 40000101 + Type3Sku1 + Hello World