From: Zhuang Yanying <ann.zhuangyanying(a)huawei.com>
This type of information defines attributes of a system
chassis, such as SMBIOS Chassis Asset Tag.
access inside VM (for example)
Linux: /sys/class/dmi/id/chassis_asset_tag.
Windows: (Get-WmiObject Win32_SystemEnclosure).SMBIOSAssetTag
wirhin Windows PowerShell.
As an example, you could use something like
<chassis>
<entry name='manufacturer'>Huawei</entry>
<entry name='version'>To be filled by O.E.M.</entry>
<entry name='serial'>To be filled by O.E.M.</entry>
<entry name='asset'>To be filled by O.E.M.</entry>
<entry name='sku'>Type3Sku1</entry>
</chassis>
Signed-off-by: Zhuang Yanying <ann.zhuangyanying(a)huawei.com>
---
docs/formatdomain.html.in | 23 ++++++++
docs/schemas/domaincommon.rng | 22 +++++++
src/conf/domain_conf.c | 55 +++++++++++++++++
src/libvirt_private.syms | 1 +
src/util/virsysinfo.c | 133 +++++++++++++++++++++++++++++++++++++++++-
src/util/virsysinfo.h | 13 +++++
6 files changed, 246 insertions(+), 1 deletion(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3ec1173..bcbf6fd 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'>Huawei</entry>
+ <entry name='version'>To be filled by
O.E.M.</entry>
+ <entry name='serial'>To be filled by
O.E.M.</entry>
+ <entry name='asset'>To be filled by
O.E.M.</entry>
+ <entry name='sku'>Type3Sku1</entry>
+ </chassis>
<oemStrings>
<entry>myappname:some arbitrary data</entry>
<entry>otherappname:more arbitrary data</entry>
@@ -502,6 +509,22 @@
validation and <code>date</code> format checking, all values are
passed as strings to the hypervisor driver.
</dd>
+ <dt><code>chassis</code></dt>
+ <dd>
+ This is block 3 of SMBIOS, with entry names drawn from:
+ <dl>
+ <dt><code>manufacturer</code></dt>
+ <dd>Manufacturer of Chassis</dd>
+ <dt><code>version</code></dt>
+ <dd>Version of the Chassis</dd>
+ <dt><code>serial</code></dt>
+ <dd>Serial number</dd>
+ <dt><code>asset</code></dt>
+ <dd>Asset tag</dd>
+ <dt><code>sku</code></dt>
+ <dd>SKU number</dd>
+ </dl>
+ </dd>
<dt><code>oemStrings</code></dt>
<dd>
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 ee6f83c..8165e69 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4896,6 +4896,18 @@
</element>
</zeroOrMore>
<optional>
+ <element name="chassis">
+ <oneOrMore>
+ <element name="entry">
+ <attribute name="name">
+ <ref name="sysinfo-chassis-name"/>
+ </attribute>
+ <ref name="sysinfo-value"/>
+ </element>
+ </oneOrMore>
+ </element>
+ </optional>
+ <optional>
<element name="oemStrings">
<oneOrMore>
<element name="entry">
@@ -4940,6 +4952,16 @@
</choice>
</define>
+ <define name="sysinfo-chassis-name">
+ <choice>
+ <value>manufacturer</value>
+ <value>version</value>
+ <value>serial</value>
+ <value>asset</value>
+ <value>sku</value>
+ </choice>
+ </define>
+
<define name="sysinfo-value">
<data type="string"/>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fb732a0..e369235 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14542,6 +14542,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,
@@ -14600,6 +14644,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 3b14d7d..97e4c00 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2860,6 +2860,7 @@ virVasprintfInternal;
# util/virsysinfo.h
virSysinfoBaseBoardDefClear;
virSysinfoBIOSDefFree;
+virSysinfoChassisDefFree;
virSysinfoDefFree;
virSysinfoFormat;
virSysinfoRead;
diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c
index e8d3371..856215c 100644
--- a/src/util/virsysinfo.c
+++ b/src/util/virsysinfo.c
@@ -108,6 +108,19 @@ 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 +156,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);
@@ -826,6 +841,66 @@ virSysinfoParseX86BaseBoard(const char *base,
}
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)
{
const char *cur, *tmp_base;
@@ -1047,7 +1122,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 +1142,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)
@@ -1203,6 +1281,29 @@ virSysinfoBaseBoardFormat(virBufferPtr buf,
}
static void
+virSysinfoChassisFormat(virBufferPtr buf,
+ virSysinfoChassisDefPtr def)
+{
+ if (!def)
+ return;
+
+ virBufferAddLit(buf, "<chassis>\n");
+ virBufferAdjustIndent(buf, 2);
+ virBufferEscapeString(buf, "<entry
name='manufacturer'>%s</entry>\n",
+ def->manufacturer);
+ virBufferEscapeString(buf, "<entry
name='version'>%s</entry>\n",
+ def->version);
+ virBufferEscapeString(buf, "<entry
name='serial'>%s</entry>\n",
+ def->serial);
+ virBufferEscapeString(buf, "<entry
name='asset'>%s</entry>\n",
+ def->asset);
+ virBufferEscapeString(buf, "<entry
name='sku'>%s</entry>\n",
+ def->sku);
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</chassis>\n");
+}
+
+static void
virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def)
{
size_t i;
@@ -1354,6 +1455,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 +1568,32 @@ 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 +1637,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 ecb3a36..00a15db 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);
--
1.8.3.1