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 both require a new GUID to
be generated to allow the guest operating system to recognize the VM
is re-executing something that has already executed before.

Signed-off-by: John Ferlan <jfer...@redhat.com>
---
 src/qemu/qemu_driver.c  | 17 ++++++++++++++---
 src/qemu/qemu_process.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 src/qemu/qemu_process.h |  1 +
 3 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b697838070..7e968f475d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6554,7 +6554,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) {
@@ -15827,6 +15828,15 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr 
snapshot,
                     compatible = qemuDomainCheckABIStability(driver, vm, 
config);
                 }
 
+                /* 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) {
                     virErrorPtr err = virGetLastError();
 
@@ -15907,7 +15917,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,
@@ -15993,7 +16004,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 5b73a61962..f9bba69f80 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6072,6 +6072,43 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 }
 
 
+/**
+ * qemuProcessGenID:
+ * @vm: Pointer to domain object
+ * @flags: qemuProcessStartFlags
+ *
+ * If this domain is requesting to use genid
+ */
+static int
+qemuProcessGenID(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;
+        }
+    }
+
+    return 0;
+}
+
+
 /**
  * qemuProcessLaunch:
  *
@@ -6124,7 +6161,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);
 
@@ -6148,6 +6186,9 @@ qemuProcessLaunch(virConnectPtr conn,
         goto cleanup;
     logfile = qemuDomainLogContextGetWriteFD(logCtxt);
 
+    if (qemuProcessGenID(vm, flags) < 0)
+        goto cleanup;
+
     VIR_DEBUG("Building emulator command line");
     if (!(cmd = qemuBuildCommandLine(driver,
                                      qemuDomainLogContextGetManager(logCtxt),
@@ -6513,7 +6554,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 a0e34b1c85..5098eacfe8 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -80,6 +80,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.14.3

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

Reply via email to