[PATCH] virsysinfo: Parse OEM strings

Setting OEM strings for a domain was introduced in v4.1.0-rc1~315. However, any application that wanted to use them (e.g. to point to an URL where a config file is stored) had to 'dmidecode -u --oem-string N' (where N is index of the string). Well, we can expose them under our <sysinfo/> XML and if the domain is running Libvirt inside it can be obtained using virConnectGetSysinfo() API. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/util/virsysinfo.c | 60 ++++++++++++++++++++++++++++- tests/sysinfodata/x86sysinfo.data | 10 +++++ tests/sysinfodata/x86sysinfo.expect | 10 +++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c index 41f4d1cff9..94f7ca8811 100644 --- a/src/util/virsysinfo.c +++ b/src/util/virsysinfo.c @@ -919,6 +919,61 @@ virSysinfoParseX86Chassis(const char *base, } +static int +virSysinfoParseOEMStrings(const char *base, + virSysinfoOEMStringsDefPtr *stringsRet) +{ + virSysinfoOEMStringsDefPtr strings = NULL; + int ret = -1; + const char *cur; + + if (!(cur = strstr(base, "OEM Strings"))) + return 0; + + if (VIR_ALLOC(strings) < 0) + return -1; + + while ((cur = strstr(cur, "String "))) { + char *eol; + + cur += 7; + + if (!(eol = strchr(cur, '\n'))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed output of dmidecode")); + goto cleanup; + } + + while (g_ascii_isdigit(*cur)) + cur++; + + if (*cur != ':') { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed output of dmidecode")); + goto cleanup; + } + + cur += 2; + + virSkipSpacesBackwards(cur, &eol); + if (!eol) + continue; + + if (VIR_EXPAND_N(strings->values, strings->nvalues, 1) < 0) + goto cleanup; + + strings->values[strings->nvalues - 1] = g_strndup(cur, eol - cur); + } + + *stringsRet = g_steal_pointer(&strings); + ret = 0; + + cleanup: + virSysinfoOEMStringsDefFree(strings); + return ret; +} + + static int virSysinfoParseX86Processor(const char *base, virSysinfoDefPtr ret) { @@ -1132,7 +1187,7 @@ virSysinfoReadDMI(void) return NULL; } - cmd = virCommandNewArgList(path, "-q", "-t", "0,1,2,3,4,17", NULL); + cmd = virCommandNewArgList(path, "-q", "-t", "0,1,2,3,4,11,17", NULL); VIR_FREE(path); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) @@ -1155,6 +1210,9 @@ virSysinfoReadDMI(void) if (virSysinfoParseX86Chassis(outbuf, &ret->chassis) < 0) goto error; + if (virSysinfoParseOEMStrings(outbuf, &ret->oemStrings) < 0) + goto error; + ret->nprocessor = 0; ret->processor = NULL; if (virSysinfoParseX86Processor(outbuf, ret) < 0) diff --git a/tests/sysinfodata/x86sysinfo.data b/tests/sysinfodata/x86sysinfo.data index 426261041d..5615e144fb 100644 --- a/tests/sysinfodata/x86sysinfo.data +++ b/tests/sysinfodata/x86sysinfo.data @@ -81,3 +81,13 @@ Memory Device Serial Number: 29057112 Asset Tag: 0839 Part Number: IMSH2GS13A1F1C-10F + +OEM Strings + String 1: Default string + String 2: Default string + String 3: MIAMI + String 4: Default string + String 5: FFFFFFFFFFFFF + String 6: FFFFFFFFFFFFF + String 7: FFFFFFFFFFFFF + String 8: Default string diff --git a/tests/sysinfodata/x86sysinfo.expect b/tests/sysinfodata/x86sysinfo.expect index fcdd790cbd..118cc4277e 100644 --- a/tests/sysinfodata/x86sysinfo.expect +++ b/tests/sysinfodata/x86sysinfo.expect @@ -50,4 +50,14 @@ <entry name='serial_number'>29057112</entry> <entry name='part_number'>IMSH2GS13A1F1C-10F</entry> </memory_device> + <oemStrings> + <entry>Default string</entry> + <entry>Default string</entry> + <entry>MIAMI</entry> + <entry>Default string</entry> + <entry>FFFFFFFFFFFFF</entry> + <entry>FFFFFFFFFFFFF</entry> + <entry>FFFFFFFFFFFFF</entry> + <entry>Default string</entry> + </oemStrings> </sysinfo> -- 2.26.2

