mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 14:15:28 +00:00
Qemu arbitrary monitor commands.
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@redhat.com>
This commit is contained in:
parent
21adf03c2d
commit
057e855324
@ -121,6 +121,7 @@ struct _qemuDomainObjPrivate {
|
||||
qemuMonitorPtr mon;
|
||||
virDomainChrDefPtr monConfig;
|
||||
int monJSON;
|
||||
int monitor_warned;
|
||||
|
||||
int nvcpupids;
|
||||
int *vcpupids;
|
||||
@ -3716,6 +3717,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"),
|
||||
@ -12561,6 +12564,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",
|
||||
@ -12660,7 +12714,7 @@ static virDriver qemuDriver = {
|
||||
qemuDomainSnapshotCurrent, /* domainSnapshotCurrent */
|
||||
qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */
|
||||
qemuDomainSnapshotDelete, /* domainSnapshotDelete */
|
||||
NULL, /* qemuDomainMonitorCommand */
|
||||
qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -2345,3 +2345,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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user