]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Alter VM Generation ID for specific startup/launch transitions
authorJohn Ferlan <jferlan@redhat.com>
Mon, 9 Apr 2018 14:31:17 +0000 (10:31 -0400)
committerJohn Ferlan <jferlan@redhat.com>
Fri, 25 May 2018 12:15:47 +0000 (08:15 -0400)
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 <jferlan@redhat.com>
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_driver.c
src/qemu/qemu_process.c
src/qemu/qemu_process.h

index 3a328e5d4679d9e259945767190e61a8a81d1ef1..4a8059ebd1bd6bc99ff0ce284e198a746dc3d2dc 100644 (file)
@@ -6578,7 +6578,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) {
@@ -15852,6 +15853,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();
 
@@ -15932,7 +15942,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,
@@ -16018,7 +16029,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;
 
index ac2049b95df5d9ef278d896d2553cd6af7b4e3b8..5f5759c9c812d8c01305913db99be2d55baefaac 100644 (file)
@@ -6050,6 +6050,39 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 }
 
 
+/**
+ * qemuProcessGenID:
+ * @vm: Pointer to domain object
+ * @flags: qemuProcessStartFlags
+ *
+ * If this domain is requesting to use genid, then update the GUID
+ * value if the VIR_QEMU_PROCESS_START_GEN_VMID flag is set. This
+ * flag is set on specific paths during domain start processing when
+ * there is the possibility that the VM is potentially re-executing
+ * something that has already been executed before.
+ */
+static int
+qemuProcessGenID(virDomainObjPtr vm,
+                 unsigned int flags)
+{
+    if (!vm->def->genidRequested)
+        return 0;
+
+    /* 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) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("failed to regenerate genid"));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
 /**
  * qemuProcessLaunch:
  *
@@ -6102,7 +6135,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);
 
@@ -6126,6 +6160,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),
@@ -6491,7 +6528,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;
index a0e34b1c85da3635b4d4065c5106c1e70c47f4df..5098eacfe8079f01db28d5d58864ad66e1aa6812 100644 (file)
@@ -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,