Changeset
docs/formatdomain.html.in                         |  29 ++++++
docs/news.xml                                     |  12 +++
docs/schemas/domaincommon.rng                     |   8 ++
src/conf/domain_conf.c                            |  81 +++++++++++++++-
src/conf/domain_conf.h                            |  19 +++-
src/conf/network_conf.c                           |   2 +-
src/conf/secret_conf.c                            |   2 +-
src/libxl/libxl_domain.c                          |   4 +-
src/openvz/openvz_conf.c                          |   2 +-
src/qemu/qemu_capabilities.c                      |   2 +
src/qemu/qemu_capabilities.h                      |   1 +
src/qemu/qemu_command.c                           |  31 ++++++
src/qemu/qemu_domain.c                            |  23 +++--
src/qemu/qemu_domain.h                            |   6 +-
src/qemu/qemu_driver.c                            |  31 ++++--
src/qemu/qemu_migration.c                         |   4 +-
src/qemu/qemu_process.c                           | 110 +++++++++++++++++++++-
src/qemu/qemu_process.h                           |   1 +
src/test/test_driver.c                            |   6 +-
src/xenconfig/xen_common.c                        |   2 +-
tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml |   1 +
tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml |   1 +
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml  |   1 +
tests/qemuxml2argvdata/genid-auto.args            |  21 +++++
tests/qemuxml2argvdata/genid-auto.xml             |  32 +++++++
tests/qemuxml2argvdata/genid.args                 |  21 +++++
tests/qemuxml2argvdata/genid.xml                  |  32 +++++++
tests/qemuxml2argvtest.c                          |   4 +
tests/qemuxml2xmloutdata/genid-active.xml         |  32 +++++++
tests/qemuxml2xmloutdata/genid-auto-active.xml    |  32 +++++++
tests/qemuxml2xmloutdata/genid-auto-inactive.xml  |  32 +++++++
tests/qemuxml2xmloutdata/genid-inactive.xml       |  32 +++++++
tests/qemuxml2xmltest.c                           |   5 +-
33 files changed, 585 insertions(+), 37 deletions(-)
create mode 100644 tests/qemuxml2argvdata/genid-auto.args
create mode 100644 tests/qemuxml2argvdata/genid-auto.xml
create mode 100644 tests/qemuxml2argvdata/genid.args
create mode 100644 tests/qemuxml2argvdata/genid.xml
create mode 100644 tests/qemuxml2xmloutdata/genid-active.xml
create mode 100644 tests/qemuxml2xmloutdata/genid-auto-active.xml
create mode 100644 tests/qemuxml2xmloutdata/genid-auto-inactive.xml
create mode 100644 tests/qemuxml2xmloutdata/genid-inactive.xml
Git apply log
Switched to a new branch '20180411201005.14749-1-jferlan@redhat.com'
Applying: Check return status for virUUIDGenerate
Applying: conf: Modify last arg to virDomainDefCopy
Applying: qemu: Add flags to qemuDomainMigratableDefCheckABIStability
Applying: conf: Add VM Generation ID to virDomainDef
Applying: conf: Add flag to regenerate genid for virDomainDefCopy
Applying: conf: Add VM Generation ID parse/format support
Applying: qemu: Add VM Generation ID device capability
Applying: qemu: Handle genid processing during startup/launch
Applying: qemu: Add VM Generation ID to qemu command line
Applying: docs: Add news article for VM Generation ID
Using index info to reconstruct a base tree...
M	docs/news.xml
Falling back to patching base and 3-way merge...
Auto-merging docs/news.xml
To https://github.com/patchew-project/libvirt
 * [new tag]         patchew/20180411201005.14749-1-jferlan@redhat.com -> patchew/20180411201005.14749-1-jferlan@redhat.com
Test passed: syntax-check

loading

[libvirt] [PATCH 00/10] Add support for VM Generation ID (vmgenid)
Posted by John Ferlan, 1 week ago
As a result of the RFC:

https://www.redhat.com/archives/libvir-list/2018-March/msg01214.html

Patches to support changes for

https://bugzilla.redhat.com/show_bug.cgi?id=1149445

The first patch isn't necessarily related, but since it I was looking
at the all the virUUIDGenerate calls, I figured I'd include it here.
It can be consider separately.

I did leave in the possibility that someone can supply a GUID in the
XML; however, that can be removed - requiring that just the <genid/>
exists and forcing every usage to generate the GUID. The spec isn't
100% clear on whether that's a valid use. One area which I'm still a
little bit fuzzy on is the snapshot functionality. The transitions
while running won't work unless/until the qemu command to set the
genid GUID value are accepted. It'd be tough to fail, but according
to how I've read the spec it'd be required to change the GUID value
and since we cannot do so, failure is the only option.

John Ferlan (10):
  Check return status for virUUIDGenerate
  conf: Modify last arg to virDomainDefCopy
  qemu: Add flags to qemuDomainMigratableDefCheckABIStability
  conf: Add VM Generation ID to virDomainDef
  conf: Add flag to regenerate genid for virDomainDefCopy
  conf: Add VM Generation ID parse/format support
  qemu: Add VM Generation ID device capability
  qemu: Handle genid processing during startup/launch
  qemu: Add VM Generation ID to qemu command line
  docs: Add news article for VM Generation ID

 docs/formatdomain.html.in                         |  29 ++++++
 docs/news.xml                                     |  12 +++
 docs/schemas/domaincommon.rng                     |   8 ++
 src/conf/domain_conf.c                            |  81 +++++++++++++++-
 src/conf/domain_conf.h                            |  19 +++-
 src/conf/network_conf.c                           |   2 +-
 src/conf/secret_conf.c                            |   2 +-
 src/libxl/libxl_domain.c                          |   4 +-
 src/openvz/openvz_conf.c                          |   2 +-
 src/qemu/qemu_capabilities.c                      |   2 +
 src/qemu/qemu_capabilities.h                      |   1 +
 src/qemu/qemu_command.c                           |  31 ++++++
 src/qemu/qemu_domain.c                            |  23 +++--
 src/qemu/qemu_domain.h                            |   6 +-
 src/qemu/qemu_driver.c                            |  31 ++++--
 src/qemu/qemu_migration.c                         |   4 +-
 src/qemu/qemu_process.c                           | 110 +++++++++++++++++++++-
 src/qemu/qemu_process.h                           |   1 +
 src/test/test_driver.c                            |   6 +-
 src/xenconfig/xen_common.c                        |   2 +-
 tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml |   1 +
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml |   1 +
 tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml  |   1 +
 tests/qemuxml2argvdata/genid-auto.args            |  21 +++++
 tests/qemuxml2argvdata/genid-auto.xml             |  32 +++++++
 tests/qemuxml2argvdata/genid.args                 |  21 +++++
 tests/qemuxml2argvdata/genid.xml                  |  32 +++++++
 tests/qemuxml2argvtest.c                          |   4 +
 tests/qemuxml2xmloutdata/genid-active.xml         |  32 +++++++
 tests/qemuxml2xmloutdata/genid-auto-active.xml    |  32 +++++++
 tests/qemuxml2xmloutdata/genid-auto-inactive.xml  |  32 +++++++
 tests/qemuxml2xmloutdata/genid-inactive.xml       |  32 +++++++
 tests/qemuxml2xmltest.c                           |   5 +-
 33 files changed, 585 insertions(+), 37 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/genid-auto.args
 create mode 100644 tests/qemuxml2argvdata/genid-auto.xml
 create mode 100644 tests/qemuxml2argvdata/genid.args
 create mode 100644 tests/qemuxml2argvdata/genid.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-active.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-auto-active.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-auto-inactive.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-inactive.xml

-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 01/10] Check return status for virUUIDGenerate
Posted by John Ferlan, 1 week ago
Although legal, a few paths were not checking a return value < 0
for failure instead they checked a non zero failure.

Clean them all up to be consistent.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/conf/domain_conf.c     | 2 +-
 src/conf/network_conf.c    | 2 +-
 src/conf/secret_conf.c     | 2 +-
 src/openvz/openvz_conf.c   | 2 +-
 src/xenconfig/xen_common.c | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d23182f18a..f57f956503 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18776,7 +18776,7 @@ virDomainDefParseXML(xmlDocPtr xml,
      * also serve as the uuid. */
     tmp = virXPathString("string(./uuid[1])", ctxt);
     if (!tmp) {
-        if (virUUIDGenerate(def->uuid)) {
+        if (virUUIDGenerate(def->uuid) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Failed to generate UUID"));
             goto error;
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 54109a3d2e..630a87fc07 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1619,7 +1619,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     /* Extract network uuid */
     tmp = virXPathString("string(./uuid[1])", ctxt);
     if (!tmp) {
-        if (virUUIDGenerate(def->uuid)) {
+        if (virUUIDGenerate(def->uuid) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Failed to generate UUID"));
             goto error;
diff --git a/src/conf/secret_conf.c b/src/conf/secret_conf.c
index 989705234c..7a2e4b28aa 100644
--- a/src/conf/secret_conf.c
+++ b/src/conf/secret_conf.c
@@ -177,7 +177,7 @@ secretXMLParseNode(xmlDocPtr xml, xmlNodePtr root)
 
     uuidstr = virXPathString("string(./uuid)", ctxt);
     if (!uuidstr) {
-        if (virUUIDGenerate(def->uuid)) {
+        if (virUUIDGenerate(def->uuid) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Failed to generate UUID"));
             goto cleanup;
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index 23a02d749e..deb2520ced 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -1020,7 +1020,7 @@ openvzSetUUID(int vpsid)
 {
     unsigned char uuid[VIR_UUID_BUFLEN];
 
-    if (virUUIDGenerate(uuid)) {
+    if (virUUIDGenerate(uuid) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("Failed to generate UUID"));
         return -1;
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
index bc43185363..7db365f363 100644
--- a/src/xenconfig/xen_common.c
+++ b/src/xenconfig/xen_common.c
@@ -202,7 +202,7 @@ xenConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid)
     }
 
     if (!(val = virConfGetValue(conf, name))) {
-        if (virUUIDGenerate(uuid)) {
+        if (virUUIDGenerate(uuid) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Failed to generate UUID"));
             return -1;
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 02/10] conf: Modify last arg to virDomainDefCopy
Posted by John Ferlan, 1 week ago
Rather than single boolean, let's create a virDomainDefCopyFlags
and have the last argument be an unsigned int using the new
VIR_DOMAIN_DEF_COPY_MIGRATABLE bit.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/conf/domain_conf.c   | 8 ++++----
 src/conf/domain_conf.h   | 6 +++++-
 src/libxl/libxl_domain.c | 4 ++--
 src/qemu/qemu_domain.c   | 5 +++--
 src/qemu/qemu_driver.c   | 5 +++--
 src/test/test_driver.c   | 5 +++--
 6 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f57f956503..5fdcddfa91 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3320,7 +3320,7 @@ virDomainObjSetDefTransient(virCapsPtr caps,
     if (domain->newDef)
         return 0;
 
-    if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt, NULL, false)))
+    if (!(domain->newDef = virDomainDefCopy(domain->def, caps, xmlopt, NULL, 0)))
         goto out;
 
     ret = 0;
@@ -27891,7 +27891,7 @@ virDomainDefCopy(virDomainDefPtr src,
                  virCapsPtr caps,
                  virDomainXMLOptionPtr xmlopt,
                  void *parseOpaque,
-                 bool migratable)
+                 unsigned int flags)
 {
     char *xml;
     virDomainDefPtr ret;
@@ -27899,7 +27899,7 @@ virDomainDefCopy(virDomainDefPtr src,
     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
 
-    if (migratable)
+    if (flags & VIR_DOMAIN_DEF_COPY_MIGRATABLE)
         format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE | VIR_DOMAIN_DEF_FORMAT_MIGRATABLE;
 
     /* Easiest to clone via a round-trip through XML.  */
@@ -27920,7 +27920,7 @@ virDomainObjCopyPersistentDef(virDomainObjPtr dom,
     virDomainDefPtr cur;
 
     cur = virDomainObjGetPersistentDef(caps, xmlopt, dom);
-    return virDomainDefCopy(cur, caps, xmlopt, NULL, false);
+    return virDomainDefCopy(cur, caps, xmlopt, NULL, 0);
 }
 
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 89a7131fdb..4ca22d3617 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2862,11 +2862,15 @@ virDomainDefPtr virDomainObjGetOneDefState(virDomainObjPtr vm,
                                            bool *state);
 virDomainDefPtr virDomainObjGetOneDef(virDomainObjPtr vm, unsigned int flags);
 
+typedef enum {
+    /* Set when creating a copy of a definition for the purpose of migration */
+    VIR_DOMAIN_DEF_COPY_MIGRATABLE = 1 << 0,
+} virDomainDefCopyFlags;
 virDomainDefPtr virDomainDefCopy(virDomainDefPtr src,
                                  virCapsPtr caps,
                                  virDomainXMLOptionPtr xmlopt,
                                  void *parseOpaque,
-                                 bool migratable);
+                                 unsigned int flags);
 virDomainDefPtr virDomainObjCopyPersistentDef(virDomainObjPtr dom,
                                               virCapsPtr caps,
                                               virDomainXMLOptionPtr xmlopt);
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index e76740247d..c58a9c7d72 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1443,8 +1443,8 @@ libxlDomainDefCheckABIStability(libxlDriverPrivatePtr driver,
     libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
     bool ret = false;
 
-    if (!(migratableDefSrc = virDomainDefCopy(src, cfg->caps, driver->xmlopt, NULL, true)) ||
-        !(migratableDefDst = virDomainDefCopy(dst, cfg->caps, driver->xmlopt, NULL, true)))
+    if (!(migratableDefSrc = virDomainDefCopy(src, cfg->caps, driver->xmlopt, NULL, VIR_DOMAIN_DEF_COPY_MIGRATABLE)) ||
+        !(migratableDefDst = virDomainDefCopy(dst, cfg->caps, driver->xmlopt, NULL, VIR_DOMAIN_DEF_COPY_MIGRATABLE)))
         goto cleanup;
 
     ret = virDomainDefCheckABIStability(migratableDefSrc,
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 100304fd05..6568054d7d 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6182,6 +6182,8 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver,
     virDomainDefPtr copy = NULL;
     virCapsPtr caps = NULL;
     virQEMUCapsPtr qemuCaps = NULL;
+    unsigned int copyFlags = (flags & VIR_DOMAIN_XML_MIGRATABLE) ?
+                             VIR_DOMAIN_DEF_COPY_MIGRATABLE : 0;
 
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto cleanup;
@@ -6189,8 +6191,7 @@ qemuDomainDefFormatBufInternal(virQEMUDriverPtr driver,
     if (!(flags & (VIR_DOMAIN_XML_UPDATE_CPU | VIR_DOMAIN_XML_MIGRATABLE)))
         goto format;
 
-    if (!(copy = virDomainDefCopy(def, caps, driver->xmlopt, NULL,
-                                  flags & VIR_DOMAIN_XML_MIGRATABLE)))
+    if (!(copy = virDomainDefCopy(def, caps, driver->xmlopt, NULL, copyFlags)))
         goto cleanup;
 
     def = copy;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5c31dfdd58..3fede93687 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15849,7 +15849,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     snap->def->current = true;
     if (snap->def->dom) {
         config = virDomainDefCopy(snap->def->dom, caps,
-                                  driver->xmlopt, NULL, true);
+                                  driver->xmlopt, NULL,
+                                  VIR_DOMAIN_DEF_COPY_MIGRATABLE);
         if (!config)
             goto endjob;
     }
@@ -20468,7 +20469,7 @@ qemuDomainGetFSInfo(virDomainPtr dom,
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto endjob;
 
-    if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, false)))
+    if (!(def = virDomainDefCopy(vm->def, caps, driver->xmlopt, NULL, 0)))
         goto endjob;
 
     agent = qemuDomainObjEnterAgent(vm);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 856869c9d3..f16bcf75de 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -6467,7 +6467,7 @@ testDomainSnapshotCreateXML(virDomainPtr domain,
                                           privconn->caps,
                                           privconn->xmlopt,
                                           NULL,
-                                          true)))
+                                          VIR_DOMAIN_DEF_COPY_MIGRATABLE)))
             goto cleanup;
 
         if (testDomainSnapshotAlignDisks(vm, def, flags) < 0)
@@ -6722,7 +6722,8 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
 
     snap->def->current = true;
     config = virDomainDefCopy(snap->def->dom, privconn->caps,
-                              privconn->xmlopt, NULL, true);
+                              privconn->xmlopt, NULL,
+                              VIR_DOMAIN_DEF_COPY_MIGRATABLE);
     if (!config)
         goto cleanup;
 
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 03/10] qemu: Add flags to qemuDomainMigratableDefCheckABIStability
Posted by John Ferlan, 1 week ago
Allow the caller to qemuDomainMigratableDefCheckABIStability to also
provide a flag to be used for virDomainDefCheckABIStabilityFlags.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/qemu/qemu_domain.c    | 18 ++++++++++++------
 src/qemu/qemu_domain.h    |  6 ++++--
 src/qemu/qemu_driver.c    |  7 ++++---
 src/qemu/qemu_migration.c |  4 ++--
 4 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 6568054d7d..9c4bdf1ee4 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -7997,12 +7997,14 @@ qemuDomainMigratableDefCheckABIStability(virQEMUDriverPtr driver,
                                          virDomainDefPtr src,
                                          virDomainDefPtr migratableSrc,
                                          virDomainDefPtr dst,
-                                         virDomainDefPtr migratableDst)
+                                         virDomainDefPtr migratableDst,
+                                         unsigned flags)
 {
+    flags |= VIR_DOMAIN_DEF_ABI_CHECK_SKIP_VOLATILE;
     if (!virDomainDefCheckABIStabilityFlags(migratableSrc,
                                             migratableDst,
                                             driver->xmlopt,
-                                            VIR_DOMAIN_DEF_ABI_CHECK_SKIP_VOLATILE))
+                                            flags))
         return false;
 
     /* Force update any skipped values from the volatile flag */
@@ -8018,7 +8020,8 @@ qemuDomainMigratableDefCheckABIStability(virQEMUDriverPtr driver,
 bool
 qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
                                virDomainDefPtr src,
-                               virDomainDefPtr dst)
+                               virDomainDefPtr dst,
+                               unsigned int flags)
 {
     virDomainDefPtr migratableDefSrc = NULL;
     virDomainDefPtr migratableDefDst = NULL;
@@ -8030,7 +8033,8 @@ qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
 
     ret = qemuDomainMigratableDefCheckABIStability(driver,
                                                    src, migratableDefSrc,
-                                                   dst, migratableDefDst);
+                                                   dst, migratableDefDst,
+                                                   flags);
 
  cleanup:
     virDomainDefFree(migratableDefSrc);
