Hi, Migration will be disallowed when the vm uses host devices or has snapshots (qemuMigrationIsAllowed)[1]. Would it make sense to introduce a VIR_MIGRATE_FORCE similar to VIR_REVERT_FORCE here? We could then introduce error codes similar to the snapshot case (VIR_ERR_MIGRATE_RISKY). This path is just to illustrate the idea not to be applied as is. Cheers, -- Guido [1] Hopefully we can make migration with snapshots safe in the future by transfering the metadata. A current hack around is to put this onto shared storage and reread it on the destination side after migration.
>From 4628166c7cbb247da8726248c7e54b265da99a7d Mon Sep 17 00:00:00 2001 From: Guido Guenther <agx@xxxxxxxxxxx> Date: Thu, 13 Oct 2011 12:05:08 +0200 Subject: [PATCH] Introduce VIR_MIGRATE_FORCE flag to allow for risky migrations Change errors indicating risky migration to VIR_ERR_MIGRATE_RISKY. --- include/libvirt/libvirt.h.in | 3 ++- include/libvirt/virterror.h | 2 ++ src/qemu/qemu_driver.c | 10 +++++----- src/qemu/qemu_migration.c | 38 ++++++++++++++++++++++++-------------- src/qemu/qemu_migration.h | 13 +++++++++---- src/util/virterror.c | 6 ++++++ 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 361881a..1f147f1 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -767,7 +767,8 @@ typedef enum { VIR_MIGRATE_CHANGE_PROTECTION = (1 << 8), /* protect for changing domain configuration through the * whole migration process; this will be used automatically * when supported */ - + VIR_MIGRATE_FORCE = (1 << 9), /* Force migration even when we have host devices in use + or have snapshotes */ } virDomainMigrateFlags; /* Domain migration. */ diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index a8549b7..cc09ea0 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -240,6 +240,8 @@ typedef enum { VIR_ERR_STORAGE_POOL_BUILT = 76, /* storage pool already built */ VIR_ERR_SNAPSHOT_REVERT_RISKY = 77, /* force was not requested for a risky domain snapshot revert */ + VIR_ERR_MIGRATE_RISKY = 78, /* force was not requested for a + risky domain migration */ } virErrorNumber; /** diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6b65716..5e5214d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7881,7 +7881,7 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn, ret = qemuMigrationPrepareTunnel(driver, dconn, NULL, 0, NULL, NULL, /* No cookies in v2 */ - st, dname, dom_xml); + st, dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -7941,7 +7941,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ret = qemuMigrationPrepareDirect(driver, dconn, NULL, 0, NULL, NULL, /* No cookies */ uri_in, uri_out, - dname, dom_xml); + dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -8094,7 +8094,7 @@ qemuDomainMigrateBegin3(virDomainPtr domain, goto endjob; if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname, - cookieout, cookieoutlen))) + cookieout, cookieoutlen, flags))) goto endjob; if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { @@ -8171,7 +8171,7 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, cookiein, cookieinlen, cookieout, cookieoutlen, uri_in, uri_out, - dname, dom_xml); + dname, dom_xml, flags); cleanup: qemuDriverUnlock(driver); @@ -8216,7 +8216,7 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, ret = qemuMigrationPrepareTunnel(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, - st, dname, dom_xml); + st, dname, dom_xml, flags); qemuDriverUnlock(driver); cleanup: diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index decb0f2..3263c2f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -788,18 +788,24 @@ error: * the fact that older servers did not do checks on the source. */ static bool qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, - virDomainDefPtr def) + virDomainDefPtr def, int flags) { int nsnapshots; + /* FIXME: there are different kinds of risk (a missing host device + might break the vm entirely while missing snapshots will not */ + if (flags & VIR_MIGRATE_FORCE) { + return true; + } + if (vm) { if (qemuProcessAutoDestroyActive(driver, vm)) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, "%s", _("domain is marked for auto destroy")); return false; } if ((nsnapshots = virDomainSnapshotObjListNum(&vm->snapshots, 0))) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, _("cannot migrate domain with %d snapshots"), nsnapshots); return false; @@ -808,7 +814,7 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, def = vm->def; } if (def->nhostdevs > 0) { - qemuReportError(VIR_ERR_OPERATION_INVALID, + qemuReportError(VIR_ERR_MIGRATE_RISKY, "%s", _("Domain with assigned host devices cannot be migrated")); return false; } @@ -1002,7 +1008,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver, const char *xmlin, const char *dname, char **cookieout, - int *cookieoutlen) + int *cookieoutlen, + unsigned long flags) { char *rv = NULL; qemuMigrationCookiePtr mig = NULL; @@ -1021,7 +1028,7 @@ char *qemuMigrationBegin(struct qemud_driver *driver, if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_OUT) qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_BEGIN3); - if (!qemuMigrationIsAllowed(driver, vm, NULL)) + if (!qemuMigrationIsAllowed(driver, vm, NULL, flags)) goto cleanup; if (!(mig = qemuMigrationEatCookie(driver, vm, NULL, 0, 0))) @@ -1078,7 +1085,8 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, const char *dname, const char *dom_xml, const char *migrateFrom, - virStreamPtr st) + virStreamPtr st, + int flags) { virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; @@ -1099,7 +1107,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; - if (!qemuMigrationIsAllowed(driver, NULL, def)) + if (!qemuMigrationIsAllowed(driver, NULL, def, flags)) goto cleanup; /* Target domain name, maybe renamed. */ @@ -1239,7 +1247,8 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, int *cookieoutlen, virStreamPtr st, const char *dname, - const char *dom_xml) + const char *dom_xml, + unsigned long flags) { int ret; @@ -1253,7 +1262,7 @@ qemuMigrationPrepareTunnel(struct qemud_driver *driver, */ ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, dname, dom_xml, - "stdio", st); + "stdio", st, flags); return ret; } @@ -1268,7 +1277,8 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, const char *uri_in, char **uri_out, const char *dname, - const char *dom_xml) + const char *dom_xml, + unsigned long flags) { static int port = 0; int this_port; @@ -1364,7 +1374,7 @@ qemuMigrationPrepareDirect(struct qemud_driver *driver, ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, dname, dom_xml, - migrateFrom, NULL); + migrateFrom, NULL, flags); cleanup: VIR_FREE(hostname); if (ret != 0) @@ -2031,7 +2041,7 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver, * a single job. */ dom_xml = qemuMigrationBegin(driver, vm, xmlin, dname, - &cookieout, &cookieoutlen); + &cookieout, &cookieoutlen, flags); if (!dom_xml) goto cleanup; @@ -2308,7 +2318,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver, goto endjob; } - if (!qemuMigrationIsAllowed(driver, vm, NULL)) + if (!qemuMigrationIsAllowed(driver, vm, NULL, flags)) goto cleanup; resume = virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING; diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index f806ca1..f6491b5 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -35,7 +35,9 @@ VIR_MIGRATE_PAUSED | \ VIR_MIGRATE_NON_SHARED_DISK | \ VIR_MIGRATE_NON_SHARED_INC | \ - VIR_MIGRATE_CHANGE_PROTECTION) + VIR_MIGRATE_CHANGE_PROTECTION | \ + VIR_MIGRATE_FORCE) + enum qemuMigrationJobPhase { QEMU_MIGRATION_PHASE_NONE = 0, @@ -81,7 +83,8 @@ char *qemuMigrationBegin(struct qemud_driver *driver, const char *xmlin, const char *dname, char **cookieout, - int *cookieoutlen); + int *cookieoutlen, + unsigned long flags); int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, @@ -91,7 +94,8 @@ int qemuMigrationPrepareTunnel(struct qemud_driver *driver, int *cookieoutlen, virStreamPtr st, const char *dname, - const char *dom_xml); + const char *dom_xml, + unsigned long flags); int qemuMigrationPrepareDirect(struct qemud_driver *driver, virConnectPtr dconn, @@ -102,7 +106,8 @@ int qemuMigrationPrepareDirect(struct qemud_driver *driver, const char *uri_in, char **uri_out, const char *dname, - const char *dom_xml); + const char *dom_xml, + unsigned long flags); int qemuMigrationPerform(struct qemud_driver *driver, virConnectPtr conn, diff --git a/src/util/virterror.c b/src/util/virterror.c index 5006fa2..3544208 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1210,6 +1210,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("revert requires force: %s"); break; + case VIR_ERR_MIGRATE_RISKY: + if (info == NULL) + errmsg = _("migration requires force"); + else + errmsg = _("migration requires force: %s"); + break; } return (errmsg); } -- 1.7.6.3
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list