mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
qemu: Finish domain shutdown on reconnect
If a domain started with -no-shutdown shuts down while libvirtd is not running, it will be seen as paused when libvirtd reconnects to it. Use the paused reason to detect if a domain was stopped because of shutdown and finish the process just as if a SHUTDOWN event is delivered from qemu.
This commit is contained in:
parent
c20b7c9826
commit
cc0e4e8ddb
@ -429,18 +429,15 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static void
|
||||||
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
qemuProcessShutdownOrReboot(virDomainObjPtr vm)
|
||||||
virDomainObjPtr vm)
|
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
VIR_DEBUG("vm=%p", vm);
|
|
||||||
|
|
||||||
virDomainObjLock(vm);
|
|
||||||
if (priv->gotShutdown) {
|
if (priv->gotShutdown) {
|
||||||
VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s",
|
VIR_DEBUG("Ignoring repeated SHUTDOWN event from domain %s",
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
goto cleanup;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->gotShutdown = true;
|
priv->gotShutdown = true;
|
||||||
@ -454,16 +451,23 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
vm) < 0) {
|
vm) < 0) {
|
||||||
VIR_ERROR(_("Failed to create reboot thread, killing domain"));
|
VIR_ERROR(_("Failed to create reboot thread, killing domain"));
|
||||||
qemuProcessKill(vm, true);
|
qemuProcessKill(vm, true);
|
||||||
if (virDomainObjUnref(vm) == 0)
|
/* Safe to ignore value since ref count was incremented above */
|
||||||
vm = NULL;
|
ignore_value(virDomainObjUnref(vm));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qemuProcessKill(vm, true);
|
qemuProcessKill(vm, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
static int
|
||||||
if (vm)
|
qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||||
virDomainObjUnlock(vm);
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("vm=%p", vm);
|
||||||
|
|
||||||
|
virDomainObjLock(vm);
|
||||||
|
qemuProcessShutdownOrReboot(vm);
|
||||||
|
virDomainObjUnlock(vm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2572,6 +2576,8 @@ qemuProcessReconnect(void *opaque)
|
|||||||
qemuDomainObjPrivatePtr priv;
|
qemuDomainObjPrivatePtr priv;
|
||||||
virConnectPtr conn = data->conn;
|
virConnectPtr conn = data->conn;
|
||||||
struct qemuDomainJobObj oldjob;
|
struct qemuDomainJobObj oldjob;
|
||||||
|
int state;
|
||||||
|
int reason;
|
||||||
|
|
||||||
memcpy(&oldjob, &data->oldjob, sizeof(oldjob));
|
memcpy(&oldjob, &data->oldjob, sizeof(oldjob));
|
||||||
|
|
||||||
@ -2603,7 +2609,8 @@ qemuProcessReconnect(void *opaque)
|
|||||||
if (qemuProcessUpdateState(driver, obj) < 0)
|
if (qemuProcessUpdateState(driver, obj) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (virDomainObjGetState(obj, NULL) == VIR_DOMAIN_SHUTOFF) {
|
state = virDomainObjGetState(obj, &reason);
|
||||||
|
if (state == VIR_DOMAIN_SHUTOFF) {
|
||||||
VIR_DEBUG("Domain '%s' wasn't fully started yet, killing it",
|
VIR_DEBUG("Domain '%s' wasn't fully started yet, killing it",
|
||||||
obj->def->name);
|
obj->def->name);
|
||||||
goto error;
|
goto error;
|
||||||
@ -2618,6 +2625,18 @@ qemuProcessReconnect(void *opaque)
|
|||||||
&priv->qemuCaps) < 0)
|
&priv->qemuCaps) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
/* In case the domain was paused for shutdown while we were not running,
|
||||||
|
* we need to finish the shutdown process. And we need to do it after
|
||||||
|
* we have qemuCaps filled in.
|
||||||
|
*/
|
||||||
|
if (state == VIR_DOMAIN_PAUSED
|
||||||
|
&& reason == VIR_DOMAIN_PAUSED_SHUTTING_DOWN) {
|
||||||
|
VIR_DEBUG("Domain %s shut down while we were not running;"
|
||||||
|
" finishing shutdown sequence", obj->def->name);
|
||||||
|
qemuProcessShutdownOrReboot(obj);
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
|
||||||
priv->persistentAddrs = 1;
|
priv->persistentAddrs = 1;
|
||||||
|
|
||||||
@ -2647,12 +2666,13 @@ qemuProcessReconnect(void *opaque)
|
|||||||
if (obj->def->id >= driver->nextvmid)
|
if (obj->def->id >= driver->nextvmid)
|
||||||
driver->nextvmid = obj->def->id + 1;
|
driver->nextvmid = obj->def->id + 1;
|
||||||
|
|
||||||
if (virDomainObjUnref(obj) > 0)
|
endjob:
|
||||||
virDomainObjUnlock(obj);
|
|
||||||
|
|
||||||
if (qemuDomainObjEndJob(driver, obj) == 0)
|
if (qemuDomainObjEndJob(driver, obj) == 0)
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
|
|
||||||
|
if (obj && virDomainObjUnref(obj) > 0)
|
||||||
|
virDomainObjUnlock(obj);
|
||||||
|
|
||||||
qemuDriverUnlock(driver);
|
qemuDriverUnlock(driver);
|
||||||
|
|
||||||
virConnectClose(conn);
|
virConnectClose(conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user