acda74
From ec03aa23ac417797f9b53d51b6f999f5e966f9d7 Mon Sep 17 00:00:00 2001
acda74
Message-Id: <ec03aa23ac417797f9b53d51b6f999f5e966f9d7@dist-git>
acda74
From: Michal Privoznik <mprivozn@redhat.com>
acda74
Date: Mon, 16 Jan 2023 12:46:09 +0100
acda74
Subject: [PATCH] qemu: Provide virDomainGetCPUStats() implementation for
acda74
 session connection
acda74
acda74
We have virDomainGetCPUStats() API which offers querying
acda74
statistics on host CPU usage by given guest. And it works in two
acda74
modes: getting overall stats (@start_cpu == -1, @ncpus == 1) or
acda74
getting per host CPU usage.
acda74
acda74
For the QEMU driver it is implemented by looking into values
acda74
stored in corresponding cpuacct CGroup controller. Well, this
acda74
works for system instances, where libvirt has permissions to
acda74
create CGroups and place QEMU process into them. But it does not
acda74
fly for session connection, where no CGroups are set up.
acda74
acda74
Fortunately, we can do something similar to v8.8.0-rc1~95 and use
acda74
virProcessGetStatInfo() to fill the overall stats. Unfortunately,
acda74
I haven't found any source of per host CPU usage, so we just
acda74
continue throwing an error in that case.
acda74
acda74
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
acda74
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
acda74
(cherry picked from commit 8865c42771600a40eddf40663f73b458423059a4)
acda74
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2148266
acda74
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
acda74
---
acda74
 src/qemu/qemu_driver.c | 52 ++++++++++++++++++++++++++++++++++++++++--
acda74
 1 file changed, 50 insertions(+), 2 deletions(-)
acda74
acda74
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
acda74
index c576c601ad..0603af6a35 100644
acda74
--- a/src/qemu/qemu_driver.c
acda74
+++ b/src/qemu/qemu_driver.c
acda74
@@ -16009,6 +16009,50 @@ qemuDomainGetMetadata(virDomainPtr dom,
acda74
     return ret;
acda74
 }
acda74
 
acda74
+#define QEMU_CPU_STATS_PROC_TOTAL 3
acda74
+
acda74
+static int
acda74
+qemuDomainGetCPUStatsProc(virDomainObj *vm,
acda74
+                          virTypedParameterPtr params,
acda74
+                          unsigned int nparams)
acda74
+{
acda74
+    unsigned long long cpuTime = 0;
acda74
+    unsigned long long userTime = 0;
acda74
+    unsigned long long sysTime = 0;
acda74
+
acda74
+    if (nparams == 0) {
acda74
+        /* return supported number of params */
acda74
+        return QEMU_CPU_STATS_PROC_TOTAL;
acda74
+    }
acda74
+
acda74
+    if (virProcessGetStatInfo(&cpuTime, &userTime, &sysTime,
acda74
+                              NULL, NULL, vm->pid, 0) < 0) {
acda74
+        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
acda74
+                       _("cannot read cputime for domain"));
acda74
+        return -1;
acda74
+    }
acda74
+
acda74
+    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
acda74
+                                VIR_TYPED_PARAM_ULLONG, cpuTime) < 0)
acda74
+        return -1;
acda74
+
acda74
+    if (nparams > 1 &&
acda74
+        virTypedParameterAssign(&params[1], VIR_DOMAIN_CPU_STATS_USERTIME,
acda74
+                                VIR_TYPED_PARAM_ULLONG, userTime) < 0)
acda74
+        return -1;
acda74
+
acda74
+    if (nparams > 2 &&
acda74
+        virTypedParameterAssign(&params[2], VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
acda74
+                                VIR_TYPED_PARAM_ULLONG, sysTime) < 0)
acda74
+        return -1;
acda74
+
acda74
+    if (nparams > 3)
acda74
+        nparams = 3;
acda74
+
acda74
+    return nparams;
acda74
+}
acda74
+
acda74
+#undef QEMU_CPU_STATS_PROC_TOTAL
acda74
 
acda74
 static int
acda74
 qemuDomainGetCPUStats(virDomainPtr domain,
acda74
@@ -16037,8 +16081,12 @@ qemuDomainGetCPUStats(virDomainPtr domain,
acda74
         goto cleanup;
acda74
 
acda74
     if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) {
acda74
-        virReportError(VIR_ERR_OPERATION_INVALID,
acda74
-                       "%s", _("cgroup CPUACCT controller is not mounted"));
acda74
+        if (start_cpu == -1) {
acda74
+            ret = qemuDomainGetCPUStatsProc(vm, params, nparams);
acda74
+        } else {
acda74
+            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
acda74
+                           _("cgroup CPUACCT controller is not mounted"));
acda74
+        }
acda74
         goto cleanup;
acda74
     }
acda74
 
acda74
-- 
acda74
2.39.1
acda74