render / rpms / libvirt

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