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:
Chris Lalancette 2010-04-16 22:12:45 -04:00
parent 21adf03c2d
commit 057e855324
7 changed files with 126 additions and 1 deletions

View File

@ -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 */
};

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */