On 02/08/2018 02:05 AM, Zhuangyanying wrote:
From: Zhuang Yanying <ann.zhuangyanying(a)huawei.com>
Some applications inside VM need to access SMBIOS Chassis Asset Tag,
which should be emulated. It has already been realized in qemu,
SMBIOS: Build aggregate smbios tables and entry point
https://git.qemu.org/?p=qemu.git;a=commit;h=c97294ec1b9e36887e119589d4565...
but not in libvirt. we realize it here.
As an example, you could use something like
<chassis>
<entry name='manufacturer'>LENOVO</entry>
<entry name='version'>0B98401 Pro</entry>
<entry name='serial'>W1KS427111E</entry>
<entry name='asset'>344dfTYH#</entry>
</chassis>
---
src/conf/domain_conf.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_command.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/virsysinfo.c | 37 +++++++++++++++++++++++++++++++++++
src/util/virsysinfo.h | 13 +++++++++++++
4 files changed, 151 insertions(+)
Looks good so far - a few minor notes here, but you need a few more
adjustments as well.
I suggest looking at commit id 'a9a27e60' which added SMBIOS type 2
(baseboard) support in order to get an idea of the files that should be
changed along with those that you did change.
In particular, describing the <chassis> in formatdomain.html.in,
ensuring that the schema domaincommon.rng is updated to describe the new
XML, and finally xml2xml as well as xml2argv test adjustments that would
list the type 3 information for xml2xml and the command line for xml2argv.
NB: It's also desirable to create 2 patches from this one. The first
being the domain_conf, virsysinfo, docs, rng, and xml2xml with the
second being just the qemu_command and xml2argv. Finally a 3rd patch to
adjust docs/news.xml to describe the change.
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 34aae82..b0d5d68 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14506,6 +14506,47 @@ virSysinfoBaseBoardParseXML(xmlXPathContextPtr ctxt,
return ret;
}
More recent style is two empty lines between functions.
+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;
+}
Again 2 empty lines.
static int
virSysinfoOEMStringsParseXML(xmlXPathContextPtr ctxt,
@@ -14600,6 +14641,17 @@ virSysinfoParseXML(xmlNodePtr node,
if (virSysinfoBaseBoardParseXML(ctxt, &def->baseBoard,
&def->nbaseBoard) < 0)
goto error;
+ /* Extract chassis 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/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 24b434a..cf88e75 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5813,6 +5813,49 @@ qemuBuildSmbiosBaseBoardStr(virSysinfoBaseBoardDefPtr def)
return NULL;
}
Same w/ empty lines.
+static char *
+qemuBuildSmbiosChassisStr(virSysinfoChassisDefPtr def)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ if (!def)
+ return NULL;
+
+ virBufferAddLit(&buf, "type=3");
+
+ /* 2:Manufacturer */
+ virBufferAddLit(&buf, ",manufacturer=");
+ virQEMUBuildBufferEscapeComma(&buf, def->manufacturer);
+ /* 2:Version */
+ if (def->version) {
+ virBufferAddLit(&buf, ",version=");
+ virQEMUBuildBufferEscapeComma(&buf, def->version);
+ }
+ /* 2:Serial Number */
+ if (def->serial) {
+ virBufferAddLit(&buf, ",serial=");
+ virQEMUBuildBufferEscapeComma(&buf, def->serial);
+ }
+ /* 2:Asset Tag */
+ if (def->asset) {
+ virBufferAddLit(&buf, ",asset=");
+ virQEMUBuildBufferEscapeComma(&buf, def->asset);
+ }
+ /* 2:Sku */
+ if (def->sku) {
+ virBufferAddLit(&buf, ",sku=");
+ virQEMUBuildBufferEscapeComma(&buf, def->sku);
+ }
+
+ if (virBufferCheckError(&buf) < 0)
+ goto error;
+
+ return virBufferContentAndReset(&buf);
+
+ error:
+ virBufferFreeAndReset(&buf);
+ return NULL;
+}
again.
static char *
qemuBuildSmbiosOEMStringsStr(virSysinfoOEMStringsDefPtr def)
@@ -5905,6 +5948,12 @@ qemuBuildSmbiosCommandLine(virCommandPtr cmd,
VIR_FREE(smbioscmd);
}
+ smbioscmd = qemuBuildSmbiosChassisStr(source->chassis);
+ if (smbioscmd != NULL) {
+ virCommandAddArgList(cmd, "-smbios", smbioscmd, NULL);
+ VIR_FREE(smbioscmd);
+ }
+
if (source->oemStrings) {
if (!(smbioscmd = qemuBuildSmbiosOEMStringsStr(source->oemStrings)))
return -1;
diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c
index e8d3371..af434e0 100644
--- a/src/util/virsysinfo.c
+++ b/src/util/virsysinfo.c
@@ -108,6 +108,18 @@ 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);
Since this isn't a DefClear function like the BaseboardDefClear
+}
+
void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def)
{
size_t i;
@@ -143,6 +155,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);
@@ -1203,6 +1217,28 @@ virSysinfoBaseBoardFormat(virBufferPtr buf,
}
2 empty lines
static void
+virSysinfoChassisFormat(virBufferPtr buf, virSysinfoChassisDefPtr def)
Use multiple lines for args, eg.
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");
+}
+
2 empty lines
+static void
virSysinfoProcessorFormat(virBufferPtr buf, virSysinfoDefPtr def)
{
size_t i;
@@ -1354,6 +1390,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);
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);
Don't forget to update 'src/libvirt_private.syms' to appropriately add
the API (alphabetically after virSysinfoBIOSDefFree)
John
void virSysinfoOEMStringsDefFree(virSysinfoOEMStringsDefPtr def);
void virSysinfoDefFree(virSysinfoDefPtr def);