[PATCH] virsysinfo: Parse OEM strings

Michal Privoznik posted 1 patch 3 years, 10 months ago
Test syntax-check failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/fdaae8903ecca9d1135cff72f16e368197bfe29e.1591095198.git.mprivozn@redhat.com
There is a newer version of this series
src/util/virsysinfo.c               | 60 ++++++++++++++++++++++++++++-
tests/sysinfodata/x86sysinfo.data   | 10 +++++
tests/sysinfodata/x86sysinfo.expect | 10 +++++
3 files changed, 79 insertions(+), 1 deletion(-)
[PATCH] virsysinfo: Parse OEM strings
Posted by Michal Privoznik 3 years, 10 months ago
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

Re: [PATCH] virsysinfo: Parse OEM strings
Posted by Daniel P. Berrangé 3 years, 10 months ago
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 :|

Re: [PATCH] virsysinfo: Parse OEM strings
Posted by Michal Privoznik 3 years, 10 months ago
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

Re: [PATCH] virsysinfo: Parse OEM strings
Posted by Daniel P. Berrangé 3 years, 10 months ago
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 :|

Re: [PATCH] virsysinfo: Parse OEM strings
Posted by Michal Privoznik 3 years, 10 months ago
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