[libvirt] [PATCHv3 3/5] remote: Implement bulk domain stats APIs in the remote driver

Peter Krempa pkrempa at redhat.com
Wed Aug 27 18:25:41 UTC 2014


Implement the remote driver support for shuffling the domain stats
around.
---
 daemon/remote.c              | 86 ++++++++++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c   | 84 +++++++++++++++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x | 25 ++++++++++++-
 src/remote_protocol-structs  | 22 ++++++++++++
 4 files changed, 216 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 9251576..c752479 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -6383,6 +6383,92 @@ remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED,
 }


+static int
+remoteDispatchConnectGetAllDomainStats(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                       virNetServerClientPtr client,
+                                       virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                       virNetMessageErrorPtr rerr,
+                                       remote_connect_get_all_domain_stats_args *args,
+                                       remote_connect_get_all_domain_stats_ret *ret)
+{
+    int rv = -1;
+    size_t i;
+    struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
+    virDomainStatsRecordPtr *retStats = NULL;
+    int nrecords = 0;
+    virDomainPtr *doms = NULL;
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
+
+    if (args->doms.doms_len) {
+        if (VIR_ALLOC_N(doms, args->doms.doms_len + 1) < 0)
+            goto cleanup;
+
+        for (i = 0; i < args->doms.doms_len; i++) {
+            if (!(doms[i] = get_nonnull_domain(priv->conn, args->doms.doms_val[i])))
+                goto cleanup;
+        }
+
+        if ((nrecords = virDomainListGetStats(doms,
+                                              args->stats,
+                                              &retStats,
+                                              args->flags)) < 0)
+            goto cleanup;
+    } else {
+        if ((nrecords = virConnectGetAllDomainStats(priv->conn,
+                                                    args->stats,
+                                                    &retStats,
+                                                    args->flags)) < 0)
+            goto cleanup;
+    }
+
+    if (nrecords > REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Number of domain stats records is %d, "
+                         "which exceeds max limit: %d"),
+                       nrecords, REMOTE_DOMAIN_LIST_MAX);
+        goto cleanup;
+    }
+
+    if (nrecords) {
+        ret->retStats.retStats_len = nrecords;
+
+        if (VIR_ALLOC_N(ret->retStats.retStats_val, nrecords) < 0)
+            goto cleanup;
+
+        for (i = 0; i < nrecords; i++) {
+            remote_domain_stats_record *dst = ret->retStats.retStats_val + i;
+
+            make_nonnull_domain(&dst->dom, retStats[i]->dom);
+
+            if (remoteSerializeTypedParameters(retStats[i]->params,
+                                               retStats[i]->nparams,
+                                               &dst->params.params_val,
+                                               &dst->params.params_len,
+                                               VIR_TYPED_PARAM_STRING_OKAY) < 0)
+                goto cleanup;
+        }
+    } else {
+        ret->retStats.retStats_len = 0;
+        ret->retStats.retStats_val = NULL;
+    }
+
+    rv = 0;
+
+ cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+
+    virDomainStatsRecordListFree(retStats);
+    virDomainListFree(doms);
+
+    return rv;
+}
+
+
 /*----- Helpers. -----*/

 /* get_nonnull_domain and get_nonnull_network turn an on-wire
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index e949223..fda27f7 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7717,6 +7717,89 @@ remoteNetworkGetDHCPLeases(virNetworkPtr net,
 }


+static int
+remoteConnectGetAllDomainStats(virConnectPtr conn,
+                               virDomainPtr *doms,
+                               unsigned int ndoms,
+                               unsigned int stats,
+                               virDomainStatsRecordPtr **retStats,
+                               unsigned int flags)
+{
+    struct private_data *priv = conn->networkPrivateData;
+    int rv = -1;
+    size_t i;
+    remote_connect_get_all_domain_stats_args args;
+    remote_connect_get_all_domain_stats_ret ret;
+
+    virDomainStatsRecordPtr *tmpret = NULL;
+
+    if (ndoms) {
+        if (VIR_ALLOC_N(args.doms.doms_val, ndoms) < 0)
+            goto cleanup;
+
+        for (i = 0; i < ndoms; i++)
+            make_nonnull_domain(args.doms.doms_val + i, doms[i]);
+    }
+    args.doms.doms_len = ndoms;
+
+    args.stats = stats;
+    args.flags = flags;
+
+    memset(&ret, 0, sizeof(ret));
+
+    remoteDriverLock(priv);
+    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS,
+             (xdrproc_t)xdr_remote_connect_get_all_domain_stats_args, (char *)&args,
+             (xdrproc_t)xdr_remote_connect_get_all_domain_stats_ret, (char *)&ret) == -1) {
+        remoteDriverUnlock(priv);
+        goto cleanup;
+    }
+    remoteDriverUnlock(priv);
+
+    if (ret.retStats.retStats_len > REMOTE_DOMAIN_LIST_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Number of stats entries is %d, which exceeds max limit: %d"),
+                       ret.retStats.retStats_len, REMOTE_DOMAIN_LIST_MAX);
+        goto cleanup;
+    }
+
+    *retStats = NULL;
+
+    if (VIR_ALLOC_N(tmpret, ret.retStats.retStats_len + 1) < 0)
+        goto cleanup;
+
+    for (i = 0; i < ret.retStats.retStats_len; i++) {
+        virDomainStatsRecordPtr elem;
+        remote_domain_stats_record *rec = ret.retStats.retStats_val + i;
+
+        if (VIR_ALLOC(elem) < 0)
+            goto cleanup;
+
+        if (!(elem->dom = get_nonnull_domain(conn, rec->dom)))
+            goto cleanup;
+
+        if (remoteDeserializeTypedParameters(rec->params.params_val,
+                                             rec->params.params_len,
+                                             REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX,
+                                             &elem->params,
+                                             &elem->nparams))
+            goto cleanup;
+
+        tmpret[i] = elem;
+    }
+
+    *retStats = tmpret;
+    tmpret = NULL;
+    rv = ret.retStats.retStats_len;
+
+ cleanup:
+    virDomainStatsRecordListFree(tmpret);
+    xdr_free((xdrproc_t)xdr_remote_connect_get_all_domain_stats_ret,
+             (char *) &ret);
+
+    return rv;
+}
+
 /* get_nonnull_domain and get_nonnull_network turn an on-wire
  * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
  * These can return NULL if underlying memory allocations fail,
@@ -8056,6 +8139,7 @@ static virDriver remote_driver = {
     .domainSetTime = remoteDomainSetTime, /* 1.2.5 */
     .nodeGetFreePages = remoteNodeGetFreePages, /* 1.2.6 */
     .connectGetDomainCapabilities = remoteConnectGetDomainCapabilities, /* 1.2.7 */
