diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 30f559d..2f73957 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -318,9 +318,14 @@ typedef virDomainInterfaceStatsStruct *virDomainInterfaceStatsPtr; /* Domain migration flags. */ typedef enum { - VIR_MIGRATE_LIVE = 1, /* live migration */ + 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. */ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 2f7076f..91886ee 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -318,9 +318,14 @@ typedef virDomainInterfaceStatsStruct *virDomainInterfaceStatsPtr; /* Domain migration flags. */ typedef enum { - VIR_MIGRATE_LIVE = 1, /* live migration */ + 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. */ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, diff --git a/src/qemu_driver.c b/src/qemu_driver.c index f9fe2ba..b7fbce7 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -4888,6 +4888,13 @@ qemudDomainMigratePerform (virDomainPtr dom, event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + + if (vm->persistent && (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) { + virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm); + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; @@ -4943,6 +4950,7 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, virDomainPtr dom = NULL; virDomainEventPtr event = NULL; char *info = NULL; + int newVM = 1; qemuDriverLock(driver); vm = virDomainFindByName(&driver->domains, dname); @@ -4956,6 +4964,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); VIR_FREE(info); vm->state = VIR_DOMAIN_RUNNING;