@@ -8042,7 +8046,8 @@ qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
 bool
 qemuDomainCheckABIStability(virQEMUDriverPtr driver,
                             virDomainObjPtr vm,
-                            virDomainDefPtr dst)
+                            virDomainDefPtr dst,
+                            unsigned int flags)
 {
     virDomainDefPtr migratableSrc = NULL;
     virDomainDefPtr migratableDst = NULL;
@@ -8056,7 +8061,8 @@ qemuDomainCheckABIStability(virQEMUDriverPtr driver,
 
     ret = qemuDomainMigratableDefCheckABIStability(driver,
                                                    vm->def, migratableSrc,
-                                                   dst, migratableDst);
+                                                   dst, migratableDst,
+                                                   flags);
 
  cleanup:
     VIR_FREE(xml);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 21e12f6594..73463a681e 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -718,11 +718,13 @@ int qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
 
 bool qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
                                     virDomainDefPtr src,
-                                    virDomainDefPtr dst);
+                                    virDomainDefPtr dst,
+                                    unsigned int flags);
 
 bool qemuDomainCheckABIStability(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
-                                 virDomainDefPtr dst);
+                                 virDomainDefPtr dst,
+                                 unsigned int flags);
 
 bool qemuDomainAgentAvailable(virDomainObjPtr vm,
                               bool reportError);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3fede93687..261b680775 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3387,7 +3387,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver,
                                             VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) {
             goto endjob;
         }
