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