]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add RESUME event listener to qemu monitor.
authorAndres Lagar-Cavilla <andres@lagarcavilla.org>
Mon, 7 Jan 2013 21:25:01 +0000 (16:25 -0500)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 9 Jan 2013 09:17:40 +0000 (10:17 +0100)
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>
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_process.c

index 99642b647cbc509ca16aa38abd9935e119e8c0dc..cb5a3e2838c53c271da322cc46c276a5056816e8 100644 (file)
@@ -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;
index d7faa9027a9db0880ea4b41b23f5a62572d872e6..00ce8136e6d91f79ba9bc2ed4dcf068b29f82010 100644 (file)
@@ -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,
index 2d2d254eed1f881ddc17f3eff6cf6350d470886d..de5f1155e8743b51e05a0715532f88fc937f33a8 100644 (file)
@@ -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;
index f5fc1b36fdbabc041dfea4910b4e5934713b5576..938c17efcfca3befeb64a5611ed1591cbff0a862 100644 (file)
@@ -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,