-        if (!qemuDomainCheckABIStability(driver, vm, def)) {
+        if (!qemuDomainCheckABIStability(driver, vm, def, 0)) {
             virDomainDefFree(def);
             goto endjob;
         }
@@ -15885,9 +15885,10 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                         goto endjob;
 
                     compatible = qemuDomainDefCheckABIStability(driver, vm->def,
-                                                                config);
+                                                                config, 0);
                 } else {
-                    compatible = qemuDomainCheckABIStability(driver, vm, config);
+                    compatible = qemuDomainCheckABIStability(driver, vm, config,
+                                                             0);
                 }
 
                 if (!compatible) {
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 256b994bd9..a949104f5a 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2163,7 +2163,7 @@ qemuMigrationSrcBeginPhase(virQEMUDriverPtr driver,
                                             VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
             goto cleanup;
 
-        if (!qemuDomainCheckABIStability(driver, vm, def))
+        if (!qemuDomainCheckABIStability(driver, vm, def, 0))
             goto cleanup;
 
         rv = qemuDomainDefFormatLive(driver, def, NULL, false, true);
@@ -2715,7 +2715,7 @@ qemuMigrationDstPrepareAny(virQEMUDriverPtr driver,
                 if (!newdef)
                     goto cleanup;
 
-                if (!qemuDomainDefCheckABIStability(driver, *def, newdef)) {
+                if (!qemuDomainDefCheckABIStability(driver, *def, newdef, 0)) {
                     virDomainDefFree(newdef);
                     goto cleanup;
                 }
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 04/10] conf: Add VM Generation ID to virDomainDef
Posted by John Ferlan, 1 week ago
Add a genid[] field to be able to store a uuid-like GUID value.
Also add associated bool's to support VM Generation ID operation.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/conf/domain_conf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4ca22d3617..9da3b23393 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2322,6 +2322,11 @@ struct _virDomainDef {
     virDomainVirtType virtType;
     int id;
     unsigned char uuid[VIR_UUID_BUFLEN];
+
+    unsigned char genid[VIR_UUID_BUFLEN];
+    bool genidRequested;
+    bool genidGenerated;
+
     char *name;
     char *title;
     char *description;
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 05/10] conf: Add flag to regenerate genid for virDomainDefCopy
Posted by John Ferlan, 1 week ago
Add the VIR_DOMAIN_DEF_COPY_NEWGENID to indicate that the generated
domain definition should adjust the genid value before returning the
@def to the caller.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/conf/domain_conf.c | 12 ++++++++++++
 src/conf/domain_conf.h |  5 +++++
 src/qemu/qemu_driver.c |  3 ++-
 src/test/test_driver.c |  3 ++-
 4 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5fdcddfa91..385ba4ce8c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -27908,6 +27908,18 @@ virDomainDefCopy(virDomainDefPtr src,
 
     ret = virDomainDefParseString(xml, caps, xmlopt, parseOpaque, parse_flags);
 
+    /* If we have a genid and we're being called from a path that would
+     * require a different genid value, then regardless of whether it was
+     * generated or not generate a new one. */
+    if (ret && ret->genidRequested && (flags & VIR_DOMAIN_DEF_COPY_NEWGENID)) {
+        if (virUUIDGenerate(ret->genid)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Failed to generate a new genid"));
+            virDomainDefFree(ret);
+            ret = NULL;
+        }
+    }
+
     VIR_FREE(xml);
     return ret;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9da3b23393..dc748162b9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2870,6 +2870,11 @@ virDomainDefPtr virDomainObjGetOneDef(virDomainObjPtr vm, unsigned int flags);
 typedef enum {
     /* Set when creating a copy of a definition for the purpose of migration */
     VIR_DOMAIN_DEF_COPY_MIGRATABLE = 1 << 0,
+
+    /* Set when the copy should create a new genid value if supported
+     * the domain def.
+     */
+    VIR_DOMAIN_DEF_COPY_NEWGENID = 1 << 1,
 } virDomainDefCopyFlags;
 virDomainDefPtr virDomainDefCopy(virDomainDefPtr src,
                                  virCapsPtr caps,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 261b680775..56ac64630f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15850,7 +15850,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     if (snap->def->dom) {
         config = virDomainDefCopy(snap->def->dom, caps,
                                   driver->xmlopt, NULL,
-                                  VIR_DOMAIN_DEF_COPY_MIGRATABLE);
+                                  VIR_DOMAIN_DEF_COPY_MIGRATABLE |
+                                  VIR_DOMAIN_DEF_COPY_NEWGENID);
         if (!config)
             goto endjob;
     }
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index f16bcf75de..d6be51795f 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -6723,7 +6723,8 @@ testDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     snap->def->current = true;
     config = virDomainDefCopy(snap->def->dom, privconn->caps,
                               privconn->xmlopt, NULL,
-                              VIR_DOMAIN_DEF_COPY_MIGRATABLE);
+                              VIR_DOMAIN_DEF_COPY_MIGRATABLE |
+                              VIR_DOMAIN_DEF_COPY_NEWGENID);
     if (!config)
         goto cleanup;
 
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 06/10] conf: Add VM Generation ID parse/format support
Posted by John Ferlan, 1 week ago
The VM Generation ID is a mechanism to provide a unique 128-bit,
cryptographically random, and integer value identifier known as
the GUID (Globally Unique Identifier) to the guest OS. The value
is used to help notify the guest operating system when the virtual
machine is executed with a different configuration.

This patch adds support for a new "genid" XML element similar to
the "uuid" element. The "genid" element can have two forms "<genid/>"
or "<genid>$GUID</genid>". If the $GUID is not provided, libvirt
will generate one.

For the ABI checks add avoidance for the genid comparison if the
appropriate flag is set.

Since adding support for a generated GUID (or UUID like) value to
be displayed only for an active guest, modifying the xml2xml test
to include virrandommock.so is necessary since it will generate a
"known" UUID value that can be compared against for the active test.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 docs/formatdomain.html.in                        | 29 ++++++++++++
 docs/schemas/domaincommon.rng                    |  8 ++++
 src/conf/domain_conf.c                           | 59 ++++++++++++++++++++++++
 src/conf/domain_conf.h                           |  3 ++
 tests/qemuxml2argvdata/genid-auto.xml            | 32 +++++++++++++
 tests/qemuxml2argvdata/genid.xml                 | 32 +++++++++++++
 tests/qemuxml2xmloutdata/genid-active.xml        | 32 +++++++++++++
 tests/qemuxml2xmloutdata/genid-auto-active.xml   | 32 +++++++++++++
 tests/qemuxml2xmloutdata/genid-auto-inactive.xml | 32 +++++++++++++
 tests/qemuxml2xmloutdata/genid-inactive.xml      | 32 +++++++++++++
 tests/qemuxml2xmltest.c                          |  5 +-
 11 files changed, 295 insertions(+), 1 deletion(-)
 create mode 100644 tests/qemuxml2argvdata/genid-auto.xml
 create mode 100644 tests/qemuxml2argvdata/genid.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-active.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-auto-active.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-auto-inactive.xml
 create mode 100644 tests/qemuxml2xmloutdata/genid-inactive.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 5e99884dc5..fe9c3b19f0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -34,6 +34,7 @@
 &lt;domain type='kvm' id='1'&gt;
   &lt;name&gt;MyGuest&lt;/name&gt;
   &lt;uuid&gt;4dea22b3-1d52-d8f3-2516-782e98ab3fa0&lt;/uuid&gt;
+  &lt;genid&gt;43dc0cf8-809b-4adb-9bea-a9abb5f3d90e&lt;/genid&gt;
   &lt;title&gt;A short description - title - of the domain&lt;/title&gt;
   &lt;description&gt;Some human readable description&lt;/description&gt;
   &lt;metadata&gt;
@@ -61,6 +62,34 @@
         specification. <span class="since">Since 0.0.1, sysinfo
         since 0.8.7</span></dd>
 
+      <dt><code>genid</code></dt>
+      <dd><span class="since">Since 4.3.0</span>, the <code>genid</code>
+        element can be used to add a Virtual Machine Generation ID which
+        exposes a 128-bit, cryptographically random, integer value identifier,
+        referred to as a Globally Unique Identifier (GUID) using the same
+        format as the <code>uuid</code>. The value is used to help notify
+        the guest operating system when the virtual machine is executed
+        with a different configuration, such as:
+
+        <ul>
+          <li>snapshot execution</li>
+          <li>backup recovery</li>
+          <li>failover in a disaster recovery environment</li>
+          <li>creation from template (import, copy, clone)</li>
+        </ul>
+
+        The guest operating system notices the change and is then able to
+        react as appropriate by marking its copies of distributed databases
+        as dirty, re-initializing its random number generator, etc.
+
+        <p>
+        When a GUID value is not provided, e.g. using the XML syntax
+        &lt;genid/&gt;, then libvirt will automatically generate a GUID.
+        This is the recommended configuration since the hypervisor then
+        can handle changing the GUID value for specific state transitions.
+        Using a static GUID value may result in failures for starting from
+        snapshot, restoring from backup, starting a cloned domain, etc.</p></dd>
+
       <dt><code>title</code></dt>
       <dd>The optional element <code>title</code> provides space for a
         short description of the domain. The title should not contain
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4cab55f05d..1892a7c63c 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -502,6 +502,14 @@
           <ref name="UUID"/>
         </element>
       </optional>
+      <optional>
+        <element name="genid">
+          <choice>
+            <ref name="UUID"/>
+            <empty/>
+          </choice>
+        </element>
+      </optional>
     </interleave>
   </define>
   <define name="idmap">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 385ba4ce8c..0fa9386270 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18791,6 +18791,34 @@ virDomainDefParseXML(xmlDocPtr xml,
         VIR_FREE(tmp);
     }
 
+    /* Extract domain genid - a genid can either be provided or generated */
+    if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n > 0) {
+        if (n != 1) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                          _("element 'genid' can only appear once"));
+            goto error;
+        }
+        def->genidRequested = true;
+        if (!(tmp = virXPathString("string(./genid[1])", ctxt))) {
+            if (virUUIDGenerate(def->genid) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("Failed to generate genid"));
+                goto error;
+            }
+            def->genidGenerated = true;
+        } else {
+            if (virUUIDParse(tmp, def->genid) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("malformed genid element"));
+                goto error;
+            }
+        }
+    }
+    VIR_FREE(nodes);
+
     /* Extract short description of domain (title) */
     def->title = virXPathString("string(./title[1])", ctxt);
     if (def->title && strchr(def->title, '\n')) {
@@ -21903,6 +21931,26 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src,
         goto error;
     }
 
+    if (src->genidRequested != dst->genidRequested) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Target domain requested genid does not match source"));
+        goto error;
+    }
+
+    if (src->genidRequested &&
+        !(flags & VIR_DOMAIN_DEF_ABI_CHECK_SKIP_GENID) &&
+        memcmp(src->genid, dst->genid, VIR_UUID_BUFLEN) != 0) {
+        char guidsrc[VIR_UUID_STRING_BUFLEN];
+        char guiddst[VIR_UUID_STRING_BUFLEN];
+
+        virUUIDFormat(src->genid, guidsrc);
+        virUUIDFormat(dst->genid, guiddst);
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain genid %s does not match source %s"),
+                       guiddst, guidsrc);
+        goto error;
+    }
+
     /* Not strictly ABI related, but we want to make sure domains
      * don't get silently re-named through the backdoor when passing
      * custom XML into various APIs, since this would create havoc
@@ -26540,6 +26588,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     virUUIDFormat(uuid, uuidstr);
     virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
 
+    if (def->genidRequested) {
+        char genidstr[VIR_UUID_STRING_BUFLEN];
+
+        virUUIDFormat(def->genid, genidstr);
+        if (!def->genidGenerated ||
+            !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
+            virBufferAsprintf(buf, "<genid>%s</genid>\n", genidstr);
+        else
+            virBufferAddLit(buf, "<genid/>\n");
+    }
+
     virBufferEscapeString(buf, "<title>%s</title>\n", def->title);
 
     virBufferEscapeString(buf, "<description>%s</description>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index dc748162b9..dfd44bd9ff 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2947,6 +2947,9 @@ typedef enum {
     /* Set when domain lock must be released and there exists the possibility
      * that some external action could alter the value, such as cur_balloon. */
     VIR_DOMAIN_DEF_ABI_CHECK_SKIP_VOLATILE = 1 << 0,
+
+    /* Set when the ABI check should skip the genid comparison */
+    VIR_DOMAIN_DEF_ABI_CHECK_SKIP_GENID = 1 << 1,
 } virDomainDefABICheckFlags;
 
 virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr,
