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