[libvirt] [PATCH 3/3] lxc: implement connectGetAllDomainStats

Cédric Bosdonnat cbosdonnat at suse.com
Mon Mar 5 17:21:51 UTC 2018


LXC containers can also provide some statistics. Allow users to fetch
them using the existing API.
---
 src/lxc/lxc_driver.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 203 insertions(+)

diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index a16dbcc96..c357df927 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -80,6 +80,7 @@
 #include "viraccessapichecklxc.h"
 #include "virhostdev.h"
 #include "netdev_bandwidth_conf.h"
+#include "domain_stats.h"
 
 #define VIR_FROM_THIS VIR_FROM_LXC
 
@@ -5483,6 +5484,207 @@ lxcDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
     return ret;
 }
 
+static int
+lxcDomainGetStatsState(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+                       virDomainObjPtr dom,
+                       virDomainStatsRecordPtr record,
+                       int *maxparams)
+{
+    return virDomainStatsGetState(dom, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsCpu(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+                     virDomainObjPtr dom,
+                     virDomainStatsRecordPtr record,
+                     int *maxparams)
+{
+    virLXCDomainObjPrivatePtr priv = dom->privateData;
+    return virCgroupGetStatsCpu(priv->cgroup, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsInterface(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+                           virDomainObjPtr dom,
+                           virDomainStatsRecordPtr record,
+                           int *maxparams)
+{
+    return virDomainStatsGetInterface(dom, record, maxparams);
+}
+
+/* expects a LL, but typed parameter must be ULL */
+#define LXC_ADD_BLOCK_PARAM_LL(record, maxparams, name, value) \
+do { \
+    char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+    snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+             "block.cgroup.%s", name); \
+    if (virTypedParamsAddULLong(&(record)->params, \
+                                &(record)->nparams, \
+                                maxparams, \
+                                param_name, \
+                                value) < 0) \
+        goto cleanup; \
+} while (0)
+
+static int
+lxcDomainGetStatsBlock(virLXCDriverPtr driver,
+                       virDomainObjPtr dom,
+                       virDomainStatsRecordPtr record,
+                       int *maxparams)
+{
+    long long rd_req, rd_bytes, wr_req, wr_bytes;
+
+    int ret = lxcDomainBlockStatsInternal(driver, dom, "",
+                                          &rd_bytes,
+                                          &wr_bytes,
+                                          &rd_req,
+                                          &wr_req);
+
+    LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+                            "rd.reqs", rd_req);
+    LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+                            "rd.bytes", rd_bytes);
+    LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+                            "wr.reqs", wr_req);
+    LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+                            "wr.bytes", wr_bytes);
+
+ cleanup:
+    return ret;
+}
+
+#undef LXC_ADD_BLOCK_PARAM_ULL
+
+typedef int
+(*lxcDomainGetStatsFunc)(virLXCDriverPtr driver,
+                         virDomainObjPtr dom,
+                         virDomainStatsRecordPtr record,
+                         int *maxparams);
+
+struct lxcDomainGetStatsWorker {
+    lxcDomainGetStatsFunc func;
+    unsigned int stats;
+};
+
+static struct lxcDomainGetStatsWorker lxcDomainGetStatsWorkers[] = {
+    { lxcDomainGetStatsState, VIR_DOMAIN_STATS_STATE },
+    { lxcDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL },
+    { lxcDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE },
+    { lxcDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK },
+    { NULL, 0 }
+};
+
+static int
+lxcDomainGetStats(virConnectPtr conn,
+                  virDomainObjPtr dom,
+                  unsigned int stats,
+                  virDomainStatsRecordPtr *record)
+{
+    virLXCDriverPtr driver = conn->privateData;
+    int maxparams = 0;
+    virDomainStatsRecordPtr tmp;
+    size_t i;
+    int ret = -1;
+
+    if (VIR_ALLOC(tmp) < 0)
+        goto cleanup;
+
+    for (i = 0; lxcDomainGetStatsWorkers[i].func; i++) {
+        if (stats & lxcDomainGetStatsWorkers[i].stats) {
+            if (lxcDomainGetStatsWorkers[i].func(driver, dom, tmp, &maxparams) < 0)
+                goto cleanup;
+        }
+    }
+
+    if (!(tmp->dom = virGetDomain(conn, dom->def->name,
+                                  dom->def->uuid, dom->def->id)))
+        goto cleanup;
+
+    *record = tmp;
+    tmp = NULL;
+    ret = 0;
+
+ cleanup:
+    if (tmp) {
+        virTypedParamsFree(tmp->params, tmp->nparams);
+        VIR_FREE(tmp);
+    }
+
+    return ret;
+}
+
+static int
+lxcConnectGetAllDomainStats(virConnectPtr conn,
+                            virDomainPtr *doms,
+                            unsigned int ndoms,
+                            unsigned int stats,
+                            virDomainStatsRecordPtr **retStats,
+                            unsigned int flags)
+{
+    virLXCDriverPtr driver = conn->privateData;
+    virDomainObjPtr *vms = NULL;
+    virDomainObjPtr vm;
+    size_t nvms;
+    virDomainStatsRecordPtr *tmpstats = NULL;
+    int nstats = 0;
+    size_t i;
+    int ret = -1;
+    unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+                                   VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
+                                   VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE);
+
+    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE |
+                  VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT |
+                  VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE, -1);
+
+    if (virConnectGetAllDomainStatsEnsureACL(conn) < 0)
+        return -1;
+
+    /* TODO Check stats support */
+
+    if (ndoms) {
+        if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms,
+                                    &nvms, virConnectGetAllDomainStatsCheckACL,
+                                    lflags, true) < 0)
+            return -1;
+    } else {
+        if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms,
+                                    virConnectGetAllDomainStatsCheckACL,
+                                    lflags) < 0)
+            return -1;
+    }
+
+    if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0)
+        return -1;
+
+    for (i = 0; i < nvms; i++) {
+        virDomainStatsRecordPtr tmp = NULL;
+        vm = vms[i];
+
+        virObjectLock(vm);
+
+        if (lxcDomainGetStats(conn, vm, stats, &tmp) < 0) {
+            virObjectUnlock(vm);
+            goto cleanup;
+        }
+
+        if (tmp)
+            tmpstats[nstats++] = tmp;
+
+        virObjectUnlock(vm);
+    }
+
+    *retStats = tmpstats;
+    tmpstats = NULL;
+
+    ret = nstats;
+
+ cleanup:
+    virDomainStatsRecordListFree(tmpstats);
+    virObjectListFreeCount(vms, nvms);
+
+    return ret;
+}
 
 /* Function Tables */
 static virHypervisorDriver lxcHypervisorDriver = {
@@ -5577,6 +5779,7 @@ static virHypervisorDriver lxcHypervisorDriver = {
     .nodeGetFreePages = lxcNodeGetFreePages, /* 1.2.6 */
     .nodeAllocPages = lxcNodeAllocPages, /* 1.2.9 */
     .domainHasManagedSaveImage = lxcDomainHasManagedSaveImage, /* 1.2.13 */
+    .connectGetAllDomainStats = lxcConnectGetAllDomainStats, /* 4.2.0 */
 };
 
 static virConnectDriver lxcConnectDriver = {
-- 
2.16.1




More information about the libvir-list mailing list