diff --git a/tests/qemuxml2argvdata/genid-auto.xml b/tests/qemuxml2argvdata/genid-auto.xml
new file mode 100644
index 0000000000..96ad9ddda8
--- /dev/null
+++ b/tests/qemuxml2argvdata/genid-auto.xml
@@ -0,0 +1,32 @@
+<domain type='qemu' id='1'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid/>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/genid.xml b/tests/qemuxml2argvdata/genid.xml
new file mode 100644
index 0000000000..fc41f2dd28
--- /dev/null
+++ b/tests/qemuxml2argvdata/genid.xml
@@ -0,0 +1,32 @@
+<domain type='qemu' id='1'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid>e9392370-2917-565e-692b-d057f46512d6</genid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/genid-active.xml b/tests/qemuxml2xmloutdata/genid-active.xml
new file mode 100644
index 0000000000..fc41f2dd28
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/genid-active.xml
@@ -0,0 +1,32 @@
+<domain type='qemu' id='1'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid>e9392370-2917-565e-692b-d057f46512d6</genid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/genid-auto-active.xml b/tests/qemuxml2xmloutdata/genid-auto-active.xml
new file mode 100644
index 0000000000..aeca0d7fc0
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/genid-auto-active.xml
@@ -0,0 +1,32 @@
+<domain type='qemu' id='1'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid>00010203-0405-4607-8809-0a0b0c0d0e0f</genid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/genid-auto-inactive.xml b/tests/qemuxml2xmloutdata/genid-auto-inactive.xml
new file mode 100644
index 0000000000..83c924395b
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/genid-auto-inactive.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid/>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/genid-inactive.xml b/tests/qemuxml2xmloutdata/genid-inactive.xml
new file mode 100644
index 0000000000..8bd526a7a9
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/genid-inactive.xml
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <genid>e9392370-2917-565e-692b-d057f46512d6</genid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <acpi/>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='ide' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index d123180e79..0240dae051 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -276,6 +276,8 @@ mymain(void)
     setenv("PATH", "/bin", 1);
 
     DO_TEST("minimal", NONE);
+    DO_TEST("genid", NONE);
+    DO_TEST("genid-auto", NONE);
     DO_TEST("machine-core-on", NONE);
     DO_TEST("machine-core-off", NONE);
     DO_TEST("machine-loadparm-multiple-disks-nets-s390", NONE);
@@ -1284,7 +1286,8 @@ mymain(void)
 }
 
 VIR_TEST_MAIN_PRELOAD(mymain,
-                      abs_builddir "/.libs/virpcimock.so")
+                      abs_builddir "/.libs/virpcimock.so",
+                      abs_builddir "/.libs/virrandommock.so")
 
 #else
 
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] conf: Add VM Generation ID parse/format support
Posted by Marc Hartmayer, 1 week ago
On Wed, Apr 11, 2018 at 10:10 PM +0200, John Ferlan <jferlan@redhat.com> wrote:
> The VM Generation ID is a mechanism to provide a unique 128-bit,
> cryptographically random, and integer value identifier known as
> the GUID (Globally Unique Identifier) to the guest OS. The value
> is used to help notify the guest operating system when the virtual
> machine is executed with a different configuration.
>
> This patch adds support for a new "genid" XML element similar to
> the "uuid" element. The "genid" element can have two forms "<genid/>"
> or "<genid>$GUID</genid>". If the $GUID is not provided, libvirt
> will generate one.
>
> For the ABI checks add avoidance for the genid comparison if the
> appropriate flag is set.
>
> Since adding support for a generated GUID (or UUID like) value to
> be displayed only for an active guest, modifying the xml2xml test
> to include virrandommock.so is necessary since it will generate a
> "known" UUID value that can be compared against for the active test.
>
> Signed-off-by: John Ferlan <jferlan@redhat.com>
> ---
>  docs/formatdomain.html.in                        | 29 ++++++++++++
>  docs/schemas/domaincommon.rng                    |  8 ++++
>  src/conf/domain_conf.c                           | 59 ++++++++++++++++++++++++
>  src/conf/domain_conf.h                           |  3 ++
>  tests/qemuxml2argvdata/genid-auto.xml            | 32 +++++++++++++
>  tests/qemuxml2argvdata/genid.xml                 | 32 +++++++++++++
>  tests/qemuxml2xmloutdata/genid-active.xml        | 32 +++++++++++++
>  tests/qemuxml2xmloutdata/genid-auto-active.xml   | 32 +++++++++++++
>  tests/qemuxml2xmloutdata/genid-auto-inactive.xml | 32 +++++++++++++
>  tests/qemuxml2xmloutdata/genid-inactive.xml      | 32 +++++++++++++
>  tests/qemuxml2xmltest.c                          |  5 +-
>  11 files changed, 295 insertions(+), 1 deletion(-)
>  create mode 100644 tests/qemuxml2argvdata/genid-auto.xml
>  create mode 100644 tests/qemuxml2argvdata/genid.xml
>  create mode 100644 tests/qemuxml2xmloutdata/genid-active.xml
>  create mode 100644 tests/qemuxml2xmloutdata/genid-auto-active.xml
>  create mode 100644 tests/qemuxml2xmloutdata/genid-auto-inactive.xml
>  create mode 100644 tests/qemuxml2xmloutdata/genid-inactive.xml
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index 5e99884dc5..fe9c3b19f0 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -34,6 +34,7 @@
>  &lt;domain type='kvm' id='1'&gt;
>    &lt;name&gt;MyGuest&lt;/name&gt;
>    &lt;uuid&gt;4dea22b3-1d52-d8f3-2516-782e98ab3fa0&lt;/uuid&gt;
> +  &lt;genid&gt;43dc0cf8-809b-4adb-9bea-a9abb5f3d90e&lt;/genid&gt;
>    &lt;title&gt;A short description - title - of the domain&lt;/title&gt;
>    &lt;description&gt;Some human readable description&lt;/description&gt;
>    &lt;metadata&gt;
> @@ -61,6 +62,34 @@
>          specification. <span class="since">Since 0.0.1, sysinfo
>          since 0.8.7</span></dd>
>
> +      <dt><code>genid</code></dt>
> +      <dd><span class="since">Since 4.3.0</span>, the <code>genid</code>
> +        element can be used to add a Virtual Machine Generation ID which
> +        exposes a 128-bit, cryptographically random, integer value identifier,
> +        referred to as a Globally Unique Identifier (GUID) using the same
> +        format as the <code>uuid</code>. The value is used to help notify
> +        the guest operating system when the virtual machine is executed
> +        with a different configuration, such as:
> +
> +        <ul>
> +          <li>snapshot execution</li>
> +          <li>backup recovery</li>
> +          <li>failover in a disaster recovery environment</li>
> +          <li>creation from template (import, copy, clone)</li>
> +        </ul>
> +
> +        The guest operating system notices the change and is then able to
> +        react as appropriate by marking its copies of distributed databases
> +        as dirty, re-initializing its random number generator, etc.
> +
> +        <p>
> +        When a GUID value is not provided, e.g. using the XML syntax
> +        &lt;genid/&gt;, then libvirt will automatically generate a GUID.
> +        This is the recommended configuration since the hypervisor then
> +        can handle changing the GUID value for specific state transitions.
> +        Using a static GUID value may result in failures for starting from
> +        snapshot, restoring from backup, starting a cloned domain, etc.</p></dd>
> +
>        <dt><code>title</code></dt>
>        <dd>The optional element <code>title</code> provides space for a
>          short description of the domain. The title should not contain
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 4cab55f05d..1892a7c63c 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -502,6 +502,14 @@
>            <ref name="UUID"/>
>          </element>
>        </optional>
> +      <optional>
> +        <element name="genid">
> +          <choice>
> +            <ref name="UUID"/>
> +            <empty/>
> +          </choice>
> +        </element>
> +      </optional>
>      </interleave>
>    </define>
>    <define name="idmap">
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 385ba4ce8c..0fa9386270 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -18791,6 +18791,34 @@ virDomainDefParseXML(xmlDocPtr xml,
>          VIR_FREE(tmp);
>      }
>
> +    /* Extract domain genid - a genid can either be provided or generated */
> +    if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
> +        goto error;
> +
> +    if (n > 0) {
> +        if (n != 1) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                          _("element 'genid' can only appear once"));
> +            goto error;
> +        }
> +        def->genidRequested = true;
> +        if (!(tmp = virXPathString("string(./genid[1])", ctxt))) {
> +            if (virUUIDGenerate(def->genid) < 0) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               "%s", _("Failed to generate genid"));
> +                goto error;
> +            }
> +            def->genidGenerated = true;
> +        } else {
> +            if (virUUIDParse(tmp, def->genid) < 0) {

You haven’t added these struct members to _virDomainDef (genid and
genidRequested) anywhere.

> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               "%s", _("malformed genid element"));
> +                goto error;
> +            }
> +        }
> +    }

