]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: Add support for setting Chassis SMBIOS data fields
authorZhuang Yanying <ann.zhuangyanying@huawei.com>
Wed, 14 Feb 2018 09:22:38 +0000 (17:22 +0800)
committerJohn Ferlan <jferlan@redhat.com>
Sat, 17 Feb 2018 12:36:46 +0000 (07:36 -0500)
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, add the following to the guest XML

    <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>

Signed-off-by: Zhuang Yanying <ann.zhuangyanying@huawei.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/libvirt_private.syms
src/util/virsysinfo.c
src/util/virsysinfo.h
tests/qemuxml2argvdata/smbios.xml
tests/qemuxml2xmloutdata/smbios.xml

index 3ec1173c6fafbf1b676199e3538d541076922627..6fd2189cd2f46859f6b93d0c733b40b3307a502c 100644 (file)
     &lt;entry name='version'&gt;0B98401 Pro&lt;/entry&gt;
     &lt;entry name='serial'&gt;W1KS427111E&lt;/entry&gt;
   &lt;/baseBoard&gt;
+  &lt;chassis&gt;
+    &lt;entry name='manufacturer'&gt;Dell Inc.&lt;/entry&gt;
+    &lt;entry name='version'&gt;2.12&lt;/entry&gt;
+    &lt;entry name='serial'&gt;65X0XF2&lt;/entry&gt;
+    &lt;entry name='asset'&gt;40000101&lt;/entry&gt;
+    &lt;entry name='sku'&gt;Type3Sku1&lt;/entry&gt;
+  &lt;/chassis&gt;
   &lt;oemStrings&gt;
     &lt;entry&gt;myappname:some arbitrary data&lt;/entry&gt;
     &lt;entry&gt;otherappname:more arbitrary data&lt;/entry&gt;
             validation and <code>date</code> format checking, all values are
             passed as strings to the hypervisor driver.
           </dd>
+          <dt><code>chassis</code></dt>
+          <dd>
+            <span class="since">Since 4.1.0,</span> 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
index ee6f83c96ca934a2231763b0a5643fa330781986..8165e699d67ef29264a2b8e0d1abf157d2271fc8 100644 (file)
             </oneOrMore>
           </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>
     </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>
index 3cfd6de5e0679162624d86eae586632b5140864a..2b99d32790d775481ebbb5b9ad37cd39148e031d 100644 (file)
@@ -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;
index 2524f7bc29b085ebab6b64cea4142aa3aa429c3d..e57e0dc28ac5d8ae0a80785ce78150ab585fcbb2 100644 (file)
@@ -2862,6 +2862,7 @@ virVasprintfInternal;
 # util/virsysinfo.h
 virSysinfoBaseBoardDefClear;
 virSysinfoBIOSDefFree;
+virSysinfoChassisDefFree;
 virSysinfoDefFree;
 virSysinfoFormat;
 virSysinfoRead;
index e8d337191244b4e6e4387addc08c636917f6deb4..137f14ae4497c71583522270a7e9c8a6b29091d3 100644 (file)
@@ -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, "<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)
 {
@@ -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:
index ecb3a36eb8811ec3f0de191044ff8625b9d83876..00a15dbf0dbb1de596bab7d7499ed3738c8bd31a 100644 (file)
@@ -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);
 
index 319bdf61dfa7c7e18bbd97aa726be3c423622f28..ad8d13937536638b143949dc036c049e26c71bb0 100644 (file)
       <entry name='asset'>CZC1065993</entry>
       <entry name='location'>Upside down</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>Hello</entry>
       <entry>World</entry>
index cbe616c7daa4d1222b548e268bf03c8d2cf66fe2..d5f1d2961048a8557c571360a1cc23bd1408bd4e 100644 (file)
       <entry name='asset'>CZC1065993</entry>
       <entry name='location'>Upside down</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>Hello</entry>
       <entry>World</entry>