mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Finer grained migration control
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@redhat.com>
This commit is contained in:
@@ -339,6 +339,8 @@ typedef enum {
|
|||||||
VIR_MIGRATE_LIVE = (1 << 0), /* live migration */
|
VIR_MIGRATE_LIVE = (1 << 0), /* live migration */
|
||||||
VIR_MIGRATE_PEER2PEER = (1 << 1), /* direct source -> dest host control channel */
|
VIR_MIGRATE_PEER2PEER = (1 << 1), /* direct source -> dest host control channel */
|
||||||
VIR_MIGRATE_TUNNELLED = (1 << 2), /* tunnel migration data over libvirtd connection */
|
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;
|
} virDomainMigrateFlags;
|
||||||
|
|
||||||
/* Domain migration. */
|
/* Domain migration. */
|
||||||
|
|||||||
@@ -3128,6 +3128,10 @@ virDomainMigrateDirect (virDomainPtr domain,
|
|||||||
* VIR_MIGRATE_LIVE Do not pause the VM during migration
|
* VIR_MIGRATE_LIVE Do not pause the VM during migration
|
||||||
* VIR_MIGRATE_PEER2PEER Direct connection between source & destination hosts
|
* VIR_MIGRATE_PEER2PEER Direct connection between source & destination hosts
|
||||||
* VIR_MIGRATE_TUNNELLED Tunnel migration data over the libvirt RPC channel
|
* 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.
|
* VIR_MIGRATE_TUNNELLED requires that VIR_MIGRATE_PEER2PEER be set.
|
||||||
* Applications using the VIR_MIGRATE_PEER2PEER flag will probably
|
* Applications using the VIR_MIGRATE_PEER2PEER flag will probably
|
||||||
|
|||||||
@@ -6847,7 +6847,8 @@ qemudDomainMigratePerform (virDomainPtr dom,
|
|||||||
event = virDomainEventNewFromObj(vm,
|
event = virDomainEventNewFromObj(vm,
|
||||||
VIR_DOMAIN_EVENT_STOPPED,
|
VIR_DOMAIN_EVENT_STOPPED,
|
||||||
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
|
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);
|
virDomainRemoveInactive(&driver->domains, vm);
|
||||||
vm = NULL;
|
vm = NULL;
|
||||||
}
|
}
|
||||||
@@ -6885,13 +6886,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
|||||||
const char *cookie ATTRIBUTE_UNUSED,
|
const char *cookie ATTRIBUTE_UNUSED,
|
||||||
int cookielen ATTRIBUTE_UNUSED,
|
int cookielen ATTRIBUTE_UNUSED,
|
||||||
const char *uri ATTRIBUTE_UNUSED,
|
const char *uri ATTRIBUTE_UNUSED,
|
||||||
unsigned long flags ATTRIBUTE_UNUSED,
|
unsigned long flags,
|
||||||
int retcode)
|
int retcode)
|
||||||
{
|
{
|
||||||
struct qemud_driver *driver = dconn->privateData;
|
struct qemud_driver *driver = dconn->privateData;
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
virDomainPtr dom = NULL;
|
virDomainPtr dom = NULL;
|
||||||
virDomainEventPtr event = NULL;
|
virDomainEventPtr event = NULL;
|
||||||
|
int newVM = 1;
|
||||||
|
|
||||||
qemuDriverLock(driver);
|
qemuDriverLock(driver);
|
||||||
vm = virDomainFindByName(&driver->domains, dname);
|
vm = virDomainFindByName(&driver->domains, dname);
|
||||||
@@ -6905,6 +6907,34 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
|||||||
* object, but if no, clean up the empty qemu process.
|
* object, but if no, clean up the empty qemu process.
|
||||||
*/
|
*/
|
||||||
if (retcode == 0) {
|
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);
|
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
|
||||||
|
|
||||||
/* run 'cont' on the destination, which allows migration on qemu
|
/* run 'cont' on the destination, which allows migration on qemu
|
||||||
|
|||||||
@@ -2465,6 +2465,8 @@ static const vshCmdOptDef opts_migrate[] = {
|
|||||||
{"p2p", VSH_OT_BOOL, 0, gettext_noop("peer-2-peer migration")},
|
{"p2p", VSH_OT_BOOL, 0, gettext_noop("peer-2-peer migration")},
|
||||||
{"direct", VSH_OT_BOOL, 0, gettext_noop("direct migration")},
|
{"direct", VSH_OT_BOOL, 0, gettext_noop("direct migration")},
|
||||||
{"tunnelled", VSH_OT_BOOL, 0, gettext_noop("tunnelled 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")},
|
{"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")},
|
{"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")},
|
{"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"))
|
if (vshCommandOptBool (cmd, "tunnelled"))
|
||||||
flags |= VIR_MIGRATE_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) ||
|
if ((flags & VIR_MIGRATE_PEER2PEER) ||
|
||||||
vshCommandOptBool (cmd, "direct")) {
|
vshCommandOptBool (cmd, "direct")) {
|
||||||
/* For peer2peer migration or direct migration we only expect one URI
|
/* For peer2peer migration or direct migration we only expect one URI
|
||||||
|
|||||||
Reference in New Issue
Block a user