On Tue, Jun 02, 2020 at 12:53:18PM +0200, Michal Privoznik wrote:
Setting OEM strings for a domain was introduced in v4.1.0-rc1~315. However, any application that wanted to use them (e.g. to point to an URL where a config file is stored) had to 'dmidecode -u --oem-string N' (where N is index of the string). Well, we can expose them under our <sysinfo/> XML and if the domain is running Libvirt inside it can be obtained using virConnectGetSysinfo() API.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/util/virsysinfo.c | 60 ++++++++++++++++++++++++++++- tests/sysinfodata/x86sysinfo.data | 10 +++++ tests/sysinfodata/x86sysinfo.expect | 10 +++++ 3 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/tests/sysinfodata/x86sysinfo.data b/tests/sysinfodata/x86sysinfo.data index 426261041d..5615e144fb 100644 --- a/tests/sysinfodata/x86sysinfo.data +++ b/tests/sysinfodata/x86sysinfo.data @@ -81,3 +81,13 @@ Memory Device Serial Number: 29057112 Asset Tag: 0839 Part Number: IMSH2GS13A1F1C-10F + +OEM Strings + String 1: Default string + String 2: Default string + String 3: MIAMI + String 4: Default string + String 5: FFFFFFFFFFFFF + String 6: FFFFFFFFFFFFF + String 7: FFFFFFFFFFFFF + String 8: Default string
What does dmidecode do for escaping (if anything) if I set a string value of "Ha ha ha try parsing\n String 3: this correctly\n String 4:then" Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On 6/2/20 12:56 PM, Daniel P. Berrangé wrote:
On Tue, Jun 02, 2020 at 12:53:18PM +0200, Michal Privoznik wrote:
Setting OEM strings for a domain was introduced in v4.1.0-rc1~315. However, any application that wanted to use them (e.g. to point to an URL where a config file is stored) had to 'dmidecode -u --oem-string N' (where N is index of the string). Well, we can expose them under our <sysinfo/> XML and if the domain is running Libvirt inside it can be obtained using virConnectGetSysinfo() API.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/util/virsysinfo.c | 60 ++++++++++++++++++++++++++++- tests/sysinfodata/x86sysinfo.data | 10 +++++ tests/sysinfodata/x86sysinfo.expect | 10 +++++ 3 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/tests/sysinfodata/x86sysinfo.data b/tests/sysinfodata/x86sysinfo.data index 426261041d..5615e144fb 100644 --- a/tests/sysinfodata/x86sysinfo.data +++ b/tests/sysinfodata/x86sysinfo.data @@ -81,3 +81,13 @@ Memory Device Serial Number: 29057112 Asset Tag: 0839 Part Number: IMSH2GS13A1F1C-10F + +OEM Strings + String 1: Default string + String 2: Default string + String 3: MIAMI + String 4: Default string + String 5: FFFFFFFFFFFFF + String 6: FFFFFFFFFFFFF + String 7: FFFFFFFFFFFFF + String 8: Default string
What does dmidecode do for escaping (if anything) if I set a string value of
"Ha ha ha try parsing\n String 3: this correctly\n String 4:then"
This is what I put into domain XML: <sysinfo type='smbios'> <oemStrings> <entry>Hello</entry> <entry>World</entry> <entry>Ha ha ha try parsing\n String 3: this correctly\n String 4:then</entry> <entry>This is, more tricky value=escaped</entry> </oemStrings> </sysinfo> This is how it appeared on the cmd line: -smbios 'type=11,value=Hello,value=World,value=Ha ha ha try parsing\n String 3: this correctly\n String 4:then,value=This is,, more tricky value=escaped' \ Now, inside the guest, plain dmidecode replaces \n with a dot: # dmidecode -t 11 Handle 0x0E00, DMI type 11, 5 bytes OEM Strings String 1: Hello String 2: World String 3: Ha ha ha try parsing\n. String 3: this correctly\n. String 4:then String 4: This is, more tricky value=escaped But if I tell it to not decode entries, then it displays the string correctly: # dmidecode -u --oem-string 3 Ha ha ha try parsing\n String 3: this correctly\n String 4:then So maybe we should use the latter instead? We could use 'dmidecode -u --oem-string count' to get the number of strings and then iterate through each one of them. Michal

