Since this is already in QEMU we can add this stat which might be useful
for people.
Resolves:
https://issues.redhat.com/browse/RHEL-71883
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
docs/manpages/virsh.rst | 3 +++
src/libvirt-domain.c | 3 +++
src/qemu/qemu_agent.c | 59 +++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 6 +++++
src/qemu/qemu_driver.c | 32 ++++++++++++++++++++++
tests/qemuagenttest.c | 53 ++++++++++++++++++++++++++++++++++++
6 files changed, 156 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 06c2802b3f9f..60b556cb0cd0 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2408,6 +2408,9 @@ When selecting the *--state* group the following fields are
returned:
for bank <index> in cache monitor <num>
* ``cpu.cache.monitor.<num>.bank.<index>.bytes`` - the number of bytes
of last level cache that the domain is using on cache bank <index>
+* ``cpu.load.1m`` - average load in guest for last 1 minute
+* ``cpu.load.5m`` - average load in guest for last 5 minutes
+* ``cpu.load.15m`` - average load in guest for last 15 minutes
*--balloon* returns:
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 072cc3225579..35f5e926e52b 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12272,6 +12272,9 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
* last level cache that the
* domain is using on cache
* bank <index>
+ * "cpu.load.1m" - average load in guest for last 1 minute
+ * "cpu.load.5m" - average load in guest for last 5 minutes
+ * "cpu.load.15m" - average load in guest for last 15 minutes
*
* VIR_DOMAIN_STATS_BALLOON:
* Return memory balloon device information.
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 43fca86f10ed..6dbe8c52d738 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2568,3 +2568,62 @@ int qemuAgentGetDisks(qemuAgent *agent,
g_free(*disks);
return -1;
}
+
+
+int
+qemuAgentGetLoadAvg(qemuAgent *agent,
+ double *load1m,
+ double *load5m,
+ double *load15m,
+ bool report_unsupported)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+ virJSONValue *data = NULL;
+ int rc;
+
+ if (load1m)
+ *load1m = 0;
+
+ if (load5m)
+ *load5m = 0;
+
+ if (load15m)
+ *load15m = 0;
+
+ if (!(cmd = qemuAgentMakeCommand("guest-get-load", NULL)))
+ return -1;
+
+ if ((rc = qemuAgentCommandFull(agent, cmd, &reply, agent->timeout,
+ report_unsupported)) < 0)
+ return rc;
+
+ if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu agent didn't return an array of loads"));
+ return -1;
+ }
+
+ if (load1m &&
+ virJSONValueObjectGetNumberDouble(data, "load1m", load1m) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'load1m' missing in reply of
guest-get-load"));
+ return -1;
+ }
+
+ if (load5m &&
+ virJSONValueObjectGetNumberDouble(data, "load5m", load5m) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'load5m' missing in reply of
guest-get-load"));
+ return -1;
+ }
+
+ if (load15m &&
+ virJSONValueObjectGetNumberDouble(data, "load15m", load15m) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'load15m' missing in reply of
guest-get-load"));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index f98586e8f8ab..cd17a98d3924 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -195,3 +195,9 @@ int qemuAgentSSHRemoveAuthorizedKeys(qemuAgent *agent,
int qemuAgentGetDisks(qemuAgent *mon,
qemuAgentDiskInfo ***disks,
bool report_unsupported);
+
+int qemuAgentGetLoadAvg(qemuAgent *agent,
+ double *load1m,
+ double *load5m,
+ double *load15m,
+ bool report_unsupported);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 80c918312b8f..d9279b3a5804 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16937,6 +16937,36 @@ qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom,
return;
}
+
+static void
+qemuDomainGetStatsCpuLoadAvg(virDomainObj *dom,
+ virTypedParamList *params,
+ unsigned int privflags)
+{
+ qemuAgent *agent = NULL;
+ double load1m = 0;
+ double load5m = 0;
+ double load15m = 0;
+ int rc = 0;
+
+ if (!HAVE_JOB(privflags) ||
+ !virDomainObjIsActive(dom) ||
+ !qemuDomainAgentAvailable(dom, false))
+ return;
+
+ agent = qemuDomainObjEnterAgent(dom);
+ rc = qemuAgentGetLoadAvg(agent, &load1m, &load5m, &load15m, false);
+ qemuDomainObjExitAgent(dom, agent);
+
+ if (rc < 0)
+ return;
+
+ virTypedParamListAddDouble(params, load1m, "cpu.load.1m");
+ virTypedParamListAddDouble(params, load5m, "cpu.load.5m");
+ virTypedParamListAddDouble(params, load15m, "cpu.load.15m");
+}
+
+
static void
qemuDomainGetStatsCpu(virQEMUDriver *driver,
virDomainObj *dom,
@@ -16954,6 +16984,8 @@ qemuDomainGetStatsCpu(virQEMUDriver *driver,
qemuDomainGetStatsCpuCache(driver, dom, params);
qemuDomainGetStatsCpuHaltPollTime(dom, params, privflags);
+
+ qemuDomainGetStatsCpuLoadAvg(dom, params, privflags);
}
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index 328788024197..566571cf1107 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -1356,6 +1356,58 @@ testQemuAgentTimezone(const void *data)
virTypedParamsFree(params, nparams);
return ret;
}
+
+
+static const char testQemuAgentGetLoadAvgResponse[] =
+ "{"
+ " \"return\": {"
+ " \"load15m\": 0.03564453125,"
+ " \"load5m\": 0.064453125,"
+ " \"load1m\": 0.00390625"
+ " }"
+ "}";
+
+static int
+testQemuAgentGetLoadAvg(const void *data)
+{
+ virDomainXMLOption *xmlopt = (virDomainXMLOption *)data;
+ g_autoptr(qemuMonitorTest) test = qemuMonitorTestNewAgent(xmlopt);
+ double load1m = 0;
+ double load5m = 0;
+ double load15m = 0;
+
+ if (!test)
+ return -1;
+
+ if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+ return -1;
+
+ if (qemuMonitorTestAddItem(test, "guest-get-load",
+ testQemuAgentGetLoadAvgResponse) < 0)
+ return -1;
+
+ if (qemuAgentGetLoadAvg(qemuMonitorTestGetAgent(test),
+ &load1m, &load5m, &load15m, true) < 0)
+ return -1;
+
+#define VALIDATE_LOAD(value_, expected_) \
+ do { \
+ if (value_ != expected_) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ "Expected " #value_ " '%.11f', got
'%.11f'", \
+ expected_, value_); \
+ return -1; \
+ } \
+ } while (0)
+
+ VALIDATE_LOAD(load1m, 0.00390625);
+ VALIDATE_LOAD(load5m, 0.064453125);
+ VALIDATE_LOAD(load15m, 0.03564453125);
+
+ return 0;
+}
+
+
static int
mymain(void)
{
@@ -1392,6 +1444,7 @@ mymain(void)
DO_TEST(Timezone);
DO_TEST(SSHKeys);
DO_TEST(GetDisks);
+ DO_TEST(GetLoadAvg);
DO_TEST(Timeout); /* Timeout should always be called last */
--
2.48.1