diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 5f18ad3f2c..06d2a5e28e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -609,6 +609,7 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) qemuMonitorLock(priv->mon); qemuMonitorRef(priv->mon); + virTimeMs(&priv->monStart); virDomainObjUnlock(obj); } @@ -629,6 +630,7 @@ void qemuDomainObjExitMonitor(virDomainObjPtr obj) virDomainObjLock(obj); + priv->monStart = 0; if (refs == 0) { priv->mon = NULL; } @@ -650,6 +652,7 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, qemuMonitorLock(priv->mon); qemuMonitorRef(priv->mon); + virTimeMs(&priv->monStart); virDomainObjUnlock(obj); qemuDriverUnlock(driver); } @@ -674,6 +677,7 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, qemuDriverLock(driver); virDomainObjLock(obj); + priv->monStart = 0; if (refs == 0) { priv->mon = NULL; } diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index bacf5b5340..3d041fc074 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -79,6 +79,8 @@ struct _qemuDomainObjPrivate { qemuMonitorPtr mon; virDomainChrSourceDefPtr monConfig; int monJSON; + bool monError; + unsigned long long monStart; bool gotShutdown; int nvcpupids; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 853c84c392..563520481a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1873,6 +1873,66 @@ cleanup: return ret; } +static int +qemuDomainGetControlInfo(virDomainPtr dom, + virDomainControlInfoPtr info, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + qemuDomainObjPrivatePtr priv; + int ret = -1; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto cleanup; + } + + priv = vm->privateData; + + memset(info, 0, sizeof(*info)); + + if (priv->monError) { + info->state = VIR_DOMAIN_CONTROL_ERROR; + } else if (priv->jobActive) { + if (!priv->monStart) { + info->state = VIR_DOMAIN_CONTROL_JOB; + if (virTimeMs(&info->stateTime) < 0) + goto cleanup; + info->stateTime -= priv->jobStart; + } else { + info->state = VIR_DOMAIN_CONTROL_OCCUPIED; + if (virTimeMs(&info->stateTime) < 0) + goto cleanup; + info->stateTime -= priv->monStart; + } + } else { + info->state = VIR_DOMAIN_CONTROL_OK; + } + + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + return ret; +} + #define QEMUD_SAVE_MAGIC "LibvirtQemudSave" #define QEMUD_SAVE_VERSION 2 @@ -8159,6 +8219,7 @@ static virDriver qemuDriver = { .domainGetBlkioParameters = qemuDomainGetBlkioParameters, /* 0.9.0 */ .domainGetInfo = qemudDomainGetInfo, /* 0.2.0 */ .domainGetState = qemuDomainGetState, /* 0.9.2 */ + .domainGetControlInfo = qemuDomainGetControlInfo, /* 0.9.3 */ .domainSave = qemudDomainSave, /* 0.2.0 */ .domainRestore = qemuDomainRestore, /* 0.2.0 */ .domainCoreDump = qemudDomainCoreDump, /* 0.7.0 */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 683841700c..fe66100fe7 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -166,6 +166,7 @@ qemuProcessHandleMonitorError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, qemuDriverLock(driver); virDomainObjLock(vm); + ((qemuDomainObjPrivatePtr) vm->privateData)->monError = true; event = virDomainEventControlErrorNewFromObj(vm); if (event) qemuDomainEventQueue(driver, event); @@ -2300,6 +2301,8 @@ int qemuProcessStart(virConnectPtr conn, #endif priv->monJSON = 0; + priv->monError = false; + priv->monStart = 0; priv->gotShutdown = false; if ((ret = virFileDeletePid(driver->stateDir, vm->def->name)) != 0) {