Normally, when you migrate a domain from host A to host B, the domain on host A remains defined but shutoff and the domain on host B remains running but is a "transient". Add a new flag to virDomainMigrate() to allow the original domain to be undefined on source host A, and a new flag to virDomainMigrate() to allow the new domain to be persisted on the destination host B. Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> --- include/libvirt/libvirt.h.in | 2 ++ src/libvirt.c | 4 ++++ src/qemu/qemu_driver.c | 34 ++++++++++++++++++++++++++++++++-- tools/virsh.c | 8 ++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index f51a565..6186d4e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -339,6 +339,8 @@ typedef enum { VIR_MIGRATE_LIVE = (1 << 0), /* live migration */ VIR_MIGRATE_PEER2PEER = (1 << 1), /* direct source -> dest host control channel */ VIR_MIGRATE_TUNNELLED = (1 << 2), /* tunnel migration data over libvirtd connection */ + VIR_MIGRATE_PERSIST_DEST = (1 << 3), /* persist the VM on the destination */ + VIR_MIGRATE_UNDEFINE_SOURCE = (1 << 4), /* undefine the VM on the source */ } virDomainMigrateFlags; /* Domain migration. */ diff --git a/src/libvirt.c b/src/libvirt.c index b14942d..92a1eaa 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3128,6 +3128,10 @@ virDomainMigrateDirect (virDomainPtr domain, * VIR_MIGRATE_LIVE Do not pause the VM during migration * VIR_MIGRATE_PEER2PEER Direct connection between source & destination hosts * VIR_MIGRATE_TUNNELLED Tunnel migration data over the libvirt RPC channel + * VIR_MIGRATE_PERSIST_DEST If the migration is successful, persist the domain + * on the destination host. + * VIR_MIGRATE_UNDEFINE_SOURCE If the migration is successful, undefine the + * domain on the source host. * * VIR_MIGRATE_TUNNELLED requires that VIR_MIGRATE_PEER2PEER be set. * Applications using the VIR_MIGRATE_PEER2PEER flag will probably diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3812f91..ba5694e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6848,7 +6848,8 @@ qemudDomainMigratePerform (virDomainPtr dom, event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_MIGRATED); - if (!vm->persistent) { + if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { + virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm); virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } @@ -6886,13 +6887,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, const char *cookie ATTRIBUTE_UNUSED, int cookielen ATTRIBUTE_UNUSED, const char *uri ATTRIBUTE_UNUSED, - unsigned long flags ATTRIBUTE_UNUSED, + unsigned long flags, int retcode) { struct qemud_driver *driver = dconn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; virDomainEventPtr event = NULL; + int newVM = 1; qemuDriverLock(driver); vm = virDomainFindByName(&driver->domains, dname); @@ -6906,6 +6908,34 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, * object, but if no, clean up the empty qemu process. */ if (retcode == 0) { + if (flags & VIR_MIGRATE_PERSIST_DEST) { + if (vm->persistent) + newVM = 0; + vm->persistent = 1; + + if (virDomainSaveConfig(dconn, driver->configDir, vm->def) < 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. + * Return a NULL dom pointer, and hope that this is a rare + * situation and management tools are smart. + */ + vm = NULL; + goto cleanup; + } + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_DEFINED, + newVM ? + VIR_DOMAIN_EVENT_DEFINED_ADDED : + VIR_DOMAIN_EVENT_DEFINED_UPDATED); + if (event) + qemuDomainEventQueue(driver, event); + + } dom = virGetDomain (dconn, vm->def->name, vm->def->uuid); /* run 'cont' on the destination, which allows migration on qemu diff --git a/tools/virsh.c b/tools/virsh.c index 46c5454..47122d5 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2465,6 +2465,8 @@ static const vshCmdOptDef opts_migrate[] = { {"p2p", VSH_OT_BOOL, 0, gettext_noop("peer-2-peer migration")}, {"direct", VSH_OT_BOOL, 0, gettext_noop("direct migration")}, {"tunnelled", VSH_OT_BOOL, 0, gettext_noop("tunnelled migration")}, + {"persistent", VSH_OT_BOOL, 0, gettext_noop("persist VM on destination")}, + {"undefinesource", VSH_OT_BOOL, 0, gettext_noop("undefine VM on source")}, {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")}, {"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("connection URI of the destination host")}, {"migrateuri", VSH_OT_DATA, 0, gettext_noop("migration URI, usually can be omitted")}, @@ -2504,6 +2506,12 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool (cmd, "tunnelled")) flags |= VIR_MIGRATE_TUNNELLED; + if (vshCommandOptBool (cmd, "persistent")) + flags |= VIR_MIGRATE_PERSIST_DEST; + + if (vshCommandOptBool (cmd, "undefinesource")) + flags |= VIR_MIGRATE_UNDEFINE_SOURCE; + if ((flags & VIR_MIGRATE_PEER2PEER) || vshCommandOptBool (cmd, "direct")) { /* For peer2peer migration or direct migration we only expect one URI -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list