Hi, All.
Thank you for many comments.
And I extremely apologize not to use git... My company's network closes
the almost port and only http via proxy and simple mail are available.
The attached patch is reflected all comments.
Especially,
>> diff -uNrp libvirt-0.9.13.orig/src/driver.h libvirt-0.9.13/src/driver.h
>> --- libvirt-0.9.13.orig/src/driver.h 2012-06-25 16:06:18.000000000 +0900
>> +++ libvirt-0.9.13/src/driver.h 2012-07-02 10:02:54.405454285 +0900
>> @@ -860,6 +860,10 @@ typedef char *
>> const char *uri,
>> unsigned int flags);
>>
>> +typedef int
>> + (*virDrvDomainGuestAgentCommand)(virDomainPtr domain, const
char *cmd,
>> + char **result, unsigned int
flags);
>> +
>> /**
>> * _virDriver:
>> *
>> @@ -1041,6 +1045,7 @@ struct _virDriver {
>> virDrvDomainGetDiskErrors domainGetDiskErrors;
>> virDrvDomainSetMetadata domainSetMetadata;
>> virDrvDomainGetMetadata domainGetMetadata;
>> + virDrvDomainGuestAgentCommand qemuDomainGuestAgentCommand;
>> };
>
> I'd move these two as close as possible to
virDrvDomainQemuMonitorCommand so we have similar commands grouped.
I moved virDrvDomainQemuMonitorCommand to virDrvDomainQemuSupportCommand
to close two functions.
In addition,
>> diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_agent.c
libvirt-0.9.13/src/qemu/qemu_agent.c
>> --- libvirt-0.9.13.orig/src/qemu/qemu_agent.c 2012-06-25
16:06:18.000000000 +0900
>> +++ libvirt-0.9.13/src/qemu/qemu_agent.c 2012-07-02
10:02:54.408488163 +0900
>> @@ -1410,3 +1410,29 @@ qemuAgentSuspend(qemuAgentPtr mon,
>> virJSONValueFree(reply);
>> return ret;
>> }
>> +
>> +int qemuAgentGuestAgentCommand(qemuAgentPtr mon,
>> + const char *cmd,
>> + char **result)
>> +{
>> + int ret = -1;
>> + virJSONValuePtr jcmd;
>> + virJSONValuePtr reply = NULL;
>> +
>> + jcmd = qemuAgentMakeCommand(cmd, NULL);
>> + if (!jcmd)
>> + return ret;
>
> This is confusing. In case of qemu-monitor-command we require user to
pass whole command string:
> {'execute':'some-dummy-command'}
> which is correct as we don't lock them in {'execute':'%s'} scheme.
Remember, we want them to
> use commands/features not yet exposed by libvirt. So if qemu will
ever come up with different
> command scheme this API will remain broken. In addition - and this is
even more serious - there is
> no way of specifying arguments to a command, e.g. guest-sync take an
integer:
> {'execute':'guest-sync', 'arguments':{'id':123}}
> Therefore I think we need to drop qemuAgentMakeCommand() here and
require users to do
> the very same here as they do in qemu-monitor-command.
I prefer to the type of 'virsh qemu-agent-command guest-info', bacause
it is user friendly. But I understood the problem and fixed.
Regards
MATSUDA Daiki
$ diffstat libvirt-0.9.13_qemu_agent_command3.patch
daemon/remote.c | 36 +++++++++++++++++
docs/hvsupport.pl | 1
include/libvirt/libvirt-qemu.h | 3 +
python/generator.py | 1
python/libvirt-qemu-override-api.xml | 7 +++
python/libvirt-qemu-override.c | 31 ++++++++++++++
src/driver.h | 5 +-
src/libvirt-qemu.c | 49 +++++++++++++++++++++++
src/libvirt_qemu.syms | 5 ++
src/qemu/qemu_agent.c | 26 ++++++++++++
src/qemu/qemu_agent.h | 4 +
src/qemu/qemu_driver.c | 73
+++++++++++++++++++++++++++++++++++
src/qemu_protocol-structs | 9 ++++
src/remote/qemu_protocol.x | 13 +++++-
src/remote/remote_driver.c | 39 ++++++++++++++++++
tools/virsh.c | 64 ++++++++++++++++++++++++++++++
16 files changed, 363 insertions(+), 3 deletions(-)
virsh # qemu-agent-command RHEL58_64 '{"execute":"guest-info"}'
{"return":{"version":"1.1.50","supported_commands":[{"enabled":true,"name":"guest-network-get-interfaces"},{"enabled":true,"name":"guest-suspend-hybrid"},{"enabled":true,"name":"guest-suspend-ram"},{"enabled":true,"name":"guest-suspend-disk"},{"enabled":true,"name":"guest-fsfreeze-thaw"},{"enabled":true,"name":"guest-fsfreeze-freeze"},{"enabled":true,"name":"guest-fsfreeze-status"},{"enabled":true,"name":"guest-file-flush"},{"enabled":true,"name":"guest-file-seek"},{"enabled":true,"name":"guest-file-write"},{"enabled":true,"name":"guest-file-read"},{"enabled":true,"name":"guest-file-close"},{"enabled":true,"name":"guest-file-open"},{"enabled":true,"name":"guest-shutdown"},{"enabled":true,"name":"guest-info"},{"enabled":true,"name":"guest-ping"},{"enabled":true,"name":"guest-sync"},{"enabled":true,"name":"guest-sync-delimited"}]}}
virsh # qemu-agent-command RHEL58_64 '{"execute":"guest-sync",
"arguments":{"id":123}}'
{"return":123}
diff -uNrp libvirt-0.9.13.orig/daemon/remote.c libvirt-0.9.13/daemon/remote.c
--- libvirt-0.9.13.orig/daemon/remote.c 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/daemon/remote.c 2012-07-06 09:18:12.494454191 +0900
@@ -3923,6 +3923,42 @@ cleanup:
return rv;
}
+
+static int
+qemuDispatchAgentCommand(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ qemu_agent_command_args *args,
+ qemu_agent_command_ret *ret)
+{
+ virDomainPtr dom = NULL;
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+ if (virDomainQemuAgentCommand(dom, args->cmd, &ret->result,
+ args->flags) < 0) {
+ goto cleanup;
+ }
+
+ rv = 0;
+cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ if (dom)
+ virDomainFree(dom);
+ return rv;
+}
+
/*----- Helpers. -----*/
/* get_nonnull_domain and get_nonnull_network turn an on-wire
diff -uNrp libvirt-0.9.13.orig/docs/hvsupport.pl libvirt-0.9.13/docs/hvsupport.pl
--- libvirt-0.9.13.orig/docs/hvsupport.pl 2011-06-10 15:50:11.000000000 +0900
+++ libvirt-0.9.13/docs/hvsupport.pl 2012-07-06 09:18:36.363454752 +0900
@@ -129,6 +129,7 @@ $apis{virDomainMigratePerform3} = "0.9.2
$apis{virDomainMigrateFinish3} = "0.9.2";
$apis{virDomainMigrateConfirm3} = "0.9.2";
+$apis{virDomainQemuSupportCommand} = "0.9.14";
# Now we want to get the mapping between public APIs
diff -uNrp libvirt-0.9.13.orig/include/libvirt/libvirt-qemu.h libvirt-0.9.13/include/libvirt/libvirt-qemu.h
--- libvirt-0.9.13.orig/include/libvirt/libvirt-qemu.h 2012-03-06 22:59:21.000000000 +0900
+++ libvirt-0.9.13/include/libvirt/libvirt-qemu.h 2012-07-06 09:18:12.494454191 +0900
@@ -32,6 +32,9 @@ virDomainPtr virDomainQemuAttach(virConn
unsigned int pid_value,
unsigned int flags);
+int virDomainQemuAgentCommand(virDomainPtr domain, const char *cmd,
+ char **result, unsigned int flags);
+
# ifdef __cplusplus
}
# endif
diff -uNrp libvirt-0.9.13.orig/python/generator.py libvirt-0.9.13/python/generator.py
--- libvirt-0.9.13.orig/python/generator.py 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/python/generator.py 2012-07-06 09:18:12.495454550 +0900
@@ -429,6 +429,7 @@ skip_impl = (
qemu_skip_impl = (
'virDomainQemuMonitorCommand',
+ 'virDomainQemuAgentCommand',
)
diff -uNrp libvirt-0.9.13.orig/python/libvirt-qemu-override-api.xml libvirt-0.9.13/python/libvirt-qemu-override-api.xml
--- libvirt-0.9.13.orig/python/libvirt-qemu-override-api.xml 2011-09-14 15:24:44.000000000 +0900
+++ libvirt-0.9.13/python/libvirt-qemu-override-api.xml 2012-07-06 09:18:12.496455183 +0900
@@ -8,5 +8,12 @@
<arg name='cmd' type='const char *' info='the command which will be passed to QEMU monitor'/>
<arg name='flags' type='unsigned int' info='an OR'ed set of virDomainQemuMonitorCommandFlags'/>
</function>
+ <function name='virDomainQemuAgentCommand' file='python-qemu'>
+ <info>Send a Guest Agent command to domain</info>
+ <return type='str *' info='the command output or None in case of error'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='cmd' type='const char *' info='guest agent command on domain'/>
+ <arg name='flags' type='unsigned int' info='execution flags'/>
+ </function>
</symbols>
</api>
diff -uNrp libvirt-0.9.13.orig/python/libvirt-qemu-override.c libvirt-0.9.13/python/libvirt-qemu-override.c
--- libvirt-0.9.13.orig/python/libvirt-qemu-override.c 2012-03-30 11:45:28.000000000 +0900
+++ libvirt-0.9.13/python/libvirt-qemu-override.c 2012-07-06 09:18:12.496455183 +0900
@@ -82,6 +82,36 @@ libvirt_qemu_virDomainQemuMonitorCommand
return py_retval;
}
+static PyObject *
+libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ char *result = NULL;
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ unsigned int flags;
+ char *cmd;
+ int c_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"Ozi:virDomainQemuAgentCommand",
+ &pyobj_domain, &cmd, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (domain == NULL)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virDomainQemuAgentCommand(domain, cmd, &result, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ py_retval = PyString_FromString(result);
+ return py_retval;
+}
+
/************************************************************************
* *
* The registration stuff *
@@ -90,6 +120,7 @@ libvirt_qemu_virDomainQemuMonitorCommand
static PyMethodDef libvirtQemuMethods[] = {
#include "libvirt-qemu-export.c"
{(char *) "virDomainQemuMonitorCommand", libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL},
+ {(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
diff -uNrp libvirt-0.9.13.orig/src/driver.h libvirt-0.9.13/src/driver.h
--- libvirt-0.9.13.orig/src/driver.h 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/driver.h 2012-07-06 09:18:12.497454257 +0900
@@ -680,7 +680,7 @@ typedef int
unsigned int flags);
typedef int
- (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd,
+ (*virDrvDomainQemuSupportCommand)(virDomainPtr domain, const char *cmd,
char **result, unsigned int flags);
/* Choice of unsigned int rather than pid_t is intentional. */
@@ -1015,7 +1015,7 @@ struct _virDriver {
virDrvDomainSnapshotHasMetadata domainSnapshotHasMetadata;
virDrvDomainRevertToSnapshot domainRevertToSnapshot;
virDrvDomainSnapshotDelete domainSnapshotDelete;
- virDrvDomainQemuMonitorCommand qemuDomainMonitorCommand;
+ virDrvDomainQemuSupportCommand qemuDomainMonitorCommand;
virDrvDomainQemuAttach qemuDomainAttach;
virDrvDomainOpenConsole domainOpenConsole;
virDrvDomainOpenGraphics domainOpenGraphics;
@@ -1041,6 +1041,7 @@ struct _virDriver {
virDrvDomainGetDiskErrors domainGetDiskErrors;
virDrvDomainSetMetadata domainSetMetadata;
virDrvDomainGetMetadata domainGetMetadata;
+ virDrvDomainQemuSupportCommand qemuDomainQemuAgentCommand;
};
typedef int
diff -uNrp libvirt-0.9.13.orig/src/libvirt-qemu.c libvirt-0.9.13/src/libvirt-qemu.c
--- libvirt-0.9.13.orig/src/libvirt-qemu.c 2012-05-31 23:23:22.000000000 +0900
+++ libvirt-0.9.13/src/libvirt-qemu.c 2012-07-06 09:18:12.497454257 +0900
@@ -185,3 +185,52 @@ error:
virDispatchError(conn);
return NULL;
}
+
+/**
+ * virDomainQemuAgentCommand:
+ * @domain: a domain object
+ * @cmd: the guest agent command string
+ * @result: a string returned by @cmd
+ * @flags: execution flags
+ *
+ * Execution Guest Agent Command
+ *
+ * Returns 0 if succeeded, -1 in failing.
+ */
+int
+virDomainQemuAgentCommand(virDomainPtr domain,
+ const char *cmd,
+ char **result,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DEBUG("domain=%p, cmd=%s, result=%p, flags=%x",
+ domain, cmd, result, flags);
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = domain->conn;
+
+ virCheckNonNullArgGoto(result, error);
+
+ if (conn->driver->qemuDomainQemuAgentCommand) {
+ int ret;
+ ret = conn->driver->qemuDomainQemuAgentCommand(domain, cmd, result,
+ flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virDispatchError(domain->conn);
+ return -1;
+}
diff -uNrp libvirt-0.9.13.orig/src/libvirt_qemu.syms libvirt-0.9.13/src/libvirt_qemu.syms
--- libvirt-0.9.13.orig/src/libvirt_qemu.syms 2011-07-14 12:00:39.000000000 +0900
+++ libvirt-0.9.13/src/libvirt_qemu.syms 2012-07-06 09:18:12.498454377 +0900
@@ -19,3 +19,8 @@ LIBVIRT_QEMU_0.9.4 {
global:
virDomainQemuAttach;
} LIBVIRT_QEMU_0.8.3;
+
+LIBVIRT_QEMU_0.9.14 {
+ global:
+ virDomainQemuAgentCommand;
+} LIBVIRT_QEMU_0.9.4;
diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_agent.c libvirt-0.9.13/src/qemu/qemu_agent.c
--- libvirt-0.9.13.orig/src/qemu/qemu_agent.c 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/qemu/qemu_agent.c 2012-07-06 09:18:12.498454377 +0900
@@ -1410,3 +1410,29 @@ qemuAgentSuspend(qemuAgentPtr mon,
virJSONValueFree(reply);
return ret;
}
+
+int qemuAgentQemuAgentCommand(qemuAgentPtr mon,
+ const char *cmd_str,
+ char **result)
+{
+ int ret = -1;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+
+ cmd = virJSONValueFromString(cmd_str);
+ if (!cmd)
+ return ret;
+
+ ret = qemuAgentCommand(mon, cmd, &reply);
+
+ if (ret == 0) {
+ ret = qemuAgentCheckError(cmd, reply);
+ *result = virJSONValueToString(reply);
+ } else {
+ *result = NULL;
+ }
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_agent.h libvirt-0.9.13/src/qemu/qemu_agent.h
--- libvirt-0.9.13.orig/src/qemu/qemu_agent.h 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/qemu/qemu_agent.h 2012-07-06 09:18:12.499545367 +0900
@@ -80,4 +80,8 @@ int qemuAgentFSThaw(qemuAgentPtr mon);
int qemuAgentSuspend(qemuAgentPtr mon,
unsigned int target);
+
+int qemuAgentQemuAgentCommand(qemuAgentPtr mon,
+ const char *cmd,
+ char **result);
#endif /* __QEMU_AGENT_H__ */
diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_driver.c libvirt-0.9.13/src/qemu/qemu_driver.c
--- libvirt-0.9.13.orig/src/qemu/qemu_driver.c 2012-06-27 10:44:39.000000000 +0900
+++ libvirt-0.9.13/src/qemu/qemu_driver.c 2012-07-06 09:18:12.503579712 +0900
@@ -13158,6 +13158,78 @@ qemuListAllDomains(virConnectPtr conn,
return ret;
}
+static int
+qemuDomainQemuAgentCommand(virDomainPtr domain,
+ const char *cmd,
+ char **result,
+ unsigned int flags)
+{
+ struct qemud_driver *driver = domain->conn->privateData;
+ virDomainObjPtr vm;
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv;
+
+ virCheckFlags(0, -1);
+
+ qemuDriverLock(driver);
+ vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+ qemuDriverUnlock(driver);
+
+ 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;
+ }
+
+ priv = vm->privateData;
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ if (priv->agentError) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("QEMU guest agent is not available due to an error"));
+ goto cleanup;
+ }
+
+ if (!priv->agent) {
+ qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("QEMU guest agent is not configured"));
+ goto cleanup;
+ }
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+
+ qemuDomainObjEnterAgent(driver, vm);
+ ret = qemuAgentQemuAgentCommand(priv->agent, cmd, result);
+ qemuDomainObjExitAgent(driver, vm);
+
+ VIR_DEBUG ("qemu-agent-command ret: '%d' domain: '%s' string: %s",
+ ret, vm->def->name, *result);
+
+endjob:
+ if (qemuDomainObjEndJob(driver, vm) == 0) {
+ vm = NULL;
+ }
+
+cleanup:
+ if (vm)
+ virDomainObjUnlock(vm);
+ return ret;
+}
+
static virDriver qemuDriver = {
.no = VIR_DRV_QEMU,
.name = QEMU_DRIVER_NAME,
@@ -13323,6 +13395,7 @@ static virDriver qemuDriver = {
.domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
.domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
.domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
+ .qemuDomainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.9.14 */
};
diff -uNrp libvirt-0.9.13.orig/src/qemu_protocol-structs libvirt-0.9.13/src/qemu_protocol-structs
--- libvirt-0.9.13.orig/src/qemu_protocol-structs 2012-03-06 22:59:21.000000000 +0900
+++ libvirt-0.9.13/src/qemu_protocol-structs 2012-07-06 09:18:12.505455079 +0900
@@ -19,7 +19,16 @@ struct qemu_domain_attach_args {
struct qemu_domain_attach_ret {
remote_nonnull_domain dom;
};
+struct qemu_agent_command_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string cmd;
+ u_int flags;
+};
+struct qemu_agent_command_ret {
+ remote_nonnull_string result;
+};
enum qemu_procedure {
QEMU_PROC_MONITOR_COMMAND = 1,
QEMU_PROC_DOMAIN_ATTACH = 2,
+ QEMU_PROC_AGENT_COMMAND = 3,
};
diff -uNrp libvirt-0.9.13.orig/src/remote/qemu_protocol.x libvirt-0.9.13/src/remote/qemu_protocol.x
--- libvirt-0.9.13.orig/src/remote/qemu_protocol.x 2012-03-06 22:59:21.000000000 +0900
+++ libvirt-0.9.13/src/remote/qemu_protocol.x 2012-07-06 09:18:12.506618309 +0900
@@ -47,6 +47,16 @@ struct qemu_domain_attach_ret {
remote_nonnull_domain dom;
};
+struct qemu_agent_command_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string cmd;
+ u_int flags;
+};
+
+struct qemu_agent_command_ret {
+ remote_nonnull_string result;
+};
+
/* Define the program number, protocol version and procedure numbers here. */
const QEMU_PROGRAM = 0x20008087;
const QEMU_PROTOCOL_VERSION = 1;
@@ -61,5 +71,6 @@ enum qemu_procedure {
* are some exceptions to this rule, e.g. domainDestroy. Other APIs MAY
* be marked as high priority. If in doubt, it's safe to choose low. */
QEMU_PROC_MONITOR_COMMAND = 1, /* skipgen skipgen priority:low */
- QEMU_PROC_DOMAIN_ATTACH = 2 /* autogen autogen priority:low */
+ QEMU_PROC_DOMAIN_ATTACH = 2, /* autogen autogen priority:low */
+ QEMU_PROC_AGENT_COMMAND = 3 /* skipgen skipgen priority:low */
};
diff -uNrp libvirt-0.9.13.orig/src/remote/remote_driver.c libvirt-0.9.13/src/remote/remote_driver.c
--- libvirt-0.9.13.orig/src/remote/remote_driver.c 2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/remote/remote_driver.c 2012-07-06 09:18:12.508579685 +0900
@@ -5127,6 +5127,44 @@ make_nonnull_domain_snapshot (remote_non
make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
}
+static int
+remoteQemuDomainQemuAgentCommand (virDomainPtr domain, const char *cmd,
+ char **result, unsigned int flags)
+{
+ int rv = -1;
+ qemu_agent_command_args args;
+ qemu_agent_command_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain(&args.dom, domain);
+ args.cmd = (char *)cmd;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof(ret));
+
+ if (call (domain->conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_AGENT_COMMAND,
+ (xdrproc_t) xdr_qemu_agent_command_args, (char *) &args,
+ (xdrproc_t) xdr_qemu_agent_command_ret, (char *) &ret) == -1)
+ goto done;
+
+ *result = strdup(ret.result);
+ if (*result == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ rv = 0;
+
+cleanup:
+ xdr_free ((xdrproc_t) xdr_qemu_agent_command_ret, (char *) &ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
/*----------------------------------------------------------------------*/
unsigned long remoteVersion(void)
@@ -5303,6 +5341,7 @@ static virDriver remote_driver = {
.domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */
.domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */
.domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */
+ .qemuDomainQemuAgentCommand = remoteQemuDomainQemuAgentCommand, /* 0.9.14 */
};
static virNetworkDriver network_driver = {
diff -uNrp libvirt-0.9.13.orig/tools/virsh.c libvirt-0.9.13/tools/virsh.c
--- libvirt-0.9.13.orig/tools/virsh.c 2012-07-02 10:45:49.000000000 +0900
+++ libvirt-0.9.13/tools/virsh.c 2012-07-06 09:18:12.514579757 +0900
@@ -18138,6 +18138,68 @@ cleanup:
return ret;
}
+/*
+ * "qemu-agent-command" command
+ */
+static const vshCmdInfo info_qemu_agent_command[] = {
+ {"help", N_("Qemu Guest Agent Command")},
+ {"desc", N_("Qemu Guest Agent Command")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_qemu_agent_command[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"cmd", VSH_OT_ARGV, VSH_OFLAG_REQ, N_("command")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ bool ret = false;
+ char *guest_agent_cmd = NULL;
+ char *result = NULL;
+ unsigned int flags = 0;
+ const vshCmdOpt *opt = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool pad = false;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ dom = vshCommandOptDomain(ctl, cmd, NULL);
+ if (dom == NULL)
+ goto cleanup;
+
+ while ((opt = vshCommandOptArgv(cmd, opt))) {
+ if (pad)
+ virBufferAddChar(&buf, ' ');
+ pad = true;
+ virBufferAdd(&buf, opt->data, -1);
+ }
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to collect command"));
+ goto cleanup;
+ }
+ guest_agent_cmd = virBufferContentAndReset(&buf);
+
+ if (virDomainQemuAgentCommand(dom, guest_agent_cmd, &result, flags) < 0)
+ goto cleanup;
+
+ printf("%s\n", result);
+
+ ret = true;
+
+cleanup:
+ VIR_FREE(result);
+ VIR_FREE(guest_agent_cmd);
+ if (dom)
+ virDomainFree(dom);
+
+ return ret;
+}
+
static const vshCmdDef domManagementCmds[] = {
{"attach-device", cmdAttachDevice, opts_attach_device,
info_attach_device, 0},
@@ -18447,6 +18509,8 @@ static const vshCmdDef hostAndHypervisor
{"qemu-attach", cmdQemuAttach, opts_qemu_attach, info_qemu_attach, 0},
{"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command,
info_qemu_monitor_command, 0},
+ {"qemu-agent-command", cmdQemuAgentCommand, opts_qemu_agent_command,
+ info_qemu_agent_command, 0},
{"sysinfo", cmdSysinfo, NULL, info_sysinfo, 0},
{"uri", cmdURI, NULL, info_uri, 0},
{"version", cmdVersion, opts_version, info_version, 0},
--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list