[PATCH] qemu_agent: support guest-info command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, libvirt qemu agent supports some QEMU Guest Agent's commands
or use them. But they are not adapted to communication test to the
Domain OS.

So, QEMU Guest Agent provide 'guest-info' command to display its version
and their commands. And I wrote the codes for supporting it.

virsh # guest-agent-info RHEL62_32
Version: 1.1.0
Commands:
        guest-network-get-interfaces
        guest-suspend-hybrid
        guest-suspend-ram
        guest-suspend-disk
        guest-fsfreeze-thaw
        guest-fsfreeze-freeze
        guest-fsfreeze-status
        guest-file-flush
        guest-file-seek
        guest-file-write
        guest-file-read
        guest-file-close
        guest-file-open
        guest-shutdown
        guest-info
        guest-ping
        guest-sync
        guest-sync-delimited

I am sorry that attached patch is against libvirt-0.9.13-rc1, because my
network environment can not access via git and header code is not built
with the problem gnulib...

Regards
MATSUDA Daiki

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-06-26 11:34:02.058455043 +0900
@@ -3923,6 +3923,46 @@ cleanup:
     return rv;
 }
 
+static int remoteDispatchDomainGuestAgentInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                              virNetServerClientPtr client ATTRIBUTE_UNUSED,
+                                              virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                              virNetMessageErrorPtr rerr,
+                                              remote_domain_guest_agent_info_args *args,
+                                              remote_domain_guest_agent_info_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;
+
+    ret->buffer.buffer_len = REMOTE_DOMAIN_GA_INFO_BUFFER_MAX;
+    if (VIR_ALLOC_N (ret->buffer.buffer_val, REMOTE_DOMAIN_GA_INFO_BUFFER_MAX) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (virDomainGuestAgentInfo(dom, &(ret->buffer.buffer_val)) < 0) {
+        virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("Guest Agent Error"));
+        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/daemon/remote_dispatch.h libvirt-0.9.13/daemon/remote_dispatch.h
--- libvirt-0.9.13.orig/daemon/remote_dispatch.h	2012-06-25 19:48:08.000000000 +0900
+++ libvirt-0.9.13/daemon/remote_dispatch.h	2012-06-26 11:36:45.846454615 +0900
@@ -12889,6 +12889,28 @@ static int remoteDispatchSupportsFeature
 
 
 
+static int remoteDispatchDomainGuestAgentInfo(
+    virNetServerPtr server,
+    virNetServerClientPtr client,
+    virNetMessagePtr msg,
+    virNetMessageErrorPtr rerr,
+    remote_domain_guest_agent_info_args *args,
+    remote_domain_guest_agent_info_ret *ret);
+static int remoteDispatchDomainGuestAgentInfoHelper(
+    virNetServerPtr server,
+    virNetServerClientPtr client,
+    virNetMessagePtr msg,
+    virNetMessageErrorPtr rerr,
+    void *args,
+    void *ret)
+{
+  VIR_DEBUG("server=%p client=%p msg=%p rerr=%p args=%p ret=%p", server, client, msg, rerr, args, ret);
+  return remoteDispatchDomainGuestAgentInfo(server, client, msg, rerr, args, ret);
+}
+/* remoteDispatchDomainGuestAgentInfo body has to be implemented manually */
+
+
+
 virNetServerProgramProc remoteProcs[] = {
 { /* Unused 0 */
    NULL,
@@ -15374,5 +15396,14 @@ virNetServerProgramProc remoteProcs[] = 
    true,
    1
 },
+{ /* Method DomainGuestAgentInfo => 276 */
+   remoteDispatchDomainGuestAgentInfoHelper,
+   sizeof(remote_domain_guest_agent_info_args),
+   (xdrproc_t)xdr_remote_guest_agent_info_args,
+   sizeof(remote_domain_guest_agent_info_ret),
+   (xdrproc_t)remote_domain_guest_agent_info_ret,
+   true,
+   0
+},
 };
 size_t remoteNProcs = ARRAY_CARDINALITY(remoteProcs);
diff -uNrp libvirt-0.9.13.orig/include/libvirt/libvirt.h.in libvirt-0.9.13/include/libvirt/libvirt.h.in
--- libvirt-0.9.13.orig/include/libvirt/libvirt.h.in	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/include/libvirt/libvirt.h.in	2012-06-26 11:38:08.694455103 +0900
@@ -4128,6 +4128,11 @@ typedef struct _virTypedParameter virMem
  */
 typedef virMemoryParameter *virMemoryParameterPtr;
 
+/**
+ * Guest Agent Code:
+ */
+int virDomainGuestAgentInfo(virDomainPtr domain, char **buffer);
+
 #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-06-26 11:38:41.150580134 +0900
@@ -425,6 +425,7 @@ skip_impl = (
     'virDomainGetInterfaceParameters',
     'virDomainGetCPUStats',
     'virDomainGetDiskErrors',
+    'virDomainGuestAgentInfo',
 )
 
 qemu_skip_impl = (
diff -uNrp libvirt-0.9.13.orig/python/libvirt-override-api.xml libvirt-0.9.13/python/libvirt-override-api.xml
--- libvirt-0.9.13.orig/python/libvirt-override-api.xml	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/python/libvirt-override-api.xml	2012-06-26 11:39:18.182492585 +0900
@@ -487,5 +487,10 @@
       <arg name='domain' type='virDomainPtr' info='a domain object'/>
       <arg name='flags' type='unsigned int' info='unused, always pass 0'/>
     </function>
+    <function name='virDomainGuestAgentInfo' file='python'>
+      <info>guestagent-info</info>
+      <arg name='domain' type='virDomainPtr' info='pointer to the domain'/>
+      <return type='int' info='more than 0 if successed, negative on failure.'/>
+    </function>
   </symbols>
 </api>
diff -uNrp libvirt-0.9.13.orig/python/libvirt-override.c libvirt-0.9.13/python/libvirt-override.c
--- libvirt-0.9.13.orig/python/libvirt-override.c	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/python/libvirt-override.c	2012-06-26 11:40:17.312579756 +0900
@@ -5758,6 +5758,36 @@ cleanup:
     return py_retval;
 }
 
+static PyObject *
+libvirt_virDomainGuestAgentInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
+{
+    PyObject *py_retval;
+    int c_retval;
+    char *info;
+    virDomainPtr domain;
+    PyObject *pyobj_domain;
+
+    if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainGuestAgentInfo", &pyobj_domain, &info)) {
+#if DEBUG_ERROR
+        printf("%s failed to parse tuple\n", __FUNCTION__);
+#endif
+        return(NULL);
+    }
+    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    c_retval = virDomainGuestAgentInfo(domain, &info);
+    LIBVIRT_END_ALLOW_THREADS;
+    if (c_retval < 0)
+        return VIR_PY_NONE;
+
+    py_retval = PyList_New(1);
+    PyList_SetItem(py_retval, 0, libvirt_constcharPtrWrap(info));
+
+    if (info) free(info);
+    return(py_retval);
+}
+
 /************************************************************************
  *									*
  *			The registration stuff				*
@@ -5865,6 +5895,7 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virDomainBlockPeek", libvirt_virDomainBlockPeek, METH_VARARGS, NULL},
     {(char *) "virDomainMemoryPeek", libvirt_virDomainMemoryPeek, METH_VARARGS, NULL},
     {(char *) "virDomainGetDiskErrors", libvirt_virDomainGetDiskErrors, METH_VARARGS, NULL},
+    {(char *) "virDomainGuestAgentInfo", libvirt_virDomainGuestAgentInfo, 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-06-26 11:42:25.618580083 +0900
@@ -860,6 +860,10 @@ typedef char *
                                const char *uri,
                                unsigned int flags);
 
+typedef int
+    (*virDrvDomainGuestAgentInfo)(virDomainPtr dom,
+                                  char **buffer);
+
 /**
  * _virDriver:
  *
@@ -1041,6 +1045,7 @@ struct _virDriver {
     virDrvDomainGetDiskErrors           domainGetDiskErrors;
     virDrvDomainSetMetadata             domainSetMetadata;
     virDrvDomainGetMetadata             domainGetMetadata;
+    virDrvDomainGuestAgentInfo          domainGuestAgentInfo;
 };
 
 typedef int
diff -uNrp libvirt-0.9.13.orig/src/libvirt.c libvirt-0.9.13/src/libvirt.c
--- libvirt-0.9.13.orig/src/libvirt.c	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/libvirt.c	2012-06-26 11:42:58.093454455 +0900
@@ -18973,3 +18973,38 @@ error:
     virDispatchError(dom->conn);
     return -1;
 }
+
+/**
+ * virDomainGuestAgentInfo:
+ * @domain: a domain object
+ * @buffer: returning Guest Agent information
+ *
+ * Provide a list of Guest Agent's support command.
+ * Returns 0 if succeeded, -1 in failing.
+ */
+int virDomainGuestAgentInfo(virDomainPtr domain, char **buffer)
+{
+    virConnectPtr conn;
+    int ret = -1;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return ret;
+    }
+
+    conn = domain->conn;
+
+    if (conn->driver->domainGuestAgentInfo) {
+        ret = conn->driver->domainGuestAgentInfo(domain, buffer);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibDomainError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    /* Copy to connection error object for back compatability */
+    virDispatchError(domain->conn);
+    return ret;
+}
diff -uNrp libvirt-0.9.13.orig/src/libvirt_public.syms libvirt-0.9.13/src/libvirt_public.syms
--- libvirt-0.9.13.orig/src/libvirt_public.syms	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/libvirt_public.syms	2012-06-26 11:43:29.939455045 +0900
@@ -542,6 +542,7 @@ LIBVIRT_0.9.13 {
         virDomainSnapshotIsCurrent;
         virDomainSnapshotListAllChildren;
         virDomainSnapshotRef;
+        virDomainGuestAgentInfo;
 } LIBVIRT_0.9.11;
 
 # .... define new API here using predicted next version number ....
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-06-26 11:44:35.332580082 +0900
@@ -1410,3 +1410,74 @@ qemuAgentSuspend(qemuAgentPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+static int qemuMonitorJSONExtractInfo(virJSONValuePtr reply, char **buffer)
+{
+    virJSONValuePtr data, data2;
+    int ret = -1;
+    int i;
+    char *pin = NULL;
+
+    pin = *buffer;
+
+    if (!(data = virJSONValueObjectGet(reply, "return")) ||
+        data->type != VIR_JSON_TYPE_OBJECT) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("guestagent-info reply was missing return data"));
+        goto cleanup;
+    }
+
+    if (!(data2 = virJSONValueObjectGet(data, "version")) ||
+        data2->type != VIR_JSON_TYPE_STRING) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("guestagent-info reply was not complete data(version)"));
+        goto cleanup;
+    }
+    sprintf(pin, "Version: %s\nCommands:", virJSONValueGetString(data2));
+    pin = strchr(pin, '\0');
+
+    if (!(data2 = virJSONValueObjectGet(data, "supported_commands")) ||
+        data2->type != VIR_JSON_TYPE_ARRAY) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("guestagent-info reply was not complete data(commands)"));
+        goto cleanup;
+    }
+
+    data = data2;
+    for (i = 0; i < virJSONValueArraySize(data); i++) {
+        bool value;
+        data2 = virJSONValueArrayGet(data, i);
+        if (!virJSONValueGetBoolean(virJSONValueObjectGet(data2, "enabled"), &value) && value) {
+            sprintf(pin, "\n\t%s", virJSONValueGetString(virJSONValueObjectGet(data2, "name")));
+            pin = strchr(pin, '\0');
+        }
+    }
+
+    ret = 0;
+
+cleanup:
+    return ret;
+}
+
+int qemuAgentInfo(qemuAgentPtr mon, char **buffer)
+{
+    int ret = -1;
+    virJSONValuePtr cmd;
+    virJSONValuePtr reply = NULL;
+
+    cmd = qemuAgentMakeCommand("guest-info", NULL);
+    if (!cmd)
+        return ret;
+
+    ret = qemuAgentCommand(mon, cmd, &reply);
+
+    if (ret == 0)
+        ret = qemuAgentCheckError(cmd, reply);
+
+    if (ret == 0)
+        ret = qemuMonitorJSONExtractInfo(reply, buffer);
+
+    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-06-26 11:44:57.044580088 +0900
@@ -80,4 +80,6 @@ int qemuAgentFSThaw(qemuAgentPtr mon);
 
 int qemuAgentSuspend(qemuAgentPtr mon,
                      unsigned int target);
+
+int qemuAgentInfo(qemuAgentPtr mon, char **buffer);
 #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-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/qemu/qemu_driver.c	2012-06-26 11:46:19.600454553 +0900
@@ -13157,6 +13157,59 @@ qemuListAllDomains(virConnectPtr conn,
     return ret;
 }
 
+static int qemuDomainGuestAgentInfo(virDomainPtr dom, char **buffer)
+{
+    int ret = -1;
+
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    qemuDomainObjPrivatePtr priv;
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->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->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;
+    }
+
+    qemuDomainObjEnterAgent(driver, vm);
+    ret = qemuAgentInfo(priv->agent, buffer);
+    qemuDomainObjExitAgent(driver, vm);
+
+    VIR_DEBUG ("guestagent-info ret: '%d' domain: '%s' string: %s", ret, vm->def->name, *buffer);
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
 static virDriver qemuDriver = {
     .no = VIR_DRV_QEMU,
     .name = QEMU_DRIVER_NAME,
@@ -13322,6 +13375,7 @@ static virDriver qemuDriver = {
     .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
     .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
     .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
+    .domainGuestAgentInfo = qemuDomainGuestAgentInfo, /* 0.9.13 */
 };
 
 
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-06-26 11:47:41.600579693 +0900
@@ -5127,6 +5127,34 @@ make_nonnull_domain_snapshot (remote_non
     make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
 }
 
+static int
+remoteDomainGuestAgentInfo(virDomainPtr domain, char **buffer)
+{
+    int rv = -1;
+    struct private_data *priv = domain->conn->privateData;
+    remote_domain_guest_agent_info_args args;
+    remote_domain_guest_agent_info_ret ret;
+
+    remoteDriverLock(priv);
+
+    make_nonnull_domain(&args.dom, domain);
+
+    memset (&ret, 0, sizeof ret);
+
+    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GUEST_AGENT_INFO,
+              (xdrproc_t) xdr_remote_domain_guest_agent_info_args, (char *) &args,
+              (xdrproc_t) xdr_remote_domain_guest_agent_info_ret, (char *) &ret) == -1)
+        goto done;
+    *buffer = strdup(ret.buffer.buffer_val);
+    rv = 0;
+
+    VIR_FREE(ret.buffer.buffer_val);
+
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
 /*----------------------------------------------------------------------*/
 
 unsigned long remoteVersion(void)
@@ -5303,6 +5331,7 @@ static virDriver remote_driver = {
     .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */
     .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */
     .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */
+    .domainGuestAgentInfo = remoteDomainGuestAgentInfo, /* 0.9.13 */
 };
 
 static virNetworkDriver network_driver = {
diff -uNrp libvirt-0.9.13.orig/src/remote/remote_protocol.x libvirt-0.9.13/src/remote/remote_protocol.x
--- libvirt-0.9.13.orig/src/remote/remote_protocol.x	2012-06-25 16:06:18.000000000 +0900
+++ libvirt-0.9.13/src/remote/remote_protocol.x	2012-06-26 11:50:00.761455124 +0900
@@ -2513,6 +2513,16 @@ struct remote_connect_list_all_domains_r
     unsigned int ret;
 };
 
+const REMOTE_DOMAIN_GA_INFO_BUFFER_MAX = 1024;
+
+struct remote_domain_guest_agent_info_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_guest_agent_info_ret {
+    opaque buffer<REMOTE_DOMAIN_GA_INFO_BUFFER_MAX>;
+};
+
 
 /*----- Protocol. -----*/
 
@@ -2838,7 +2848,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_SNAPSHOT_HAS_METADATA = 272, /* autogen autogen */
     REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS = 273, /* skipgen skipgen priority:high */
     REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274, /* skipgen skipgen priority:high */
-    REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275 /* skipgen skipgen priority:high */
+    REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, /* skipgen skipgen priority:high */
+    REMOTE_PROC_DOMAIN_GUEST_AGENT_INFO = 276 /* skipgen skipgen */
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
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-06-25 19:07:41.000000000 +0900
+++ libvirt-0.9.13/tools/virsh.c	2012-06-26 11:52:42.751454461 +0900
@@ -160,6 +160,7 @@ typedef enum {
 #define VSH_CMD_GRP_SNAPSHOT         "Snapshot"
 #define VSH_CMD_GRP_HOST_AND_HV      "Host and Hypervisor"
 #define VSH_CMD_GRP_VIRSH            "Virsh itself"
+#define VSH_CMD_GRP_GUESTAGENT       "QEMU Guest Agent"
 
 /*
  * Command Option Flags
@@ -17947,6 +17948,44 @@ cleanup:
     return ret;
 }
 
+/*
+ * "guest-agent-info" command
+ */
+static const vshCmdInfo info_guest_agent_info[] = {
+    {"help", N_("Guest Agent Info")},
+    {"desc", N_("Guest Agent Info")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_guest_agent_info[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdGuestAgentInfo(vshControl *ctl, const vshCmd *cmd)
+{
+    int ret = -1;
+    virDomainPtr dom;
+    char *info = NULL;
+
+    if (!vshConnectionUsability(ctl, ctl->conn))
+        return false;
+
+    if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYNAME|VSH_BYUUID)))
+        return false;
+
+    if ((ret = virDomainGuestAgentInfo(dom, &info)) < 0 || !info) {
+        vshError(ctl, "%s", _("Failed to set guest-agent-info"));
+    } else {
+        vshPrint(ctl, "%s\n", info);
+    }
+
+    if (info) VIR_FREE(info);
+    virDomainFree(dom);
+    return ret < 0 ? false : true;
+}
+
 static const vshCmdDef domManagementCmds[] = {
     {"attach-device", cmdAttachDevice, opts_attach_device,
      info_attach_device, 0},
@@ -18261,6 +18300,11 @@ static const vshCmdDef hostAndHypervisor
     {NULL, NULL, NULL, NULL, 0}
 };
 
+static const vshCmdDef guestagentCmds[] = {
+    {"guest-agent-info", cmdGuestAgentInfo, opts_guest_agent_info, info_guest_agent_info, 0},
+    {NULL, NULL, NULL, NULL, 0}
+};
+
 static const vshCmdGrp cmdGroups[] = {
     {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
     {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
@@ -18273,6 +18317,7 @@ static const vshCmdGrp cmdGroups[] = {
     {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
     {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
     {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
+    {VSH_CMD_GRP_GUESTAGENT, "guestagent", guestagentCmds},
     {VSH_CMD_GRP_VIRSH, "virsh", virshCmds},
     {NULL, NULL, NULL}
 };
--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]