[libvirt] [PATCH 3/5] add virDomainQemuAgentCommand() to qemu driver and remote driver

Eric Blake eblake at redhat.com
Thu Aug 9 16:57:03 UTC 2012


On 08/07/2012 06:05 PM, MATSUDA, Daiki wrote:
>     Add virDomainQemuAgentCommand() to qemu driver and remote driver
>     to support qemuAgentCommand().
> 
>  daemon/remote.c                |   35 ++++++++++++++++++++
>  include/libvirt/libvirt-qemu.h |    3 +
>  src/driver.h                   |    6 +++
>  src/libvirt-qemu.c             |   58 +++++++++++++++++++++++++++++++++
>  src/libvirt_qemu.syms          |    5 ++
>  src/qemu/qemu_driver.c         |   71 +++++++++++++++++++++++++++++++++++++++++
>  src/qemu_protocol-structs      |   10 +++++
>  src/remote/qemu_protocol.x     |   14 +++++++-
>  src/remote/remote_driver.c     |   41 +++++++++++++++++++++++
>  9 files changed, 242 insertions(+), 1 deletion(-)

You are mixing the addition of new API (include/, src/driver.h,
src/libvirt-qemu.{c,syms}) with two implementations of two drivers
(daemon and src/remote for the RPC, and src/qemu for the qemu
implementation).  If this were an API in libvirt.h, I'd split this to
three patches, but since it is for libvirt-qemu.h, I'm 50-50 whether the
split makes sense.

Compilation failure; you need to rebase to latest libvirt.git:

  CC     libvirt_driver_qemu_impl_la-qemu_driver.lo
qemu/qemu_driver.c: In function 'qemuDomainQemuAgentCommand':
qemu/qemu_driver.c:13228:9: error: implicit declaration of function
'qemuReportError' [-Werror=implicit-function-declaration]
qemu/qemu_driver.c:13228:9: error: nested extern declaration of
'qemuReportError' [-Werror=nested-externs]

> 
> diff --git a/daemon/remote.c b/daemon/remote.c
> index 832307e..4fd5c9b 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -3948,6 +3948,41 @@ 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)

Indentation is off.

This function looks pretty simple; any reason we can't autogenerate it
from the .x file?

> @@ -1048,6 +1053,7 @@ struct _virDriver {
>      virDrvDomainGetDiskErrors           domainGetDiskErrors;
>      virDrvDomainSetMetadata             domainSetMetadata;
>      virDrvDomainGetMetadata             domainGetMetadata;
> +    virDrvDomainQemuAgentCommand        qemuDomainQemuAgentCommand;

I'd group this line next to the other virDomainQemu callback.

> +++ b/src/libvirt-qemu.c
> @@ -185,3 +185,61 @@ error:
>      virDispatchError(conn);
>      return NULL;
>  }
> +
> +/**
> + * virDomainQemuAgentCommand:
> + * @domain: a domain object
> + * @cmd: the guest agent command string
> + * @result: a string returned by @cmd
> + * @timeout: timeout seconds
> + * @flags: execution flags
> + *
> + * Execution Guest Agent Command

Execute an arbitrary Guest Agent command.

> + *
> + * Issue @cmd to the guest agent running in @domain.
> + * If @result is NULL, then don't wait for a result (and @timeout
> + * must be 0).  Otherwise, wait for @timeout seconds for a
> + * successful result to be populated into *@result, with
> + * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK (-1) meaning to block
> + * forever waiting for a result.
> + *
> + * Returns 0 if succeeded, -1 in failing.

s/if succeeded/on success/; s/in failing/on failure/

> + */
> +int
> +virDomainQemuAgentCommand(virDomainPtr domain,
> +                          const char *cmd,
> +                          char **result,
> +                          int timeout,
> +                          unsigned int flags)
> +{
> +    virConnectPtr conn;

> +    conn = domain->conn;
> +
> +    virCheckNonNullArgGoto(result, error);

Wrong - we allow a NULL result argument, to issue a command with no
expected response.

> @@ -13369,6 +13439,7 @@ static virDriver qemuDriver = {
>      .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
>      .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
>      .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
> +    .qemuDomainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */

Again, sticking this next to the other qemuDomainQemu callback would be
nicer.

> +++ b/src/remote/qemu_protocol.x
> @@ -47,6 +47,17 @@ struct qemu_domain_attach_ret {
>      remote_nonnull_domain dom;
>  };
> 
> +struct qemu_agent_command_args {
> +    remote_nonnull_domain dom;
> +    remote_nonnull_string cmd;
> +    int timeout;
> +    unsigned int flags;

Missing a field to pass to the other end of the connection whether the
result pointer was given as NULL.

> +};
> +
> +struct qemu_agent_command_ret {
> +    remote_nonnull_string result;

If the result pointer was NULL, then there is no result to return; I
think this has to be remote_string.

> +};
> +
>  /* Define the program number, protocol version and procedure numbers here. */
>  const QEMU_PROGRAM = 0x20008087;
>  const QEMU_PROTOCOL_VERSION = 1;
> @@ -61,5 +72,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 */

Again, can you use autogen instead of skipgen?

> +++ b/src/remote/remote_driver.c
> @@ -5191,6 +5191,46 @@ make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virD
>      make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
>  }
> 
> +static int
> +remoteQemuDomainQemuAgentCommand (virDomainPtr domain, const char *cmd,
> +                                  char **result, int timeout,
> +                                  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.timeout = timeout;
> +    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);

You need to account for the case when result is NULL (maybe you can't
autogen after all, if the generator can't handle an optionally NULL
argument).

-- 
Eric Blake   eblake at redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120809/6e72a03a/attachment-0001.sig>


More information about the libvir-list mailing list