QEMU_MONITOR_MIGRATION_STATUS_LAST,
"inactive", "active", "completed", "failed", "cancelled")
+VIR_ENUM_IMPL(qemuMonitorVMStatus,
+ QEMU_MONITOR_VM_STATUS_LAST,
+ "debug", "inmigrate", "internal-error", "io-error", "paused",
+ "postmigrate", "prelaunch", "finish-migrate", "restore-vm",
+ "running", "save-vm", "shutdown", "watchdog")
+
char *qemuMonitorEscapeArg(const char *in)
{
int len = 0;
int
-qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
int ret;
- VIR_DEBUG("mon=%p, running=%p", mon, running);
+ VIR_DEBUG("mon=%p, running=%p, reason=%p", mon, running, reason);
if (!mon || !running) {
qemuReportError(VIR_ERR_INVALID_ARG, "%s",
}
if (mon->json)
- ret = qemuMonitorJSONGetStatus(mon, running);
+ ret = qemuMonitorJSONGetStatus(mon, running, reason);
else
- ret = qemuMonitorTextGetStatus(mon, running);
+ ret = qemuMonitorTextGetStatus(mon, running, reason);
return ret;
}
ret = qemuMonitorTextBlockJob(mon, device, bandwidth, info, mode);
return ret;
}
+
+int qemuMonitorVMStatusToPausedReason(const char *status)
+{
+ int st;
+
+ if (!status)
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ if ((st = qemuMonitorVMStatusTypeFromString(status)) < 0) {
+ VIR_WARN("Qemu reported unknown VM status: '%s'", status);
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+ }
+
+ switch ((qemuMonitorVMStatus) st) {
+ case QEMU_MONITOR_VM_STATUS_DEBUG:
+ case QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR:
+ case QEMU_MONITOR_VM_STATUS_RESTORE_VM:
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ case QEMU_MONITOR_VM_STATUS_INMIGRATE:
+ case QEMU_MONITOR_VM_STATUS_POSTMIGRATE:
+ case QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE:
+ return VIR_DOMAIN_PAUSED_MIGRATION;
+
+ case QEMU_MONITOR_VM_STATUS_IO_ERROR:
+ return VIR_DOMAIN_PAUSED_IOERROR;
+
+ case QEMU_MONITOR_VM_STATUS_PAUSED:
+ case QEMU_MONITOR_VM_STATUS_PRELAUNCH:
+ return VIR_DOMAIN_PAUSED_USER;
+
+ case QEMU_MONITOR_VM_STATUS_RUNNING:
+ VIR_WARN("Qemu reports the guest is paused but status is 'running'");
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+
+ case QEMU_MONITOR_VM_STATUS_SAVE_VM:
+ return VIR_DOMAIN_PAUSED_SAVE;
+
+ case QEMU_MONITOR_VM_STATUS_SHUTDOWN:
+ return VIR_DOMAIN_PAUSED_SHUTTING_DOWN;
+
+ case QEMU_MONITOR_VM_STATUS_WATCHDOG:
+ return VIR_DOMAIN_PAUSED_WATCHDOG;
+
+ /* unreachable from this point on */
+ case QEMU_MONITOR_VM_STATUS_LAST:
+ ;
+ }
+ return VIR_DOMAIN_PAUSED_UNKNOWN;
+}
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorGetStatus(qemuMonitorPtr mon, bool *running);
+
+typedef enum {
+ QEMU_MONITOR_VM_STATUS_DEBUG,
+ QEMU_MONITOR_VM_STATUS_INMIGRATE,
+ QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR,
+ QEMU_MONITOR_VM_STATUS_IO_ERROR,
+ QEMU_MONITOR_VM_STATUS_PAUSED,
+ QEMU_MONITOR_VM_STATUS_POSTMIGRATE,
+ QEMU_MONITOR_VM_STATUS_PRELAUNCH,
+ QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE,
+ QEMU_MONITOR_VM_STATUS_RESTORE_VM,
+ QEMU_MONITOR_VM_STATUS_RUNNING,
+ QEMU_MONITOR_VM_STATUS_SAVE_VM,
+ QEMU_MONITOR_VM_STATUS_SHUTDOWN,
+ QEMU_MONITOR_VM_STATUS_WATCHDOG,
+
+ QEMU_MONITOR_VM_STATUS_LAST
+} qemuMonitorVMStatus;
+VIR_ENUM_DECL(qemuMonitorVMStatus)
+int qemuMonitorVMStatusToPausedReason(const char *status);
+
+int qemuMonitorGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorSystemReset(qemuMonitorPtr mon);
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon);
int
-qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
int ret;
+ const char *status;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
virJSONValuePtr data;
+ if (reason)
+ *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
+
if (!(cmd = qemuMonitorJSONMakeCommand("query-status", NULL)))
return -1;
goto cleanup;
}
+ if ((status = virJSONValueObjectGetString(data, "status"))) {
+ if (!*running && reason)
+ *reason = qemuMonitorVMStatusToPausedReason(status);
+ } else if (!*running) {
+ VIR_DEBUG("query-status reply was missing status details");
+ }
+
ret = 0;
cleanup:
int qemuMonitorJSONStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorJSONStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorJSONGetStatus(qemuMonitorPtr mon, bool *running);
+int qemuMonitorJSONGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorJSONSystemPowerdown(qemuMonitorPtr mon);
int qemuMonitorJSONSystemReset(qemuMonitorPtr mon);
int
-qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running)
+qemuMonitorTextGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason)
{
char *reply;
int ret = -1;
+ if (reason)
+ *reason = VIR_DOMAIN_PAUSED_UNKNOWN;
+
if (qemuMonitorHMPCommand(mon, "info status", &reply) < 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("cannot get status info"));
if (strstr(reply, "running")) {
*running = true;
} else if (strstr(reply, "paused")) {
+ char *status;
+
+ if ((status = strchr(reply, '('))) {
+ char *end = strchr(status, ')');
+ if (end)
+ *end = '\0';
+ else
+ status = NULL;
+ }
+ if (!status)
+ VIR_DEBUG("info status was missing status details");
+ else if (reason)
+ *reason = qemuMonitorVMStatusToPausedReason(status);
*running = false;
} else {
qemuReportError(VIR_ERR_OPERATION_FAILED,
int qemuMonitorTextStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
int qemuMonitorTextStopCPUs(qemuMonitorPtr mon);
-int qemuMonitorTextGetStatus(qemuMonitorPtr mon, bool *running);
+int qemuMonitorTextGetStatus(qemuMonitorPtr mon,
+ bool *running,
+ virDomainPausedReason *reason);
int qemuMonitorTextSystemPowerdown(qemuMonitorPtr mon);
int qemuMonitorTextSystemReset(qemuMonitorPtr mon);
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainState state;
+ virDomainPausedReason reason;
bool running;
int ret;
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- ret = qemuMonitorGetStatus(priv->mon, &running);
+ ret = qemuMonitorGetStatus(priv->mon, &running, &reason);
qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0 || !virDomainObjIsActive(vm))
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);
+ VIR_DEBUG("Domain %s was paused (%s) while its monitor was"
+ " disconnected; changing state to paused",
+ vm->def->name, virDomainPausedReasonTypeToString(reason));
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
} else if (state == VIR_DOMAIN_SHUTOFF && running) {
VIR_DEBUG("Domain %s finished booting; changing state to running",
vm->def->name);
char *timestamp;
qemuDomainObjPrivatePtr priv = vm->privateData;
bool running = true;
+ virDomainPausedReason reason;
virSecurityLabelPtr seclabel = NULL;
VIR_DEBUG("Beginning VM attach process");
qemuDomainObjExitMonitorWithDriver(driver, vm);
goto cleanup;
}
- if (qemuMonitorGetStatus(priv->mon, &running) < 0) {
+ if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
goto cleanup;
}
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNPAUSED);
else
- virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_UNKNOWN);
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, reason);
VIR_DEBUG("Writing domain status to disk");
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)