A qemu domain can get paused when libvirtd is stopped (e.g., because of
I/O error) so we should check its current state when reconnecting to it.
---
Notes:
    Version 2:
    - new patch

 src/qemu/qemu_monitor.c      |   20 ++++++++++++++++++++
 src/qemu/qemu_monitor.h      |    1 +
 src/qemu/qemu_monitor_json.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |    1 +
 src/qemu/qemu_monitor_text.c |   30 ++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_text.h |    1 +
 src/qemu/qemu_process.c      |   38 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index f89038e..a36a9da 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -981,6 +981,26 @@ qemuMonitorStopCPUs(qemuMonitorPtr mon)
 }
 
 
+int
+qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running)
+{
+    int ret;
+    VIR_DEBUG("mon=%p, running=%p", mon, running);
+
+    if (!mon || !running) {
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("both monitor and running must not be NULL"));
+        return -1;
+    }
+
+    if (mon->json)
+        ret = qemuMonitorJSONGetStatus(mon, running);
+    else
+        ret = qemuMonitorTextGetStatus(mon, running);
+    return ret;
+}
+
+
 int qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
 {
     int ret;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c90219b..21ed3c3 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -178,6 +178,7 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
 int qemuMonitorStartCPUs(qemuMonitorPtr mon,
                          virConnectPtr conn);
 int qemuMonitorStopCPUs(qemuMonitorPtr mon);
+int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
 
 int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
 
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 20a78e1..d9d5952 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -852,6 +852,48 @@ qemuMonitorJSONStopCPUs(qemuMonitorPtr mon)
 }
 
 
+int
+qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running)
+{
+    int ret;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+    virJSONValuePtr data;
+
+    if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL)))
+        return -1;
+
+    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+    if (ret == 0)
+        ret = qemuMonitorJSONCheckError(cmd, reply);
+
+    if (ret < 0)
+        goto cleanup;
+
+    ret = -1;
+
+    if (!(data = virJSONValueObjectGet(reply, "return"))) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("query-status reply was missing return data"));
+        goto cleanup;
+    }
+
+    if (virJSONValueObjectGetBoolean(data, "running", running) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("query-status reply was missing running state"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
+
+
 int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon)
 {
     int ret;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 086f0e1..789db49 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -46,6 +46,7 @@ int qemuMonitorJSONCheckHMP(qemuMonitorPtr mon);
 int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon,
                              virConnectPtr conn);
 int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
+int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
 
 int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
 
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 53781c8..c839986 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -373,6 +373,36 @@ qemuMonitorTextStopCPUs(qemuMonitorPtr mon) {
 }
 
 
+int
+qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running)
+{
+    char *reply;
+    int ret = -1;
+
+    if (qemuMonitorHMPCommand(mon, "info status", &reply) < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        "%s", _("cannot get status info"));
+        return -1;
+    }
+
+    if (strstr(reply, "running")) {
+        *running = true;
+    } else if (strstr(reply, "paused")) {
+        *running = false;
+    } else {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        _("unexpected reply from info status: %s"), reply);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(reply);
+    return ret;
+}
+
+
 int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon) {
     char *info;
 
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 0838a2b..298cb3b 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -43,6 +43,7 @@ int qemuMonitorTextCommandWithFd(qemuMonitorPtr mon,
 int qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
                              virConnectPtr conn);
 int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
+int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
 
 int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f74122e..d7a3353 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1881,6 +1881,37 @@ qemuProcessFiltersInstantiate(virConnectPtr conn,
     return err;
 }
 
+static int
+qemuProcessUpdateState(struct qemud_driver *driver, virDomainObjPtr vm)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainState state;
+    bool running;
+    int ret;
+
+    qemuDomainObjEnterMonitorWithDriver(driver, vm);
+    ret = qemuMonitorGetStatus(priv->mon, &running);
+    qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+    if (ret < 0 || !virDomainObjIsActive(vm))
+        return -1;
+
+    state = virDomainObjGetState(vm, NULL);
+
+    if (state == VIR_DOMAIN_PAUSED && running) {
+        VIR_DEBUG("Domain %s was unpaused while its monitor was disconnected;"
+                  " changing state to running", vm->def->name);
+        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+                             VIR_DOMAIN_RUNNING_UNPAUSED);
+    } else if (state == VIR_DOMAIN_RUNNING && !running) {
+        VIR_DEBUG("Domain %s was paused while its monitor was disconnected;"
+                  " changing state to paused", vm->def->name);
+        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
+    }
+
+    return 0;
+}
+
 struct qemuProcessReconnectData {
     virConnectPtr conn;
     struct qemud_driver *driver;
@@ -1916,6 +1947,9 @@ qemuProcessReconnect(void *payload, const void *name 
ATTRIBUTE_UNUSED, void *opa
         goto error;
     }
 
+    if (qemuProcessUpdateState(driver, obj) < 0)
+        goto error;
+
     /* If upgrading from old libvirtd we won't have found any
      * caps in the domain status, so re-query them
      */
@@ -1939,6 +1973,10 @@ qemuProcessReconnect(void *payload, const void *name 
ATTRIBUTE_UNUSED, void *opa
     if (qemuProcessFiltersInstantiate(conn, obj->def))
         goto error;
 
+    /* update domain state XML with possibly updated state in virDomainObj */
+    if (virDomainSaveStatus(driver->caps, driver->stateDir, obj) < 0)
+        goto error;
+
     if (obj->def->id >= driver->nextvmid)
         driver->nextvmid = obj->def->id + 1;
 
-- 
1.7.5.rc3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to