virNodeGetCPUStats: Implement virsh support
Signed-off-by: Minoru Usui <usui(a)mxm.nes.nec.co.jp>
---
tools/virsh.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 7 +++
2 files changed, 141 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 5679a2d..2fbc91a 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3682,6 +3682,139 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
}
/*
+ * "nodecpustats" command
+ */
+static const vshCmdInfo info_nodecpustats[] = {
+ {"help", N_("Prints cpu stats of the node.")},
+ {"desc", N_("Returns cpu stats of the node.(nsec)")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_node_cpustats[] = {
+ {"cpu", VSH_OT_INT, 0, N_("prints specified cpu statistics
only.")},
+ {"percent", VSH_OT_BOOL, 0, N_("prints by percentage during 1
second.")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdNodeCPUStats(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+ int i, j;
+ bool flag_utilization = false;
+ bool flag_percent = vshCommandOptBool(cmd, "percent");
+ int cpuNum = VIR_CPU_STATS_ALL_CPUS;
+ virCPUStatsPtr 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 util;
+ } cpu_stats[2];
+ double user_time, sys_time, idle_time, iowait_time, total_time;
+ double usage;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ return false;
+
+ if (vshCommandOptInt(cmd, "cpu", &cpuNum) < 0) {
+ vshError(ctl, "%s", _("Invalid value of cpuNum"));
+ return false;
+ }
+
+ if (virNodeGetCPUStats(ctl->conn, cpuNum, NULL, &nparams, 0) != 0) {
+ vshError(ctl, "%s",
+ _("Unable to get number of cpu stats"));
+ return false;
+ }
+ if (nparams == 0) {
+ /* nothing to output */
+ return true;
+ }
+
+ memset(cpu_stats, 0, sizeof(struct cpu_stats) * 2);
+ params = vshCalloc(ctl, nparams, sizeof(*params));
+
+ i = 0;
+ do {
+ if (virNodeGetCPUStats(ctl->conn, cpuNum, params, &nparams, 0) != 0) {
+ vshError(ctl, "%s", _("Unable to get node cpu stats"));
+ goto cleanup;
+ }
+
+ for (j = 0; j < nparams; j++) {
+ unsigned long long value = params[j].value;
+
+ if (strcmp(params[j].field, VIR_CPU_STATS_KERNEL) == 0)
+ cpu_stats[i].sys = value;
+
+ if (strcmp(params[j].field, VIR_CPU_STATS_USER) == 0)
+ cpu_stats[i].user = value;
+
+ if (strcmp(params[j].field, VIR_CPU_STATS_IDLE) == 0)
+ cpu_stats[i].idle = value;
+
+ if (strcmp(params[j].field, VIR_CPU_STATS_IOWAIT) == 0)
+ cpu_stats[i].iowait = value;
+
+ if (strcmp(params[j].field, VIR_CPU_STATS_UTILIZATION) == 0) {
+ cpu_stats[i].util = value;
+ flag_utilization = true;
+ }
+ }
+
+ if (flag_utilization || (flag_percent == false))
+ break;
+
+ i++;
+ sleep(1);
+ } while(i < 2);
+
+ if (flag_percent == false) {
+ if (flag_utilization == false) {
+ 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);
+ }
+ } else {
+ if (flag_utilization) {
+ usage = cpu_stats[0].util;
+
+ 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;
+ total_time = user_time + sys_time + idle_time + iowait_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);
+ }
+ }
+
+ ret = true;
+
+ cleanup:
+ VIR_FREE(params);
+ return ret;
+}
+
+/*
* "capabilities" command
*/
static const vshCmdInfo info_capabilities[] = {
@@ -11293,6 +11426,7 @@ static const vshCmdDef hostAndHypervisorCmds[] = {
{"freecell", cmdFreecell, opts_freecell, info_freecell, 0},
{"hostname", cmdHostname, NULL, info_hostname, 0},
{"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo, 0},
+ {"nodecpustats", cmdNodeCPUStats, opts_node_cpustats, info_nodecpustats},
{"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command,
info_qemu_monitor_command, 0},
{"sysinfo", cmdSysinfo, NULL, info_sysinfo, 0},
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 6ca3002..ade4eab 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -237,6 +237,13 @@ Print the XML representation of the hypervisor sysinfo, if
available.
Returns basic information about the node, like number and type of CPU,
and size of the physical memory.
+=item B<nodecpustats> optional I<--cpu> I<--percent>
+
+Returns cpu stats of the node.
+If I<--cpu> is specified, this will prints specified cpu statistics only.
+If I<--percent> is specified, this will prints percentage of each kind of cpu
+statistics during 1 second.
+
=item B<capabilities>
Print an XML document describing the capabilities of the hypervisor
--
1.7.1