mirror of https://gitee.com/openkylin/libvirt.git
qemu: Fix some corner cases in persistent migration
When persistently migrating a domain to a destination host where the same domain already exists (i.e., it is persistent and shutdown at the destination), we would happily throw away the original persistent definition without properly freeing it. And when updating the definition fails for some reason we don't properly revert to the original state leaving the domain broken. In addition to fixing these issues, the patch also makes sure the domain definition parsed from a migration cookie is either used or freed. Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
parent
c641d55083
commit
79ccfec803
|
@ -525,6 +525,19 @@ qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virDomainDefPtr
|
||||||
|
qemuMigrationCookieGetPersistent(qemuMigrationCookiePtr mig)
|
||||||
|
{
|
||||||
|
virDomainDefPtr def = mig->persistent;
|
||||||
|
|
||||||
|
mig->persistent = NULL;
|
||||||
|
mig->flags &= ~QEMU_MIGRATION_COOKIE_PERSISTENT;
|
||||||
|
mig->flagsMandatory &= ~QEMU_MIGRATION_COOKIE_PERSISTENT;
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
|
qemuMigrationCookieAddNetwork(qemuMigrationCookiePtr mig,
|
||||||
virQEMUDriverPtr driver,
|
virQEMUDriverPtr driver,
|
||||||
|
@ -5554,47 +5567,51 @@ qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def)
|
||||||
static int
|
static int
|
||||||
qemuMigrationPersist(virQEMUDriverPtr driver,
|
qemuMigrationPersist(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
qemuMigrationCookiePtr mig)
|
qemuMigrationCookiePtr mig,
|
||||||
|
bool ignoreSaveError)
|
||||||
{
|
{
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
virCapsPtr caps = NULL;
|
virCapsPtr caps = NULL;
|
||||||
virDomainDefPtr vmdef;
|
virDomainDefPtr vmdef;
|
||||||
|
virDomainDefPtr oldDef = NULL;
|
||||||
|
unsigned int oldPersist = vm->persistent;
|
||||||
virObjectEventPtr event;
|
virObjectEventPtr event;
|
||||||
bool newVM;
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
newVM = !vm->persistent;
|
|
||||||
vm->persistent = 1;
|
vm->persistent = 1;
|
||||||
|
oldDef = vm->newDef;
|
||||||
|
vm->newDef = qemuMigrationCookieGetPersistent(mig);
|
||||||
|
|
||||||
if (mig->persistent)
|
if (!(vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm)))
|
||||||
vm->newDef = mig->persistent;
|
goto error;
|
||||||
|
|
||||||
vmdef = virDomainObjGetPersistentDef(caps, driver->xmlopt, vm);
|
if (virDomainSaveConfig(cfg->configDir, vmdef) < 0 && !ignoreSaveError)
|
||||||
if (!vmdef) {
|
goto error;
|
||||||
if (newVM)
|
|
||||||
vm->persistent = 0;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virDomainSaveConfig(cfg->configDir, vmdef) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
event = virDomainEventLifecycleNewFromObj(vm,
|
event = virDomainEventLifecycleNewFromObj(vm,
|
||||||
VIR_DOMAIN_EVENT_DEFINED,
|
VIR_DOMAIN_EVENT_DEFINED,
|
||||||
newVM ?
|
oldPersist ?
|
||||||
VIR_DOMAIN_EVENT_DEFINED_ADDED :
|
VIR_DOMAIN_EVENT_DEFINED_UPDATED :
|
||||||
VIR_DOMAIN_EVENT_DEFINED_UPDATED);
|
VIR_DOMAIN_EVENT_DEFINED_ADDED);
|
||||||
qemuDomainEventQueue(driver, event);
|
qemuDomainEventQueue(driver, event);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
virDomainDefFree(oldDef);
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDomainDefFree(vm->newDef);
|
||||||
|
vm->persistent = oldPersist;
|
||||||
|
vm->newDef = oldDef;
|
||||||
|
oldDef = NULL;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5653,7 +5670,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
|
||||||
*/
|
*/
|
||||||
if (flags & VIR_MIGRATE_OFFLINE) {
|
if (flags & VIR_MIGRATE_OFFLINE) {
|
||||||
if (retcode != 0 ||
|
if (retcode != 0 ||
|
||||||
qemuMigrationPersist(driver, vm, mig) < 0)
|
qemuMigrationPersist(driver, vm, mig, false) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
|
dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
|
||||||
|
@ -5685,7 +5702,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
||||||
if (qemuMigrationPersist(driver, vm, mig) < 0) {
|
if (qemuMigrationPersist(driver, vm, mig, !v3proto) < 0) {
|
||||||
/* Hmpf. Migration was successful, but making it persistent
|
/* Hmpf. Migration was successful, but making it persistent
|
||||||
* was not. If we report successful, then when this domain
|
* was not. If we report successful, then when this domain
|
||||||
* shuts down, management tools are in for a surprise. On the
|
* shuts down, management tools are in for a surprise. On the
|
||||||
|
@ -5796,7 +5813,10 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
|
||||||
qemuMonitorSetDomainLog(priv->mon, -1);
|
qemuMonitorSetDomainLog(priv->mon, -1);
|
||||||
VIR_FREE(priv->origname);
|
VIR_FREE(priv->origname);
|
||||||
virDomainObjEndAPI(&vm);
|
virDomainObjEndAPI(&vm);
|
||||||
qemuMigrationCookieFree(mig);
|
if (mig) {
|
||||||
|
virDomainDefFree(qemuMigrationCookieGetPersistent(mig));
|
||||||
|
qemuMigrationCookieFree(mig);
|
||||||
|
}
|
||||||
if (orig_err) {
|
if (orig_err) {
|
||||||
virSetError(orig_err);
|
virSetError(orig_err);
|
||||||
virFreeError(orig_err);
|
virFreeError(orig_err);
|
||||||
|
|
Loading…
Reference in New Issue