]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Update domain state when reconnecting monitor
authorJiri Denemark <jdenemar@redhat.com>
Thu, 5 May 2011 11:50:25 +0000 (13:50 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Mon, 16 May 2011 11:36:08 +0000 (13:36 +0200)
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.

src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h
src/qemu/qemu_process.c

index 421a81e034cbec8300cda9e7deb6f16f95338ff8..bbc1540d27a122aa6b08563fa7efefbe738c4c3c 100644 (file)
@@ -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;
index ee3e14d88dde833c52be914f87c047aac0375512..476a73fa53e486dbb9bb960d58e543b1ff880b63 100644 (file)
@@ -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);
 
index 32da8939f44fd9d2b70b9c34b5646093a9cabc08..52f0b019567da7a0d89271c4bff80196dcc3794a 100644 (file)
@@ -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;
index 31588825ea963a67c461aea7c0ff4db4aadea3c1..cabb77f938c54a60bfe6f85b32476084f5e3ee17 100644 (file)
@@ -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);
 
index b83809c0e60ef51c257facdea4db2cbd5d5dac61..2d17de0efb28c6bf56b7fc206bd301e86d39ace8 100644 (file)
@@ -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;
 
index 1ee11797edd51228e8f7ed6e4c1f65abb43c144c..148e92f288b5a365d2ff0918c8a8e6a5712cf3e2 100644 (file)
@@ -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);
 
index 3beb666eacf68ce5695ed07f6bca7d009de176ea..01b15e0dba1b73e82618389c0a58d73f3a9f2da8 100644 (file)
@@ -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;