+    .connectGetAllDomainStats = remoteConnectGetAllDomainStats, /* 1.2.8 */
 };

 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 6dc2d29..8fc552f 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -241,6 +241,9 @@ const REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX = 256;
 /* Upper limit on the maximum number of leases in one lease file */
 const REMOTE_NETWORK_DHCP_LEASES_MAX = 65536;

+/* Upper limit on count of parameters returned via bulk stats API */
+const REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX = 4096;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];

@@ -3063,6 +3066,20 @@ struct remote_network_get_dhcp_leases_ret {
     unsigned int ret;
 };

+struct remote_domain_stats_record {
+    remote_nonnull_domain dom;
+    remote_typed_param params<REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX>;
+};
+
+struct remote_connect_get_all_domain_stats_args {
+    remote_nonnull_domain doms<REMOTE_DOMAIN_LIST_MAX>;
+    unsigned int stats;
+    unsigned int flags;
+};
+
+struct remote_connect_get_all_domain_stats_ret {
+    remote_domain_stats_record retStats<REMOTE_DOMAIN_LIST_MAX>;
+};
 /*----- Protocol. -----*/

 /* Define the program number, protocol version and procedure numbers here. */
@@ -5432,6 +5449,12 @@ enum remote_procedure {
      * @generate: none
      * @acl: domain:open_graphics
      */
-    REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343
+    REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343,

+    /**
+     * @generate: none
+     * @acl: connect:search_domains
+     * @aclfilter: domain:read
+     */
+    REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 38bf0b8..899f1cc 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2524,6 +2524,27 @@ struct remote_network_get_dhcp_leases_ret {
         } leases;
         u_int                      ret;
 };
+struct remote_domain_stats_record {
+        remote_nonnull_domain      dom;
+        struct {
+                u_int              params_len;
+                remote_typed_param * params_val;
+        } params;
+};
+struct remote_connect_get_all_domain_stats_args {
+        struct {
+                u_int              doms_len;
+                remote_nonnull_domain * doms_val;
+        } doms;
+        u_int                      stats;
+        u_int                      flags;
+};
+struct remote_connect_get_all_domain_stats_ret {
+        struct {
+                u_int              retStats_len;
+                remote_domain_stats_record * retStats_val;
+        } retStats;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -2868,4 +2889,5 @@ enum remote_procedure {
         REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 341,
         REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342,
         REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343,
+        REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
 };
-- 
2.0.2




More information about the libvir-list mailing list