virNodeGetCPUStats: Implement virsh support Signed-off-by: Minoru Usui <usui@xxxxxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list