A set of fields for CPU stats could vary on different platforms,
for example, FreeBSD doesn't report 'iowait'.
Make virsh print out only the fields that were actually filled.
---
tools/virsh-host.c | 119 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 72 insertions(+), 47 deletions(-)
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index f4ca7db..fc6c10a 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -34,6 +34,7 @@
#include "internal.h"
#include "virbuffer.h"
#include "viralloc.h"
+#include "virhash.h"
#include "virsh-domain.h"
#include "virxml.h"
#include "virtypedparam.h"
@@ -335,23 +336,16 @@ static const vshCmdOptDef opts_node_cpustats[] = {
static bool
cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
{
- size_t i, j;
+ size_t i, j, k;
bool flag_utilization = false;
bool flag_percent = vshCommandOptBool(cmd, "percent");
int cpuNum = VIR_NODE_CPU_STATS_ALL_CPUS;
virNodeCPUStatsPtr params;
int nparams = 0;
bool ret = false;
- struct cpu_stats {
- unsigned long long user;
- unsigned long long sys;
- unsigned long long idle;
- unsigned long long iowait;
- unsigned long long intr;
- unsigned long long util;
- } cpu_stats[2];
- double user_time, sys_time, idle_time, iowait_time, intr_time, total_time;
- double usage;
+ const char *fields[] = {"user:", "system:", "idle:",
"iowait:", "intr:", NULL};
+ virHashTablePtr cpu_stats[2] = {NULL, NULL};
+ virHashTablePtr diff = NULL;
if (vshCommandOptInt(cmd, "cpu", &cpuNum) < 0) {
vshError(ctl, "%s", _("Invalid value of cpuNum"));
@@ -372,6 +366,10 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
params = vshCalloc(ctl, nparams, sizeof(*params));
for (i = 0; i < 2; i++) {
+ cpu_stats[i] = virHashCreate(0, (virHashDataFree) free);
+ if (cpu_stats[i] == NULL)
+ goto cleanup;
+
if (i > 0)
sleep(1);
@@ -381,20 +379,25 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
}
for (j = 0; j < nparams; j++) {
- unsigned long long value = params[j].value;
+ unsigned long long *value;
+
+ if (VIR_ALLOC(value) < 0)
+ goto cleanup;
+
+ *value = params[j].value;
if (STREQ(params[j].field, VIR_NODE_CPU_STATS_KERNEL)) {
- cpu_stats[i].sys = value;
+ virHashAddEntry(cpu_stats[i], "system:", value);
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_USER)) {
- cpu_stats[i].user = value;
+ virHashAddEntry(cpu_stats[i], "user:", value);
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IDLE)) {
- cpu_stats[i].idle = value;
+ virHashAddEntry(cpu_stats[i], "idle:", value);
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IOWAIT)) {
- cpu_stats[i].iowait = value;
+ virHashAddEntry(cpu_stats[i], "iowait:", value);
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_INTR)) {
- cpu_stats[i].intr = value;
+ virHashAddEntry(cpu_stats[i], "intr:", value);
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_UTILIZATION)) {
- cpu_stats[i].util = value;
+ virHashAddEntry(cpu_stats[i], "usage:", value);
flag_utilization = true;
}
}
@@ -405,46 +408,68 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
if (!flag_percent) {
if (!flag_utilization) {
- vshPrint(ctl, "%-15s %20llu\n", _("user:"),
cpu_stats[0].user);
- vshPrint(ctl, "%-15s %20llu\n", _("system:"),
cpu_stats[0].sys);
- vshPrint(ctl, "%-15s %20llu\n", _("idle:"),
cpu_stats[0].idle);
- vshPrint(ctl, "%-15s %20llu\n", _("iowait:"),
cpu_stats[0].iowait);
- vshPrint(ctl, "%-15s %20llu\n", _("intr:"),
cpu_stats[0].intr);
+ for (k = 0; fields[k] != NULL; k++) {
+ unsigned long long *value = virHashLookup(cpu_stats[0], fields[k]);
+
+ if (value)
+ vshPrint(ctl, "%-15s %20llu\n", _(fields[k]), *value);
+ }
}
} else {
if (flag_utilization) {
- usage = cpu_stats[0].util;
+ double *usage = virHashLookup(cpu_stats[0], "usage:");
- vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage);
- vshPrint(ctl, "%-15s %5.1lf%%\n", _("idle:"), 100 -
usage);
+ vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), *usage);
+ vshPrint(ctl, "%-15s %5.1lf%%\n", _("idle:"), 100 -
*usage);
} else {
- user_time = cpu_stats[1].user - cpu_stats[0].user;
- sys_time = cpu_stats[1].sys - cpu_stats[0].sys;
- idle_time = cpu_stats[1].idle - cpu_stats[0].idle;
- iowait_time = cpu_stats[1].iowait - cpu_stats[0].iowait;
- intr_time = cpu_stats[1].intr - cpu_stats[0].intr;
- total_time = user_time + sys_time + idle_time + iowait_time + intr_time;
-
- usage = (user_time + sys_time) / total_time * 100;
-
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("usage:"), usage);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("user:"), user_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("system:"), sys_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("idle:"), idle_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("iowait:"), iowait_time / total_time * 100);
- vshPrint(ctl, "%-15s %5.1lf%%\n",
- _("intr:"), intr_time / total_time * 100);
+ double total_time = 0;
+ double usage = -1;
+
+ diff = virHashCreate(0, (virHashDataFree) free);
+ if (diff == NULL)
+ goto cleanup;
+
+ for (k = 0; fields[k] != NULL; k++) {
+ double *value_diff;
+ unsigned long long *oldval = virHashLookup(cpu_stats[0], fields[k]);
+ unsigned long long *newval = virHashLookup(cpu_stats[1], fields[k]);
+
+ if (!oldval || !newval)
+ continue;
+
+ if (VIR_ALLOC(value_diff) < 0)
+ goto cleanup;
+
+ *value_diff = *newval - *oldval;
+ virHashAddEntry(diff, fields[k], value_diff);
+ total_time += *value_diff;
+ }
+
+ for (k = 0; fields[k] != NULL; k++) {
+ double *value = virHashLookup(diff, fields[k]);
+
+ if (!value)
+ continue;
+
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _(fields[k]), *value / total_time * 100);
+
+ if (STREQ("idle:", fields[k]))
+ usage = (total_time - *value) / total_time * 100;
+ }
+
+ if (usage != -1)
+ vshPrint(ctl, "%-15s %5.1lf%%\n",
+ _("usage:"), usage);
}
}
ret = true;
cleanup:
+ for (i = 0; i < 2; i++)
+ virHashFree(cpu_stats[i]);
+ virHashFree(diff);
VIR_FREE(params);
return ret;
}
--
1.8.4.3