]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Avoid dangling migration-in job on shutoff domains
authorJiri Denemark <jdenemar@redhat.com>
Fri, 16 Mar 2012 06:56:19 +0000 (07:56 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Wed, 21 Mar 2012 16:31:09 +0000 (17:31 +0100)
Destination daemon should not rely on the client or source daemon
(depending on the type of migration) to call Finish when migration
fails, because the client may crash before it can do so. The domain
prepared for incoming migration is set to be destroyed (and migration
job cleaned up) when connection with the client closes but this is not
enough. If the associated qemu process crashes after Prepare step and
the domain is cleaned up before the connection gets closed, autodestroy
is not called for the domain and migration jobs remains set. In case the
domain is defined on destination host (i.e., it is not completely
removed once destroyed) we keep the job set for ever. To fix this, we
register a cleanup callback which is responsible to clean migration-in
job when a domain dies anywhere between Prepare and Finish steps. Note
that we can't blindly clean any job when spotting EOF on monitor since
normally an API is running at that time.

src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_migration.c

index a9469cf4c7b65e89f55897e29d9083117f70dfb6..41ffd6ae0db582e7f3e5cce36e286cfa78fd4944 100644 (file)
@@ -51,7 +51,6 @@
     (VIR_DOMAIN_XML_SECURE |                \
      VIR_DOMAIN_XML_UPDATE_CPU)
 
-VIR_ENUM_DECL(qemuDomainJob)
 VIR_ENUM_IMPL(qemuDomainJob, QEMU_JOB_LAST,
               "none",
               "query",
@@ -64,7 +63,6 @@ VIR_ENUM_IMPL(qemuDomainJob, QEMU_JOB_LAST,
               "async nested",
 );
 
-VIR_ENUM_DECL(qemuDomainAsyncJob)
 VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST,
               "none",
               "migration out",
index 4fdec6255fe054ccab470cc861122be2c0ec6e23..adccfedb06336b52597fb8a6ac77a0d281e02ec8 100644 (file)
@@ -71,6 +71,7 @@ enum qemuDomainJob {
 
     QEMU_JOB_LAST
 };
+VIR_ENUM_DECL(qemuDomainJob)
 
 /* Async job consists of a series of jobs that may change state. Independent
  * jobs that do not change state (and possibly others if explicitly allowed by
@@ -85,6 +86,7 @@ enum qemuDomainAsyncJob {
 
     QEMU_ASYNC_JOB_LAST
 };
+VIR_ENUM_DECL(qemuDomainAsyncJob)
 
 struct qemuDomainJobObj {
     virCond cond;                       /* Use to coordinate jobs */
index c0cf636cc28559d4864ab9290a1d7ebf5ba4f8b6..69d4f0c52066357d9f6fb83c3f83b8106bf4e22a 100644 (file)
@@ -1107,6 +1107,23 @@ cleanup:
 /* Prepare is the first step, and it runs on the destination host.
  */
 
+static void
+qemuMigrationPrepareCleanup(struct qemud_driver *driver,
+                            virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    VIR_DEBUG("driver=%p, vm=%s, job=%s, asyncJob=%s",
+              driver,
+              vm->def->name,
+              qemuDomainJobTypeToString(priv->job.active),
+              qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+
+    if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
+        return;
+    qemuDomainObjDiscardAsyncJob(driver, vm);
+}
+
 static int
 qemuMigrationPrepareAny(struct qemud_driver *driver,
                         virConnectPtr dconn,
@@ -1264,6 +1281,9 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
         VIR_WARN("Unable to encode migration cookie");
     }
 
+    if (qemuDomainCleanupAdd(vm, qemuMigrationPrepareCleanup) < 0)
+        goto endjob;
+
     virDomainAuditStart(vm, "migrated", true);
     event = virDomainEventNewFromObj(vm,
                                      VIR_DOMAIN_EVENT_STARTED,
@@ -2703,6 +2723,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
                                v3proto ? QEMU_MIGRATION_PHASE_FINISH3
                                        : QEMU_MIGRATION_PHASE_FINISH2);
 
+    qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
+
     if (flags & VIR_MIGRATE_PERSIST_DEST)
         cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;