mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06: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 qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -178,6 +178,7 @@ int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
|
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
|
||||||
virConnectPtr conn);
|
virConnectPtr conn);
|
||||||
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
|
||||||
|
int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
|
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 qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -46,6 +46,7 @@ int qemuMonitorJSONCheckHMP(qemuMonitorPtr mon);
|
|||||||
int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon,
|
int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon,
|
||||||
virConnectPtr conn);
|
virConnectPtr conn);
|
||||||
int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
|
int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
|
||||||
|
int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
|
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) {
|
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon) {
|
||||||
char *info;
|
char *info;
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ int qemuMonitorTextCommandWithFd(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
|
int qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
|
||||||
virConnectPtr conn);
|
virConnectPtr conn);
|
||||||
int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
|
int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
|
||||||
|
int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
|
||||||
|
|
||||||
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
|
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
@ -1881,6 +1881,37 @@ qemuProcessFiltersInstantiate(virConnectPtr conn,
|
|||||||
return err;
|
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 {
|
struct qemuProcessReconnectData {
|
||||||
virConnectPtr conn;
|
virConnectPtr conn;
|
||||||
struct qemud_driver *driver;
|
struct qemud_driver *driver;
|
||||||
@ -1916,6 +1947,9 @@ qemuProcessReconnect(void *payload, const void *name ATTRIBUTE_UNUSED, void *opa
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qemuProcessUpdateState(driver, obj) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* If upgrading from old libvirtd we won't have found any
|
/* If upgrading from old libvirtd we won't have found any
|
||||||
* caps in the domain status, so re-query them
|
* 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))
|
if (qemuProcessFiltersInstantiate(conn, obj->def))
|
||||||
goto error;
|
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)
|
if (obj->def->id >= driver->nextvmid)
|
||||||
driver->nextvmid = obj->def->id + 1;
|
driver->nextvmid = obj->def->id + 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user