mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 14:57:42 +00:00
Add RESUME event listener to qemu monitor.
Perform all the appropriate plumbing. When qemu/KVM VMs are paused manually through a monitor not-owned by libvirt, libvirt will think of them as "paused" event after they are resumed and effectively running. With this patch the discrepancy goes away. This is meant to address bug 892791. Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org>
This commit is contained in:
parent
3b54b2e345
commit
aedfcce33e
@ -1022,6 +1022,16 @@ int qemuMonitorEmitStop(qemuMonitorPtr mon)
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorEmitResume(qemuMonitorPtr mon)
|
||||
{
|
||||
int ret = -1;
|
||||
VIR_DEBUG("mon=%p", mon);
|
||||
|
||||
QEMU_MONITOR_CALLBACK(mon, ret, domainResume, mon->vm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset)
|
||||
{
|
||||
int ret = -1;
|
||||
|
@ -97,6 +97,8 @@ struct _qemuMonitorCallbacks {
|
||||
virDomainObjPtr vm);
|
||||
int (*domainStop)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm);
|
||||
int (*domainResume)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm);
|
||||
int (*domainRTCChange)(qemuMonitorPtr mon,
|
||||
virDomainObjPtr vm,
|
||||
long long offset);
|
||||
@ -187,6 +189,7 @@ int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitReset(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitStop(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitResume(qemuMonitorPtr mon);
|
||||
int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset);
|
||||
int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action);
|
||||
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
||||
|
@ -55,6 +55,7 @@ static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr da
|
||||
static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data);
|
||||
@ -87,6 +88,7 @@ static qemuEventHandler eventHandlers[] = {
|
||||
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
|
||||
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
|
||||
{ "RESET", qemuMonitorJSONHandleReset, },
|
||||
{ "RESUME", qemuMonitorJSONHandleResume, },
|
||||
{ "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
|
||||
{ "SHUTDOWN", qemuMonitorJSONHandleShutdown, },
|
||||
{ "SPICE_CONNECTED", qemuMonitorJSONHandleSPICEConnect, },
|
||||
@ -589,6 +591,11 @@ static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data A
|
||||
qemuMonitorEmitStop(mon);
|
||||
}
|
||||
|
||||
static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
qemuMonitorEmitResume(mon);
|
||||
}
|
||||
|
||||
static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data)
|
||||
{
|
||||
long long offset = 0;
|
||||
|
@ -735,6 +735,61 @@ unlock:
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessHandleResume(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
virDomainObjPtr vm)
|
||||
{
|
||||
virQEMUDriverPtr driver = qemu_driver;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
virDomainObjLock(vm);
|
||||
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
|
||||
if (priv->gotShutdown) {
|
||||
VIR_DEBUG("Ignoring RESUME event after SHUTDOWN");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Transitioned guest %s out of paused into resumed state",
|
||||
vm->def->name);
|
||||
|
||||
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
|
||||
VIR_DOMAIN_RUNNING_UNPAUSED);
|
||||
event = virDomainEventNewFromObj(vm,
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
|
||||
|
||||
VIR_DEBUG("Using lock state '%s' on resume event", NULLSTR(priv->lockState));
|
||||
if (virDomainLockProcessResume(driver->lockManager, driver->uri,
|
||||
vm, priv->lockState) < 0) {
|
||||
/* Don't free priv->lockState on error, because we need
|
||||
* to make sure we have state still present if the user
|
||||
* tries to resume again
|
||||
*/
|
||||
goto unlock;
|
||||
}
|
||||
VIR_FREE(priv->lockState);
|
||||
|
||||
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
|
||||
VIR_WARN("Unable to save status on vm %s after state change",
|
||||
vm->def->name);
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
virDomainObjUnlock(vm);
|
||||
|
||||
if (event) {
|
||||
qemuDriverLock(driver);
|
||||
qemuDomainEventQueue(driver, event);
|
||||
qemuDriverUnlock(driver);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
||||
virDomainObjPtr vm,
|
||||
@ -1250,6 +1305,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
|
||||
.diskSecretLookup = qemuProcessFindVolumeQcowPassphrase,
|
||||
.domainShutdown = qemuProcessHandleShutdown,
|
||||
.domainStop = qemuProcessHandleStop,
|
||||
.domainResume = qemuProcessHandleResume,
|
||||
.domainReset = qemuProcessHandleReset,
|
||||
.domainRTCChange = qemuProcessHandleRTCChange,
|
||||
.domainWatchdog = qemuProcessHandleWatchdog,
|
||||
|
Loading…
Reference in New Issue
Block a user