[…snip]

--
Beste Grüße / Kind regards
   Marc Hartmayer

IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] conf: Add VM Generation ID parse/format support
Posted by John Ferlan, 1 week ago
[...]

>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>> index 385ba4ce8c..0fa9386270 100644
>> --- a/src/conf/domain_conf.c
>> +++ b/src/conf/domain_conf.c
>> @@ -18791,6 +18791,34 @@ virDomainDefParseXML(xmlDocPtr xml,
>>          VIR_FREE(tmp);
>>      }
>>
>> +    /* Extract domain genid - a genid can either be provided or generated */
>> +    if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
>> +        goto error;
>> +
>> +    if (n > 0) {
>> +        if (n != 1) {
>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>> +                          _("element 'genid' can only appear once"));
>> +            goto error;
>> +        }
>> +        def->genidRequested = true;
>> +        if (!(tmp = virXPathString("string(./genid[1])", ctxt))) {
>> +            if (virUUIDGenerate(def->genid) < 0) {
>> +                virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                               "%s", _("Failed to generate genid"));
>> +                goto error;
>> +            }
>> +            def->genidGenerated = true;
>> +        } else {
>> +            if (virUUIDParse(tmp, def->genid) < 0) {
> 
> You haven’t added these struct members to _virDomainDef (genid and
> genidRequested) anywhere.
> 

Patch 4 does that; however, there's been some list send/receive issues
over the last 24 hours, so if that hasn't shown up in your inbox maybe
it will today at some point...

I split things up that way to reduce the amount of lines to review in
one patch - in reality patches 4-6 could be one patch...

John

>> +                virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                               "%s", _("malformed genid element"));
>> +                goto error;
>> +            }
>> +        }
>> +    }
> 
> […snip]
> 

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] conf: Add VM Generation ID parse/format support
Posted by Marc Hartmayer, 1 week ago
On Thu, Apr 12, 2018 at 01:03 PM +0200, John Ferlan <jferlan@redhat.com> wrote:
> [...]
>
>>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>>> index 385ba4ce8c..0fa9386270 100644
>>> --- a/src/conf/domain_conf.c
>>> +++ b/src/conf/domain_conf.c
>>> @@ -18791,6 +18791,34 @@ virDomainDefParseXML(xmlDocPtr xml,
>>>          VIR_FREE(tmp);
>>>      }
>>>
>>> +    /* Extract domain genid - a genid can either be provided or generated */
>>> +    if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
>>> +        goto error;
>>> +
>>> +    if (n > 0) {
>>> +        if (n != 1) {
>>> +            virReportError(VIR_ERR_XML_ERROR, "%s",
>>> +                          _("element 'genid' can only appear once"));
>>> +            goto error;
>>> +        }
>>> +        def->genidRequested = true;
>>> +        if (!(tmp = virXPathString("string(./genid[1])", ctxt))) {
>>> +            if (virUUIDGenerate(def->genid) < 0) {
>>> +                virReportError(VIR_ERR_INTERNAL_ERROR,
>>> +                               "%s", _("Failed to generate genid"));
>>> +                goto error;
>>> +            }
>>> +            def->genidGenerated = true;
>>> +        } else {
>>> +            if (virUUIDParse(tmp, def->genid) < 0) {
>>
>> You haven’t added these struct members to _virDomainDef (genid and
>> genidRequested) anywhere.
>>
>
> Patch 4 does that; however, there's been some list send/receive issues
> over the last 24 hours, so if that hasn't shown up in your inbox maybe
> it will today at some point...

Yay :D

>
> I split things up that way to reduce the amount of lines to review in
> one patch - in reality patches 4-6 could be one patch...
>
> John
>
>>> +                virReportError(VIR_ERR_INTERNAL_ERROR,
>>> +                               "%s", _("malformed genid element"));
>>> +                goto error;
>>> +            }
>>> +        }
>>> +    }
>>
>> […snip]
>>
>
--
Beste Grüße / Kind regards
   Marc Hartmayer

IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 07/10] qemu: Add VM Generation ID device capability
Posted by John Ferlan, 1 week ago
Add the query of the device objects for the vmgenid device

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/qemu/qemu_capabilities.c                      | 2 ++
 src/qemu/qemu_capabilities.h                      | 1 +
 tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 +
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 +
 tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml  | 1 +
 5 files changed, 6 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 91b7aa31ec..bd1d800098 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -468,6 +468,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "virtio-tablet-ccw",
               "qcow2-luks",
               "pcie-pci-bridge",
+              "vmgenid",
     );
 
 
@@ -1104,6 +1105,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "virtio-mouse-ccw", QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW },
     { "virtio-tablet-ccw", QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW },
     { "pcie-pci-bridge", QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE },
+    { "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index bec28cae92..a562385b4f 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -452,6 +452,7 @@ typedef enum {
     QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW, /* -device virtio-tablet-ccw */
     QEMU_CAPS_QCOW2_LUKS, /* qcow2 format support LUKS encryption */
     QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE, /* -device pcie-pci-bridge */
+    QEMU_CAPS_DEVICE_VMGENID, /* -device vmgenid */
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
index 4dd5602014..35c16e400e 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
@@ -230,6 +230,7 @@
   <flag name='isa-serial'/>
   <flag name='dump-completed'/>
   <flag name='qcow2-luks'/>
+  <flag name='vmgenid'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
   <microcodeVersion>344938</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
index 4ed2e1ea96..81515980b2 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
@@ -227,6 +227,7 @@
   <flag name='dump-completed'/>
   <flag name='qcow2-luks'/>
   <flag name='pcie-pci-bridge'/>
+  <flag name='vmgenid'/>
   <version>2011090</version>
   <kvmVersion>0</kvmVersion>
   <microcodeVersion>390060</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 13fc8c143f..972cee5f25 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -225,6 +225,7 @@
   <flag name='iscsi.password-secret'/>
   <flag name='isa-serial'/>
   <flag name='dump-completed'/>
+  <flag name='vmgenid'/>
   <version>2009000</version>
   <kvmVersion>0</kvmVersion>
   <microcodeVersion>320947</microcodeVersion>
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 08/10] qemu: Handle genid processing during startup/launch
Posted by John Ferlan, 1 week ago
Before we generate the command line for qemu, if the domain about to
be launched desires to utilize the VM Generation ID functionality, then
handle both the regenerating the GUID value for backup recovery (restore
operation) and the startup after snapshot as well as checking that the
genid value that's about to be placed on the command line doesn't
duplicate some other already running domain.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/qemu/qemu_driver.c  |  22 +++++++---
 src/qemu/qemu_process.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_process.h |   1 +
 3 files changed, 126 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 56ac64630f..c417680dac 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6611,7 +6611,8 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
     if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
                          asyncJob, "stdio", *fd, path, NULL,
                          VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
