[PATCH 1/1] vmx: Fix <genid/> mapping

Michal Privoznik mprivozn at redhat.com
Wed Sep 29 08:01:56 UTC 2021


Not a long ago I've introduced parsing of vmx.genid and
vmx.genidX properties. They map onto our <genid/> element. The
implementation was quite straightforward: the UUID which is 128
bits long is split into two equally long parts which I then put
next to each other and used virUUIDParse() to fill the UUID
buffer. However, as it turns out it is not that simple - VMX
apparently does swap some byte pairs in both Hi and Lo parts. Do
the reverse so that the UUID is true to its original value.

Mind you, this algorithm is heavily inspired by virt-v2v code:

https://github.com/libguestfs/virt-v2v/blob/981e0c6b2d2ae0093e3f31829a8d00b552898552/input/parse_domain_from_vmx.ml#L364

Fixes: 7d661d6e20fe82e5472d5ab6dcd97ed76291f256
Reported-by: Richard W.M. Jones <rjones at redhat.com>
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/vmx/vmx.c                            | 16 ++++++++++++----
 tests/vmx2xmldata/esx-in-the-wild-10.xml |  2 +-
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index d3540acd84..f0c30e60b6 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -1347,6 +1347,9 @@ virVMXParseGenID(virConf *conf,
 {
     long long vmid[2] = { 0 };
     g_autofree char *uuidstr = NULL;
+    size_t i;
+    /* This mapping comes from virt-v2v sources. */
+    const int uuidmap[] = {8, 10, 12, 14, 4, 6, 0, 2, 30, 28, 26, 24, 22, 20, 18, 16};
 
     if (virVMXGetConfigLong(conf, "vm.genid", &vmid[0], 0, true) < 0 ||
         virVMXGetConfigLong(conf, "vm.genidX", &vmid[1], 0, true) < 0)
@@ -1356,10 +1359,15 @@ virVMXParseGenID(virConf *conf,
         return 0;
 
     uuidstr = g_strdup_printf("%.16llx%.16llx", vmid[0], vmid[1]);
-    if (virUUIDParse(uuidstr, def->genid) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Could not parse UUID from string '%s'"), uuidstr);
-        return -1;
+    /* Ideally we would just call virUUIDParse() and be done, but it's not that
+     * simple. Some bytes in genid and genidX are swapped and we need to swap
+     * them back. This matches what virt-v2v does. */
+    for (i = 0; i < G_N_ELEMENTS(uuidmap); i++) {
+        int idx = uuidmap[i];
+        int val_hi = g_ascii_xdigit_value(uuidstr[idx]);
+        int val_lo = g_ascii_xdigit_value(uuidstr[idx + 1]);
+
+        def->genid[i] = 16 * val_hi + val_lo;
     }
     def->genidRequested = true;
 
diff --git a/tests/vmx2xmldata/esx-in-the-wild-10.xml b/tests/vmx2xmldata/esx-in-the-wild-10.xml
index 47ed637920..59cdc68bf3 100644
--- a/tests/vmx2xmldata/esx-in-the-wild-10.xml
+++ b/tests/vmx2xmldata/esx-in-the-wild-10.xml
@@ -1,7 +1,7 @@
 <domain type='vmware'>
   <name>w2019biosvmware</name>
   <uuid>421a6177-5aa9-abb7-5924-fc376c18a1b4</uuid>
-  <genid>13c67c91-9f47-526f-b0d6-e4dd2e4bb4f9</genid>
+  <genid>9f47526f-7c91-13c6-f9b4-4b2edde4d6b0</genid>
   <memory unit='KiB'>4194304</memory>
   <currentMemory unit='KiB'>4194304</currentMemory>
   <vcpu placement='static'>2</vcpu>
-- 
2.32.0




More information about the libvir-list mailing list