On Tue, Jun 02, 2020 at 03:11:25PM +0200, Michal Privoznik wrote:
On 6/2/20 12:56 PM, Daniel P. Berrangé wrote:
On Tue, Jun 02, 2020 at 12:53:18PM +0200, Michal Privoznik wrote:
Setting OEM strings for a domain was introduced in v4.1.0-rc1~315. However, any application that wanted to use them (e.g. to point to an URL where a config file is stored) had to 'dmidecode -u --oem-string N' (where N is index of the string). Well, we can expose them under our <sysinfo/> XML and if the domain is running Libvirt inside it can be obtained using virConnectGetSysinfo() API.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/util/virsysinfo.c | 60 ++++++++++++++++++++++++++++- tests/sysinfodata/x86sysinfo.data | 10 +++++ tests/sysinfodata/x86sysinfo.expect | 10 +++++ 3 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/tests/sysinfodata/x86sysinfo.data b/tests/sysinfodata/x86sysinfo.data index 426261041d..5615e144fb 100644 --- a/tests/sysinfodata/x86sysinfo.data +++ b/tests/sysinfodata/x86sysinfo.data @@ -81,3 +81,13 @@ Memory Device Serial Number: 29057112 Asset Tag: 0839 Part Number: IMSH2GS13A1F1C-10F + +OEM Strings + String 1: Default string + String 2: Default string + String 3: MIAMI + String 4: Default string + String 5: FFFFFFFFFFFFF + String 6: FFFFFFFFFFFFF + String 7: FFFFFFFFFFFFF + String 8: Default string
What does dmidecode do for escaping (if anything) if I set a string value of
"Ha ha ha try parsing\n String 3: this correctly\n String 4:then"
This is what I put into domain XML:
<sysinfo type='smbios'> <oemStrings> <entry>Hello</entry> <entry>World</entry> <entry>Ha ha ha try parsing\n String 3: this correctly\n String 4:then</entry> <entry>This is, more tricky value=escaped</entry> </oemStrings> </sysinfo>
This is how it appeared on the cmd line:
-smbios 'type=11,value=Hello,value=World,value=Ha ha ha try parsing\n String 3: this correctly\n String 4:then,value=This is,, more tricky value=escaped' \
Now, inside the guest, plain dmidecode replaces \n with a dot:
# dmidecode -t 11 Handle 0x0E00, DMI type 11, 5 bytes OEM Strings String 1: Hello String 2: World String 3: Ha ha ha try parsing\n. String 3: this correctly\n. String 4:then String 4: This is, more tricky value=escaped
But if I tell it to not decode entries, then it displays the string correctly:
# dmidecode -u --oem-string 3 Ha ha ha try parsing\n String 3: this correctly\n String 4:then
So maybe we should use the latter instead? We could use 'dmidecode -u --oem-string count' to get the number of strings and then iterate through each one of them.
It is a bit tedious having to run dmidecode multiple times, especially since there won't be any strings in most cases. With the normal format, we can reliably extract each string, but some chars might have been mangled. How about we keep your current code, but if we see a "." in a string, then we run "dmidecode -u --oem-string N" just for that particular string, in order to get the unmangled value. That will mean we only run dmidecode once majority of cases. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On 6/3/20 1:22 PM, Daniel P. Berrangé wrote:
With the normal format, we can reliably extract each string, but some chars might have been mangled. How about we keep your current code, but if we see a "." in a string, then we run "dmidecode -u --oem-string N" just for that particular string, in order to get the unmangled value.
That will mean we only run dmidecode once majority of cases.
Makes sense. Will post v2. Michal
participants (2)
-
Daniel P. Berrangé
-
Michal Privoznik