mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 03:12:22 +00:00
qemu: Update domain state when reconnecting monitor
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.
This commit is contained in:
parent
b046c55d40
commit
9f1319618a
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user