]> xenbits.xensource.com Git - libvirt.git/commitdiff
migration: Make erroring out on I/O error controllable by flag
authorPeter Krempa <pkrempa@redhat.com>
Wed, 12 Jun 2013 14:11:21 +0000 (16:11 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Tue, 18 Jun 2013 12:52:26 +0000 (14:52 +0200)
Paolo Bonzini pointed out that it's actually possible to migrate a qemu
instance that was paused due to I/O error and it will be able to work on
the destination if the storage is accessible.

This patch introduces flag VIR_MIGRATE_ABORT_ON_ERROR that cancels the
migration in case an I/O error happens while it's being performed and
allows migration without this flag. This flag can be possibly used for
other error reasons that may be introduced in the future.

include/libvirt/libvirt.h.in
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_migration.h
tools/virsh-domain.c
tools/virsh.pod

index 211e96b15a1205ec7a6e4a28e3d59575b4209a4b..acf3218206200b728053a8bd7b7d1d2c48aa1628 100644 (file)
@@ -1188,6 +1188,7 @@ typedef enum {
     VIR_MIGRATE_UNSAFE            = (1 << 9), /* force migration even if it is considered unsafe */
     VIR_MIGRATE_OFFLINE           = (1 << 10), /* offline migrate */
     VIR_MIGRATE_COMPRESSED        = (1 << 11), /* compress data during migration */
+    VIR_MIGRATE_ABORT_ON_ERROR    = (1 << 12), /* abort migration on I/O errors happened during migration */
 } virDomainMigrateFlags;
 
 /* Domain migration. */
index 93c7d14323a26aacd10be66f0043063c73a3855e..9b738e037cb1295711f95e942ee5cf441a942de1 100644 (file)
@@ -2819,7 +2819,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto cleanup;
 
-    if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
+    if (!qemuMigrationIsAllowed(driver, vm, vm->def, false, false))
         goto cleanup;
 
     if (qemuDomainObjBeginAsyncJob(driver, vm,
@@ -11670,7 +11670,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
     /* do the memory snapshot if necessary */
     if (memory) {
         /* check if migration is possible */
-        if (!qemuMigrationIsAllowed(driver, vm, vm->def, false))
+        if (!qemuMigrationIsAllowed(driver, vm, vm->def, false, false))
             goto endjob;
 
         /* allow the migration job to be cancelled or the domain to be paused */
index 291fee2e78ec752445dc1ed23e6d09cc0de3bb13..9a486427a7b406534af0f6d76e74e8a9f279c05e 100644 (file)
@@ -1420,7 +1420,7 @@ cleanup:
  * the fact that older servers did not do checks on the source. */
 bool
 qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm,
-                       virDomainDefPtr def, bool remote)
+                       virDomainDefPtr def, bool remote, bool abort_on_error)
 {
     int nsnapshots;
     int pauseReason;
@@ -1448,7 +1448,8 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm,
             }
 
             /* cancel migration if disk I/O error is emitted while migrating */
-            if (virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
+            if (abort_on_error &&
+                virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
                 pauseReason == VIR_DOMAIN_PAUSED_IOERROR) {
                 virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                                _("cannot migrate domain with I/O error"));
@@ -1709,7 +1710,7 @@ qemuMigrationUpdateJobStatus(virQEMUDriverPtr driver,
 static int
 qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, virDomainObjPtr vm,
                                enum qemuDomainAsyncJob asyncJob,
-                               virConnectPtr dconn)
+                               virConnectPtr dconn, bool abort_on_error)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     const char *job;
@@ -1736,7 +1737,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, virDomainObjPtr vm,
         struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
 
         /* cancel migration if disk I/O error is emitted while migrating */
-        if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT &&
+        if (abort_on_error &&
             virDomainObjGetState(vm, &pauseReason) == VIR_DOMAIN_PAUSED &&
             pauseReason == VIR_DOMAIN_PAUSED_IOERROR)
             goto cancel;
@@ -1937,6 +1938,7 @@ char *qemuMigrationBegin(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virCapsPtr caps = NULL;
     unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s,"
               " cookieout=%p, cookieoutlen=%p, flags=%lx",
@@ -1953,7 +1955,7 @@ char *qemuMigrationBegin(virQEMUDriverPtr driver,
     if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT)
         qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_BEGIN3);
 
-    if (!qemuMigrationIsAllowed(driver, vm, NULL, true))
+    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
         goto cleanup;
 
     if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
@@ -2069,6 +2071,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
     virCapsPtr caps = NULL;
     const char *listenAddr = NULL;
     char *migrateFrom = NULL;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     if (virTimeMillisNow(&now) < 0)
         return -1;
@@ -2098,7 +2101,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
     if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
         goto cleanup;
 
-    if (!qemuMigrationIsAllowed(driver, NULL, *def, true))
+    if (!qemuMigrationIsAllowed(driver, NULL, *def, true, abort_on_error))
         goto cleanup;
 
     /* Let migration hook filter domain XML */
@@ -2795,6 +2798,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
     unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
     virErrorPtr orig_err = NULL;
     unsigned int cookieFlags = 0;
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
               "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
@@ -2947,7 +2951,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
 
     if (qemuMigrationWaitForCompletion(driver, vm,
                                        QEMU_ASYNC_JOB_MIGRATION_OUT,
-                                       dconn) < 0)
+                                       dconn, abort_on_error) < 0)
         goto cleanup;
 
     /* When migration completed, QEMU will have paused the
@@ -3628,6 +3632,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
     int resume = 0;
     virErrorPtr orig_err = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
 
     if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
         goto cleanup;
@@ -3638,7 +3643,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
         goto endjob;
     }
 
-    if (!qemuMigrationIsAllowed(driver, vm, NULL, true))
+    if (!qemuMigrationIsAllowed(driver, vm, NULL, true, abort_on_error))
         goto endjob;
 
     if (!(flags & VIR_MIGRATE_UNSAFE) && !qemuMigrationIsSafe(vm->def))
@@ -4338,7 +4343,7 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
     if (rc < 0)
         goto cleanup;
 
-    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL);
+    rc = qemuMigrationWaitForCompletion(driver, vm, asyncJob, NULL, false);
 
     if (rc < 0)
         goto cleanup;
index 22b04b4179072b2ae2a89059510cdccedb768ad9..5b21ca2caded4ab0efaec1a787432e3678dd71f6 100644 (file)
@@ -38,7 +38,8 @@
      VIR_MIGRATE_CHANGE_PROTECTION |            \
      VIR_MIGRATE_UNSAFE |                       \
      VIR_MIGRATE_OFFLINE |                      \
-     VIR_MIGRATE_COMPRESSED)
+     VIR_MIGRATE_COMPRESSED |                   \
+     VIR_MIGRATE_ABORT_ON_ERROR)
 
 enum qemuMigrationJobPhase {
     QEMU_MIGRATION_PHASE_NONE = 0,
@@ -147,7 +148,8 @@ int qemuMigrationConfirm(virQEMUDriverPtr driver,
                          int retcode);
 
 bool qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm,
-                            virDomainDefPtr def, bool remote);
+                            virDomainDefPtr def, bool remote,
+                            bool abort_on_error);
 
 int qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
                         int fd, off_t offset, const char *path,
index 955e882151827dc69f9aeb374a870134a9777910..7f9b9e389ca56f057c2af18e6cfd192d9dcbcbbf 100644 (file)
@@ -8306,6 +8306,10 @@ static const vshCmdOptDef opts_migrate[] = {
      .type = VSH_OT_BOOL,
      .help = N_("compress repeated pages during live migration")
     },
+    {.name = "abort-on-error",
+     .type = VSH_OT_BOOL,
+     .help = N_("abort on soft errors during migration")
+    },
     {.name = "domain",
      .type = VSH_OT_DATA,
      .flags = VSH_OFLAG_REQ,
@@ -8399,6 +8403,9 @@ doMigrate(void *opaque)
         flags |= VIR_MIGRATE_OFFLINE;
     }
 
+    if (vshCommandOptBool(cmd, "abort-on-error"))
+        flags |= VIR_MIGRATE_ABORT_ON_ERROR;
+
     if (xmlfile &&
         virFileReadAll(xmlfile, 8192, &xml) < 0) {
         vshError(ctl, _("file '%s' doesn't exist"), xmlfile);
index 0b27dda775a4b6b37c728f3384b166bbfc735936..f4746cc915ee140135a639b717ead4b15cbb7411 100644 (file)
@@ -1043,7 +1043,8 @@ stats.
 =item B<migrate> [I<--live>] [I<--offline>] [I<--direct>] [I<--p2p> [I<--tunnelled>]]
 [I<--persistent>] [I<--undefinesource>] [I<--suspend>] [I<--copy-storage-all>]
 [I<--copy-storage-inc>] [I<--change-protection>] [I<--unsafe>] [I<--verbose>]
-[I<--compressed>] I<domain> I<desturi> [I<migrateuri>] [I<dname>]
+[I<--compressed>] [I<--abort-on-error>]
+I<domain> I<desturi> [I<migrateuri>] [I<dname>]
 [I<--timeout> B<seconds>] [I<--xml> B<file>]
 
 Migrate domain to another host.  Add I<--live> for live migration; <--p2p>
@@ -1066,7 +1067,8 @@ is implicitly enabled when supported by the hypervisor, but can be explicitly
 used to reject the migration if the hypervisor lacks change protection
 support.  I<--verbose> displays the progress of migration.  I<--compressed>
 activates compression of memory pages that have to be transferred repeatedly
-during live migration.
+during live migration. I<--abort-on-error> cancels the migration if a soft
+error (for example I/O error) happens during the migration.
 
 B<Note>: Individual hypervisors usually do not support all possible types of
 migration. For example, QEMU does not support direct migration.