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:
Jiri Denemark 2011-05-05 13:50:25 +02:00
parent b046c55d40
commit 9f1319618a
7 changed files with 133 additions and 0 deletions

View 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;

View 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);

View 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;

View 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);

View 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;

View 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);

View 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;