-                         VIR_QEMU_PROCESS_START_PAUSED) == 0)
+                         VIR_QEMU_PROCESS_START_PAUSED |
+                         VIR_QEMU_PROCESS_START_GEN_VMID) == 0)
         restored = true;
 
     if (intermediatefd != -1) {
@@ -15873,6 +15874,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
              * the migratable XML or it will always fail otherwise */
             if (config) {
                 bool compatible;
+                bool abiflags = VIR_DOMAIN_DEF_ABI_CHECK_SKIP_GENID;
 
                 /* Replace the CPU in config and put the original one in priv
                  * once we're done. When we have the updated CPU def in the
@@ -15886,10 +15888,19 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                         goto endjob;
 
                     compatible = qemuDomainDefCheckABIStability(driver, vm->def,
-                                                                config, 0);
+                                                                config, abiflags);
                 } else {
                     compatible = qemuDomainCheckABIStability(driver, vm, config,
-                                                             0);
+                                                             abiflags);
+                }
+
+                /* If using VM GenID, there is no way currently to change
+                 * the genid for the running guest, so set an error and
+                 * mark as incompatible. */
+                if (compatible && config->genidRequested) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("domain genid update requires restart"));
+                    compatible = false;
                 }
 
                 if (!compatible) {
@@ -15972,7 +15983,8 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                                   cookie ? cookie->cpu : NULL,
                                   QEMU_ASYNC_JOB_START, NULL, -1, NULL, snap,
                                   VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
-                                  VIR_QEMU_PROCESS_START_PAUSED);
+                                  VIR_QEMU_PROCESS_START_PAUSED |
+                                  VIR_QEMU_PROCESS_START_GEN_VMID);
             virDomainAuditStart(vm, "from-snapshot", rc >= 0);
             detail = VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT;
             event = virDomainEventLifecycleNewFromObj(vm,
@@ -16058,7 +16070,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                      VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED)) {
             /* Flush first event, now do transition 2 or 3 */
             bool paused = (flags & VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED) != 0;
-            unsigned int start_flags = 0;
+            unsigned int start_flags = VIR_QEMU_PROCESS_START_GEN_VMID;
 
             start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f02114c693..20fcdf7f26 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5882,6 +5882,107 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 
 
 /**
+ * qemuProcessCheckGenID:
+ * @vm: Domain to be checked
+ * @opaque: Domain about to be started
+ *
+ * For each running domain, let's make sure the domain to be started doesn't
+ * duplicate any running domain's genid GUID value
+ *
+ * Returns 0 on success, -1 on failure w/ error message set
+ */
+static int
+qemuProcessCheckGenID(virDomainObjPtr vm,
+                      void *opaque)
+{
+    int ret = 0;
+    virDomainObjPtr startvm = opaque;
+
+    /* Ignore ourselves as we're already locked */
+    if (vm == startvm)
+        return 0;
+
+    virObjectLock(vm);
+
+    if (!virDomainObjIsActive(vm))
+        goto cleanup;
+
+    if (!vm->def->genidRequested)
+        goto cleanup;
+
+    if (memcmp(startvm->def->genid, vm->def->genid, VIR_UUID_BUFLEN) == 0) {
+        /* For a generated value, just change it. Perhaps a result of
+         * not using virDomainDefCopy which generates a new genid when
+         * def->genidRequested is true. */
+        if (startvm->def->genidGenerated) {
+            if (virUUIDGenerate(startvm->def->genid) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("failed to regenerate genid"));
+                ret = -1;
+            }
+        } else {
+            char guidstr[VIR_UUID_STRING_BUFLEN];
+
+            virUUIDFormat(startvm->def->genid, guidstr);
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("domain '%s' already running with genid '%s'"),
+                           vm->def->name, guidstr);
+            ret = -1;
+        }
+        goto cleanup;
+    }
+
+ cleanup:
+    virObjectUnlock(vm);
+    return ret;
+}
+
+
+/**
+ * qemuProcessGenID:
+ * @driver: Pointer to driver
+ * @vm: Pointer to domain object
+ * @flags: qemuProcessStartFlags
+ *
+ * If this domain is requesting to use genid
+ */
+static int
+qemuProcessGenID(virQEMUDriverPtr driver,
+                 virDomainObjPtr vm,
+                 unsigned int flags)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    if (!vm->def->genidRequested)
+        return 0;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VMGENID)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                      _("this QEMU does not support the 'genid' capability"));
+        return -1;
+    }
+
+    /* If we are coming from a path where we must provide a new gen id
+     * value regardless of whether it was previously generated or provided,
+     * then generate a new GUID value before we build the command line. */
+    if (flags & VIR_QEMU_PROCESS_START_GEN_VMID) {
+        if (virUUIDGenerate(vm->def->genid)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("failed to regenerate genid"));
+            return -1;
+        }
+    }
+
+    /* Now let's make sure the genid this domain has is not duplicitous
+     * with something else running. */
+    if (virDomainObjListForEach(driver->domains, qemuProcessCheckGenID, vm) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+/**
  * qemuProcessLaunch:
  *
  * Launch a new QEMU process with stopped virtual CPUs.
@@ -5933,7 +6034,8 @@ qemuProcessLaunch(virConnectPtr conn,
     virCheckFlags(VIR_QEMU_PROCESS_START_COLD |
                   VIR_QEMU_PROCESS_START_PAUSED |
                   VIR_QEMU_PROCESS_START_AUTODESTROY |
-                  VIR_QEMU_PROCESS_START_NEW, -1);
+                  VIR_QEMU_PROCESS_START_NEW |
+                  VIR_QEMU_PROCESS_START_GEN_VMID, -1);
 
     cfg = virQEMUDriverGetConfig(driver);
 
@@ -5957,6 +6059,9 @@ qemuProcessLaunch(virConnectPtr conn,
         goto cleanup;
     logfile = qemuDomainLogContextGetWriteFD(logCtxt);
 
+    if (qemuProcessGenID(driver, vm, flags) < 0)
+        goto cleanup;
+
     VIR_DEBUG("Building emulator command line");
     if (!(cmd = qemuBuildCommandLine(driver,
                                      qemuDomainLogContextGetManager(logCtxt),
@@ -6317,7 +6422,8 @@ qemuProcessStart(virConnectPtr conn,
 
     virCheckFlagsGoto(VIR_QEMU_PROCESS_START_COLD |
                       VIR_QEMU_PROCESS_START_PAUSED |
-                      VIR_QEMU_PROCESS_START_AUTODESTROY, cleanup);
+                      VIR_QEMU_PROCESS_START_AUTODESTROY |
+                      VIR_QEMU_PROCESS_START_GEN_VMID, cleanup);
 
     if (!migrateFrom && !snapshot)
         flags |= VIR_QEMU_PROCESS_START_NEW;
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 2741115673..30a73ff3f1 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -78,6 +78,7 @@ typedef enum {
     VIR_QEMU_PROCESS_START_AUTODESTROY  = 1 << 2,
     VIR_QEMU_PROCESS_START_PRETEND      = 1 << 3,
     VIR_QEMU_PROCESS_START_NEW          = 1 << 4, /* internal, new VM is starting */
+    VIR_QEMU_PROCESS_START_GEN_VMID     = 1 << 5, /* Generate a new VMID */
 } qemuProcessStartFlags;
 
 int qemuProcessStart(virConnectPtr conn,
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 08/10] qemu: Handle genid processing during startup/launch
Posted by Daniel P. Berrangé, 1 week ago
On Wed, Apr 11, 2018 at 04:10:03PM -0400, John Ferlan wrote:
> Before we generate the command line for qemu, if the domain about to
> be launched desires to utilize the VM Generation ID functionality, then
> handle both the regenerating the GUID value for backup recovery (restore
> operation) and the startup after snapshot as well as checking that the
> genid value that's about to be placed on the command line doesn't
> duplicate some other already running domain.
> 
> Signed-off-by: John Ferlan <jferlan@redhat.com>
> ---
>  src/qemu/qemu_driver.c  |  22 +++++++---
>  src/qemu/qemu_process.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
>  src/qemu/qemu_process.h |   1 +
>  3 files changed, 126 insertions(+), 7 deletions(-)


> +    /* Now let's make sure the genid this domain has is not duplicitous
> +     * with something else running. */
> +    if (virDomainObjListForEach(driver->domains, qemuProcessCheckGenID, vm) < 0)
> +        return -1;

Is this really required  ?   AFAIK, the gen ID merely has to be unique within
the scope of the installed guest disk image, not amongst all VMs that exist.
If it was the latter, the check we're doing is pretty weak because it only
considers one host, not VMs on every other host.   IMHO this check is not
desirable because it adds mutex contention against every guest, into the
start up path and other code paths too.

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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 08/10] qemu: Handle genid processing during startup/launch
Posted by John Ferlan, 1 week ago

On 04/12/2018 07:13 AM, Daniel P. Berrangé wrote:
> On Wed, Apr 11, 2018 at 04:10:03PM -0400, John Ferlan wrote:
>> Before we generate the command line for qemu, if the domain about to
>> be launched desires to utilize the VM Generation ID functionality, then
>> handle both the regenerating the GUID value for backup recovery (restore
>> operation) and the startup after snapshot as well as checking that the
>> genid value that's about to be placed on the command line doesn't
>> duplicate some other already running domain.
>>
>> Signed-off-by: John Ferlan <jferlan@redhat.com>
>> ---
>>  src/qemu/qemu_driver.c  |  22 +++++++---
>>  src/qemu/qemu_process.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
>>  src/qemu/qemu_process.h |   1 +
>>  3 files changed, 126 insertions(+), 7 deletions(-)
> 
> 
>> +    /* Now let's make sure the genid this domain has is not duplicitous
>> +     * with something else running. */
>> +    if (virDomainObjListForEach(driver->domains, qemuProcessCheckGenID, vm) < 0)
>> +        return -1;
> 
> Is this really required  ?   AFAIK, the gen ID merely has to be unique within
> the scope of the installed guest disk image, not amongst all VMs that exist.
> If it was the latter, the check we're doing is pretty weak because it only
> considers one host, not VMs on every other host.   IMHO this check is not
> desirable because it adds mutex contention against every guest, into the
> start up path and other code paths too.
> 

