Implement the qemu driver's virDomainQemuMonitorCommand
and hook it into the API entry point.
Changes since v1:
- Rename the (external) qemuMonitorCommand to qemuDomainMonitorCommand
- Add virCheckFlags to qemuDomainMonitorCommand
Changes since v2:
- Drop ATTRIBUTE_UNUSED from the flags
Changes since v3:
- Add a flag to priv so we only print out monitor command warning once. Note
that this has not been plumbed into qemuDomainObjPrivateXMLFormat or
qemuDomainObjPrivateXMLParse, which means that if you run a monitor command,
restart libvirtd, and then run another monitor command, you may get an
an erroneous VIR_INFO. It's a pretty minor matter, and I didn't think it
warranted the additional code.
- Add BeginJob/EndJob calls around EnterMonitor/ExitMonitor
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
src/qemu/qemu_driver.c | 56 +++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_monitor.c | 13 +++++++++
src/qemu/qemu_monitor.h | 2 +
src/qemu/qemu_monitor_json.c | 28 +++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 4 +++
src/qemu/qemu_monitor_text.c | 21 +++++++++++++++
src/qemu/qemu_monitor_text.h | 3 ++
7 files changed, 126 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e2b28a4..dfdcfb0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -121,6 +121,7 @@ struct _qemuDomainObjPrivate {
qemuMonitorPtr mon;
virDomainChrDefPtr monConfig;
int monJSON;
+ int monitor_warned;
int nvcpupids;
int *vcpupids;
@@ -3672,6 +3673,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
#endif
priv->monJSON = 0;
+ priv->monitor_warned = 0;
+
if ((ret = virFileDeletePid(driver->stateDir, vm->def->name)) != 0) {
virReportSystemError(ret,
_("Cannot remove stale PID file for %s"),
@@ -12443,6 +12446,57 @@ cleanup:
return ret;
}
+static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
+ char **result, unsigned int flags)
+{
+ struct qemud_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv;
+
+ virCheckFlags(0, -1);
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+ if (!vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(domain->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;
+
+ if (!priv->monitor_warned) {
+ VIR_INFO("Qemu monitor command '%s' executed; libvirt results may be
unpredictable!",
+ cmd);
+ priv->monitor_warned = 1;
+ }
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
+ goto cleanup;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ if (qemuDomainObjEndJob(vm) == 0) {
+ vm = NULL;
+ goto cleanup;
+ }
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ qemuDriverUnlock(driver);
+ return ret;
+}
+
static virDriver qemuDriver = {
VIR_DRV_QEMU,
"QEMU",
@@ -12542,7 +12596,7 @@ static virDriver qemuDriver = {
qemuDomainSnapshotCurrent, /* domainSnapshotCurrent */
qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */
qemuDomainSnapshotDelete, /* domainSnapshotDelete */
- NULL, /* qemuDomainMonitorCommand */
+ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b05032a..f1494ff 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1918,3 +1918,16 @@ int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char
*name)
ret = qemuMonitorTextDeleteSnapshot(mon, name);
return ret;
}
+
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply)
+{
+ int ret;
+
+ DEBUG("mon=%p, cmd=%s, reply=%p", mon, cmd, reply);
+
+ if (mon->json)
+ ret = qemuMonitorJSONArbitraryCommand(mon, cmd, reply);
+ else
+ ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply);
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 459ccb7..48f4c20 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -389,4 +389,6 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name);
int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name);
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply);
+
#endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 01be86d..5ea71f2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2344,3 +2344,31 @@ int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char
*name)
virJSONValueFree(reply);
return ret;
}
+
+int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
+ const char *cmd_str,
+ char **reply_str)
+{
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ int ret = -1;
+
+ cmd = virJSONValueFromString(cmd_str);
+ if (!cmd)
+ return -1;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ goto cleanup;
+
+ *reply_str = virJSONValueToString(reply);
+ if (!(*reply_str))
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 6fa8d83..94806c1 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -196,4 +196,8 @@ int qemuMonitorJSONCreateSnapshot(qemuMonitorPtr mon, const char
*name);
int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name);
int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name);
+int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
+ const char *cmd_str,
+ char **reply_str);
+
#endif /* QEMU_MONITOR_JSON_H */
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 569742a..69971a6 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -2567,3 +2567,24 @@ cleanup:
VIR_FREE(reply);
return ret;
}
+
+int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
+ char **reply)
+{
+ char *safecmd = NULL;
+ int ret;
+
+ if (!(safecmd = qemuMonitorEscapeArg(cmd))) {
+ virReportOOMError();
+ return -1;
+ }
+
+ ret = qemuMonitorCommand(mon, safecmd, reply);
+ if (ret != 0)
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to run cmd '%s'"), safecmd);
+
+ VIR_FREE(safecmd);
+
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 9926d34..c017509 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -194,4 +194,7 @@ int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char
*name);
int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name);
int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name);
+int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
+ char **reply);
+
#endif /* QEMU_MONITOR_TEXT_H */
--
1.6.6.1