To get rid of a giant if-else block which is very easy to get lost in.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
This patch might be a bit easier to review using -b.
src/qemu/qemu_migration.c | 255 +++++++++++++++++++++++-----------------------
1 file changed, 127 insertions(+), 128 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index b02ebd7..49ed777 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -5792,6 +5792,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
unsigned short port;
+ unsigned long long timeReceived = 0;
+ virObjectEventPtr event;
VIR_DEBUG("driver=%p, dconn=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%lx, retcode=%d",
@@ -5806,6 +5808,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
goto cleanup;
}
+ ignore_value(virTimeMillisNow(&timeReceived));
+
qemuMigrationJobStartPhase(driver, vm,
v3proto ? QEMU_MIGRATION_PHASE_FINISH3
: QEMU_MIGRATION_PHASE_FINISH2);
@@ -5823,132 +5827,14 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
cookieinlen, cookie_flags)))
goto endjob;
- /* Did the migration go as planned? If yes, return the domain
- * object, but if no, clean up the empty qemu process.
- */
if (flags & VIR_MIGRATE_OFFLINE) {
- if (retcode != 0 ||
- qemuMigrationPersist(driver, vm, mig, false) < 0)
- goto endjob;
+ if (retcode == 0 &&
+ qemuMigrationPersist(driver, vm, mig, false) == 0)
+ dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
+ goto endjob;
+ }
- dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
- } else if (retcode == 0) {
- unsigned long long timeReceived = 0;
-
- ignore_value(virTimeMillisNow(&timeReceived));
-
- if (!virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("guest unexpectedly quit"));
- qemuMigrationErrorReport(driver, vm->def->name);
- goto endjob;
- }
-
- if (qemuMigrationVPAssociatePortProfiles(vm->def) < 0)
- goto endjob;
-
- if (mig->network && qemuDomainMigrateOPDRelocate(driver, vm, mig) <
0)
- VIR_WARN("unable to provide network data for relocation");
-
- if (qemuMigrationStopNBDServer(driver, vm, mig) < 0)
- goto endjob;
-
- if (flags & VIR_MIGRATE_PERSIST_DEST) {
- if (qemuMigrationPersist(driver, vm, mig, !v3proto) < 0) {
- /* Hmpf. Migration was successful, but making it persistent
- * was not. If we report successful, then when this domain
- * shuts down, management tools are in for a surprise. On the
- * other hand, if we report failure, then the management tools
- * might try to restart the domain on the source side, even
- * though the domain is actually running on the destination.
- * Pretend success and hope that this is a rare situation and
- * management tools are smart.
- *
- * However, in v3 protocol, the source VM is still available
- * to restart during confirm() step, so we kill it off now.
- */
- if (v3proto)
- goto endjob;
- }
- }
-
- /* We need to wait for QEMU to process all data sent by the source
- * before starting guest CPUs.
- */
- if (qemuMigrationWaitForDestCompletion(driver, vm,
- QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
- /* There's not much we can do for v2 protocol since the
- * original domain on the source host is already gone.
- */
- if (v3proto)
- goto endjob;
- }
-
- if (!(flags & VIR_MIGRATE_PAUSED)) {
- /* run 'cont' on the destination, which allows migration on qemu
- * >= 0.10.6 to work properly. This isn't strictly necessary on
- * older qemu's, but it also doesn't hurt anything there
- */
- if (qemuProcessStartCPUs(driver, vm, dconn,
- VIR_DOMAIN_RUNNING_MIGRATED,
- QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
- if (virGetLastError() == NULL)
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("resume operation
failed"));
- /* Need to save the current error, in case shutting
- * down the process overwrites it
- */
- orig_err = virSaveLastError();
-
- /*
- * In v3 protocol, the source VM is still available to
- * restart during confirm() step, so we kill it off
- * now.
- * In v2 protocol, the source is dead, so we leave
- * target in paused state, in case admin can fix
- * things up
- */
- if (v3proto)
- goto endjob;
- }
- }
-
- if (mig->jobInfo) {
- qemuDomainJobInfoPtr jobInfo = mig->jobInfo;
- priv->job.completed = jobInfo;
- mig->jobInfo = NULL;
-
- if (jobInfo->sent && timeReceived) {
- jobInfo->timeDelta = timeReceived - jobInfo->sent;
- jobInfo->received = timeReceived;
- jobInfo->timeDeltaSet = true;
- }
- qemuDomainJobInfoUpdateTime(priv->job.completed);
- qemuDomainJobInfoUpdateDowntime(priv->job.completed);
- }
-
- dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
-
- qemuDomainEventQueue(driver,
- virDomainEventLifecycleNewFromObj(vm,
- VIR_DOMAIN_EVENT_RESUMED,
- VIR_DOMAIN_EVENT_RESUMED_MIGRATED));
- if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
- virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
- VIR_DOMAIN_PAUSED_USER);
- qemuDomainEventQueue(driver,
- virDomainEventLifecycleNewFromObj(vm,
- VIR_DOMAIN_EVENT_SUSPENDED,
- VIR_DOMAIN_EVENT_SUSPENDED_PAUSED));
- }
-
- if (virDomainObjIsActive(vm) &&
- virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
- VIR_WARN("Failed to save status on vm %s", vm->def->name);
-
- /* Guest is successfully running, so cancel previous auto destroy */
- qemuProcessAutoDestroyRemove(driver, vm);
- } else {
+ if (retcode != 0) {
qemuDomainJobInfo info;
/* Check for a possible error on the monitor in case Finish was called
@@ -5957,8 +5843,121 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
qemuMigrationFetchJobStatus(driver, vm,
QEMU_ASYNC_JOB_MIGRATION_IN,
&info);
+ goto endjob;
}
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest unexpectedly quit"));
+ qemuMigrationErrorReport(driver, vm->def->name);
+ goto endjob;
+ }
+
+ if (qemuMigrationVPAssociatePortProfiles(vm->def) < 0)
+ goto endjob;
+
+ if (mig->network && qemuDomainMigrateOPDRelocate(driver, vm, mig) < 0)
+ VIR_WARN("unable to provide network data for relocation");
+
+ if (qemuMigrationStopNBDServer(driver, vm, mig) < 0)
+ goto endjob;
+
+ if (flags & VIR_MIGRATE_PERSIST_DEST) {
+ if (qemuMigrationPersist(driver, vm, mig, !v3proto) < 0) {
+ /* Hmpf. Migration was successful, but making it persistent
+ * was not. If we report successful, then when this domain
+ * shuts down, management tools are in for a surprise. On the
+ * other hand, if we report failure, then the management tools
+ * might try to restart the domain on the source side, even
+ * though the domain is actually running on the destination.
+ * Pretend success and hope that this is a rare situation and
+ * management tools are smart.
+ *
+ * However, in v3 protocol, the source VM is still available
+ * to restart during confirm() step, so we kill it off now.
+ */
+ if (v3proto)
+ goto endjob;
+ }
+ }
+
+ /* We need to wait for QEMU to process all data sent by the source
+ * before starting guest CPUs.
+ */
+ if (qemuMigrationWaitForDestCompletion(driver, vm,
+ QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
+ /* There's not much we can do for v2 protocol since the
+ * original domain on the source host is already gone.
+ */
+ if (v3proto)
+ goto endjob;
+ }
+
+ if (!(flags & VIR_MIGRATE_PAUSED)) {
+ /* run 'cont' on the destination, which allows migration on qemu
+ * >= 0.10.6 to work properly. This isn't strictly necessary on
+ * older qemu's, but it also doesn't hurt anything there
+ */
+ if (qemuProcessStartCPUs(driver, vm, dconn,
+ VIR_DOMAIN_RUNNING_MIGRATED,
+ QEMU_ASYNC_JOB_MIGRATION_IN) < 0) {
+ if (virGetLastError() == NULL)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("resume operation failed"));
+ /* Need to save the current error, in case shutting
+ * down the process overwrites it
+ */
+ orig_err = virSaveLastError();
+
+ /*
+ * In v3 protocol, the source VM is still available to
+ * restart during confirm() step, so we kill it off
+ * now.
+ * In v2 protocol, the source is dead, so we leave
+ * target in paused state, in case admin can fix
+ * things up.
+ */
+ if (v3proto)
+ goto endjob;
+ }
+ }
+
+ if (mig->jobInfo) {
+ qemuDomainJobInfoPtr jobInfo = mig->jobInfo;
+ priv->job.completed = jobInfo;
+ mig->jobInfo = NULL;
+
+ if (jobInfo->sent && timeReceived) {
+ jobInfo->timeDelta = timeReceived - jobInfo->sent;
+ jobInfo->received = timeReceived;
+ jobInfo->timeDeltaSet = true;
+ }
+ qemuDomainJobInfoUpdateTime(priv->job.completed);
+ qemuDomainJobInfoUpdateDowntime(priv->job.completed);
+ }
+
+ dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
+
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+ qemuDomainEventQueue(driver, event);
+
+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
+ qemuDomainEventQueue(driver, event);
+ }
+
+ if (virDomainObjIsActive(vm) &&
+ virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+ VIR_WARN("Failed to save status on vm %s", vm->def->name);
+
+ /* Guest is successfully running, so cancel previous auto destroy */
+ qemuProcessAutoDestroyRemove(driver, vm);
+
endjob:
if (!dom &&
!(flags & VIR_MIGRATE_OFFLINE) &&
@@ -5966,10 +5965,10 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
VIR_QEMU_PROCESS_STOP_MIGRATED);
virDomainAuditStop(vm, "failed");
- qemuDomainEventQueue(driver,
- virDomainEventLifecycleNewFromObj(vm,
- VIR_DOMAIN_EVENT_STOPPED,
- VIR_DOMAIN_EVENT_STOPPED_FAILED));
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_FAILED);
+ qemuDomainEventQueue(driver, event);
}
if (dom &&
--
2.7.0