Well it wasn't 100% clear from what I read whether it would be required.
I may have misread something along the way too with how/why the value
was being used with Active Directory and perhaps a cloned domain using
(or needing) some mechanism to distinguish between the two.

Still, in rereading the MS GenID paper again uniqueness between two
domains doesn't seem to be required (which is fine by me - I didn't like
the code either) since the AD issues seem to be time based to rolling
back using a snapshot.

John

FWIW: http://go.microsoft.com/fwlink/?LinkId=260709

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 08/10] qemu: Handle genid processing during startup/launch
Posted by Daniel P. Berrangé, 1 week ago
On Thu, Apr 12, 2018 at 07:54:57AM -0400, John Ferlan wrote:
> 
> 
> On 04/12/2018 07:13 AM, Daniel P. Berrangé wrote:
> > On Wed, Apr 11, 2018 at 04:10:03PM -0400, John Ferlan wrote:
> >> Before we generate the command line for qemu, if the domain about to
> >> be launched desires to utilize the VM Generation ID functionality, then
> >> handle both the regenerating the GUID value for backup recovery (restore
> >> operation) and the startup after snapshot as well as checking that the
> >> genid value that's about to be placed on the command line doesn't
> >> duplicate some other already running domain.
> >>
> >> Signed-off-by: John Ferlan <jferlan@redhat.com>
> >> ---
> >>  src/qemu/qemu_driver.c  |  22 +++++++---
> >>  src/qemu/qemu_process.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
> >>  src/qemu/qemu_process.h |   1 +
> >>  3 files changed, 126 insertions(+), 7 deletions(-)
> > 
> > 
> >> +    /* Now let's make sure the genid this domain has is not duplicitous
> >> +     * with something else running. */
> >> +    if (virDomainObjListForEach(driver->domains, qemuProcessCheckGenID, vm) < 0)
> >> +        return -1;
> > 
> > Is this really required  ?   AFAIK, the gen ID merely has to be unique within
> > the scope of the installed guest disk image, not amongst all VMs that exist.
> > If it was the latter, the check we're doing is pretty weak because it only
> > considers one host, not VMs on every other host.   IMHO this check is not
> > desirable because it adds mutex contention against every guest, into the
> > start up path and other code paths too.
> > 
> 
> Well it wasn't 100% clear from what I read whether it would be required.
> I may have misread something along the way too with how/why the value
> was being used with Active Directory and perhaps a cloned domain using
> (or needing) some mechanism to distinguish between the two.
> 
> Still, in rereading the MS GenID paper again uniqueness between two
> domains doesn't seem to be required (which is fine by me - I didn't like
> the code either) since the AD issues seem to be time based to rolling
> back using a snapshot.

In practice, unless someone uses tragically bad  UUID generator that
produces clashing strings, they're all going to be unique anyway. So
I think we're safe to drop the check and blame any mistakes on the mgmt
app using libvirt, if they occurr.

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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 09/10] qemu: Add VM Generation ID to qemu command line
Posted by John Ferlan, 1 week ago
https://bugzilla.redhat.com/show_bug.cgi?id=1149445

If the domain requests usage of the genid functionality,
then add the QEMU '-device vmgenid' to the command line
providing either the supplied or generated GUID value.

Add tests for both a generated and supplied GUID value.

Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 src/qemu/qemu_command.c                | 31 +++++++++++++++++++++++++++++++
 tests/qemuxml2argvdata/genid-auto.args | 21 +++++++++++++++++++++
 tests/qemuxml2argvdata/genid.args      | 21 +++++++++++++++++++++
 tests/qemuxml2argvtest.c               |  4 ++++
 4 files changed, 77 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/genid-auto.args
 create mode 100644 tests/qemuxml2argvdata/genid.args

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 955134d019..3b43cd4b56 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6023,6 +6023,34 @@ qemuBuildSmbiosCommandLine(virCommandPtr cmd,
 
 
 static int
+qemuBuildVMGenIDCommandLine(virCommandPtr cmd,
+                            const virDomainDef *def,
+                            virQEMUCapsPtr qemuCaps)
+{
+    virBuffer opts = VIR_BUFFER_INITIALIZER;
+    char guid[VIR_UUID_STRING_BUFLEN];
+
+    if (!def->genidRequested)
+        return 0;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VMGENID)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("genid is not supported with this QEMU binary"));
+        return -1;
+    }
+
+    virUUIDFormat(def->genid, guid);
+    virBufferAsprintf(&opts, "vmgenid,guid=%s,id=vmgenid0", guid);
+
+    virCommandAddArg(cmd, "-device");
+    virCommandAddArgBuffer(cmd, &opts);
+
+    virBufferFreeAndReset(&opts);
+    return 0;
+}
+
+
+static int
 qemuBuildSgaCommandLine(virCommandPtr cmd,
                         const virDomainDef *def,
                         virQEMUCapsPtr qemuCaps)
@@ -10078,6 +10106,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildSmbiosCommandLine(cmd, driver, def, qemuCaps) < 0)
         goto error;
 
+    if (qemuBuildVMGenIDCommandLine(cmd, def, qemuCaps) < 0)
+        goto error;
+
     /*
      * NB, -nographic *MUST* come before any serial, or monitor
      * or parallel port flags due to QEMU craziness, where it
diff --git a/tests/qemuxml2argvdata/genid-auto.args b/tests/qemuxml2argvdata/genid-auto.args
new file mode 100644
index 0000000000..980cc077b9
--- /dev/null
+++ b/tests/qemuxml2argvdata/genid-auto.args
@@ -0,0 +1,21 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-device vmgenid,guid=00010203-0405-4607-8809-0a0b0c0d0e0f,id=vmgenid0 \
+-nographic \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-boot c \
+-usb
diff --git a/tests/qemuxml2argvdata/genid.args b/tests/qemuxml2argvdata/genid.args
new file mode 100644
index 0000000000..0d5dfde98f
--- /dev/null
+++ b/tests/qemuxml2argvdata/genid.args
@@ -0,0 +1,21 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-device vmgenid,guid=e9392370-2917-565e-692b-d057f46512d6,id=vmgenid0 \
+-nographic \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-boot c \
+-usb
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 3a328e02a2..343d8eb221 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -731,6 +731,10 @@ mymain(void)
     DO_TEST("minimal", NONE);
     DO_TEST_PARSE_ERROR("minimal-no-memory", NONE);
     DO_TEST("minimal-msg-timestamp", QEMU_CAPS_MSG_TIMESTAMP);
+
+    DO_TEST("genid", QEMU_CAPS_DEVICE_VMGENID);
+    DO_TEST("genid-auto", QEMU_CAPS_DEVICE_VMGENID);
+
     DO_TEST("machine-aliases1", NONE);
     DO_TEST("machine-aliases2", QEMU_CAPS_KVM);
     DO_TEST("machine-core-on", QEMU_CAPS_MACHINE_OPT,
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 10/10] docs: Add news article for VM Generation ID
Posted by John Ferlan, 1 week ago
Signed-off-by: John Ferlan <jferlan@redhat.com>
---
 docs/news.xml | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/docs/news.xml b/docs/news.xml
index 798ab6da40..8246ef0509 100644
--- a/docs/news.xml
+++ b/docs/news.xml
@@ -44,6 +44,18 @@
           add this controller when traditional PCI devices are in use.
         </description>
       </change>
+      <change>
+        <summary>
+          Add support for VM Generation ID
+        </summary>
+        <description>
+          The VM Generatation ID exposes a 128-bit, cryptographically
+          random, integer value identifier, referred to as a Globally
+          Unique Identifier (GUID) to the guest in order to notify the
+          guest operating system when the virtual machine is executed
+          with a different configuration.
+        </description>
+      </change>
     </section>
     <section title="Improvements">
       <change>
-- 
2.13.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list