From 2e8c069dd2f70beadd6c532831f34ece531ac102 Mon Sep 17 00:00:00 2001 From: Dennis Konrad Date: Tue, 17 Dec 2019 10:37:05 +0100 Subject: [PATCH] Load Average for KVM (#3738) * Avgload (#2) * Adding avgload for kvm * Fix coding style issue * Add getter/setter * Fix several small errors * Add override * Uncomment getAverageLoad * Override getAverageLoad() * Checkstyle bug? * Delete trailing spaces * Renaming function * Change interface to match * Rename method in GetHostStatsAnswer * Change method call name * Convert double to long * Remove trailing whitespace * Change names around * Make load visible to return it * Parse string to double * Change Long to Double * Fix getter * Unify naming to cpuloadaverage * Change cpuloadaverage String to Double in listHostsMetrics Remove some unnecessary whitespaces * Add CPU_LOAD_AVERAGE to ApiConstants --- api/src/main/java/com/cloud/host/HostStats.java | 2 +- .../java/org/apache/cloudstack/api/ApiConstants.java | 1 + .../apache/cloudstack/api/response/HostResponse.java | 12 ++++++------ .../java/com/cloud/agent/api/GetHostStatsAnswer.java | 5 +++++ .../java/com/cloud/agent/api/HostStatsEntry.java | 11 +++++++++++ .../wrapper/LibvirtGetHostStatsCommandWrapper.java | 3 ++- .../org/apache/cloudstack/utils/linux/CPUStat.java | 12 ++++++++++++ .../cloudstack/metrics/MetricsServiceImpl.java | 1 + .../cloudstack/response/HostMetricsResponse.java | 10 ++++++++++ .../com/cloud/api/query/dao/HostJoinDaoImpl.java | 1 + 10 files changed, 50 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/com/cloud/host/HostStats.java b/api/src/main/java/com/cloud/host/HostStats.java index 4eb7b1a6de1..d14794401fa 100644 --- a/api/src/main/java/com/cloud/host/HostStats.java +++ b/api/src/main/java/com/cloud/host/HostStats.java @@ -35,6 +35,6 @@ public interface HostStats { public HostStats getHostStats(); - // public double getAverageLoad(); + public double getLoadAverage(); // public double getXapiMemoryUsageKBs(); } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index fb44a8a11f4..e5d96713f68 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -71,6 +71,7 @@ public class ApiConstants { public static final String COMPONENT = "component"; public static final String CPU_NUMBER = "cpunumber"; public static final String CPU_SPEED = "cpuspeed"; + public static final String CPU_LOAD_AVERAGE = "cpuloadaverage"; public static final String CREATED = "created"; public static final String CTX_ACCOUNT_ID = "ctxaccountid"; public static final String CTX_DETAILS = "ctxDetails"; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java index 3d53682d3b9..08c3338a321 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java @@ -114,9 +114,9 @@ public class HostResponse extends BaseResponse { @Param(description = "the amount of the host's CPU after applying the cpu.overprovisioning.factor ") private String cpuWithOverprovisioning; - @SerializedName("averageload") + @SerializedName(ApiConstants.CPU_LOAD_AVERAGE) @Param(description = "the cpu average load on the host") - private Long averageLoad; + private Double cpuloadaverage; @SerializedName("networkkbsread") @Param(description = "the incoming network traffic on the host") @@ -337,8 +337,8 @@ public class HostResponse extends BaseResponse { this.cpuUsed = cpuUsed; } - public void setAverageLoad(Long averageLoad) { - this.averageLoad = averageLoad; + public void setCpuAverageLoad(Double averageLoad) { + this.cpuloadaverage = averageLoad; } public void setNetworkKbsRead(Long networkKbsRead) { @@ -570,8 +570,8 @@ public class HostResponse extends BaseResponse { return cpuUsed; } - public Long getAverageLoad() { - return averageLoad; + public Double getAverageLoad() { + return cpuloadaverage; } public Long getNetworkKbsRead() { diff --git a/core/src/main/java/com/cloud/agent/api/GetHostStatsAnswer.java b/core/src/main/java/com/cloud/agent/api/GetHostStatsAnswer.java index 05a7e3ed422..ffe2ab5e20d 100644 --- a/core/src/main/java/com/cloud/agent/api/GetHostStatsAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/GetHostStatsAnswer.java @@ -69,6 +69,11 @@ public class GetHostStatsAnswer extends Answer implements HostStats { return hostStats.getCpuUtilization(); } + @Override + public double getLoadAverage() { + return hostStats.getLoadAverage(); + } + @Override public double getNetworkReadKBs() { return hostStats.getNetworkReadKBs(); diff --git a/core/src/main/java/com/cloud/agent/api/HostStatsEntry.java b/core/src/main/java/com/cloud/agent/api/HostStatsEntry.java index 5fd1c515b6e..2de15d100e2 100644 --- a/core/src/main/java/com/cloud/agent/api/HostStatsEntry.java +++ b/core/src/main/java/com/cloud/agent/api/HostStatsEntry.java @@ -28,6 +28,7 @@ public class HostStatsEntry implements HostStats { HostVO hostVo; String entityType; double cpuUtilization; + double averageLoad; double networkReadKBs; double networkWriteKBs; double totalMemoryKBs; @@ -45,6 +46,7 @@ public class HostStatsEntry implements HostStats { this.networkWriteKBs = networkWriteKBs; this.totalMemoryKBs = totalMemoryKBs; this.freeMemoryKBs = freeMemoryKBs; + this.averageLoad = averageLoad; } @Override @@ -101,6 +103,15 @@ public class HostStatsEntry implements HostStats { this.cpuUtilization = cpuUtilization; } + @Override + public double getLoadAverage() { + return this.averageLoad; + } + + public void setAverageLoad(double cpuAvgLoad) { + this.averageLoad = cpuAvgLoad; + } + @Override public double getUsedMemory() { return (totalMemoryKBs - freeMemoryKBs) * 1024; diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java index b04a866f3ca..d47b69d1764 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java @@ -42,10 +42,11 @@ public final class LibvirtGetHostStatsCommandWrapper extends CommandWrapper nicStats = libvirtComputingResource.getNicStats(libvirtComputingResource.getPublicBridgeName()); - final HostStatsEntry hostStats = new HostStatsEntry(command.getHostId(), cpuUtil, nicStats.first() / 1024, nicStats.second() / 1024, "host", memStat.getTotal() / 1024, memStat.getAvailable() / 1024, 0, 0); + final HostStatsEntry hostStats = new HostStatsEntry(command.getHostId(), cpuUtil, nicStats.first() / 1024, nicStats.second() / 1024, "host", memStat.getTotal() / 1024, memStat.getAvailable() / 1024, 0, loadAvg); return new GetHostStatsAnswer(command, hostStats); } } \ No newline at end of file diff --git a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/CPUStat.java b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/CPUStat.java index ce3385084ae..d180d013a24 100644 --- a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/CPUStat.java +++ b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/linux/CPUStat.java @@ -30,6 +30,7 @@ public class CPUStat { private UptimeStats _lastStats; private final String _sysfsCpuDir = "/sys/devices/system/cpu"; private final String _uptimeFile = "/proc/uptime"; + private final String _loadavgFile = "/proc/loadavg"; class UptimeStats { public Double upTime = 0d; @@ -80,6 +81,17 @@ public class CPUStat { return _cores; } + public Double getCpuLoadAverage() { + File f = new File(_loadavgFile); + String[] load = {"0.0"}; + try (Scanner scanner = new Scanner(f,"UTF-8");) { + load = scanner.useDelimiter("\\Z").next().split("\\s+"); + } catch (FileNotFoundException ex) { + s_logger.warn("File " + _uptimeFile + " not found:" + ex.toString()); + } + return Double.parseDouble(load[0]); + } + public Double getCpuUsedPercent() { Double cpuUsed = 0d; if (_cores == null || _cores == 0) { diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 9f20fc3efa0..6e6c0ea7e24 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -279,6 +279,7 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric metricsResponse.setCpuTotal(hostResponse.getCpuNumber(), hostResponse.getCpuSpeed(), cpuOvercommitRatio); metricsResponse.setCpuUsed(hostResponse.getCpuUsed(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); + metricsResponse.setLoadAverage(hostResponse.getAverageLoad()); metricsResponse.setMemTotal(hostResponse.getMemoryTotal(), memoryOvercommitRatio); metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated()); metricsResponse.setMemUsed(hostResponse.getMemoryUsed()); diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java index 72e9f92f803..a7446af98a5 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java @@ -43,6 +43,10 @@ public class HostMetricsResponse extends HostResponse { @Param(description = "the total cpu allocated in Ghz") private String cpuAllocated; + @SerializedName("cpuloadaverage") + @Param(description = "the average cpu load the last minute") + private Double loadAverage; + @SerializedName("memorytotalgb") @Param(description = "the total cpu capacity in GiB") private String memTotal; @@ -117,6 +121,12 @@ public class HostMetricsResponse extends HostResponse { } } + public void setLoadAverage(final Double loadAverage) { + if (loadAverage != null) { + this.loadAverage = loadAverage; + } + } + public void setCpuAllocated(final String cpuAllocated, final Integer cpuNumber, final Long cpuSpeed) { if (cpuAllocated != null && cpuNumber != null && cpuSpeed != null) { this.cpuAllocated = String.format("%.2f Ghz", Double.valueOf(cpuAllocated.replace("%", "")) * cpuNumber * cpuSpeed / (100.0 * 1000.0)); diff --git a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java index 4cb8a76940e..35dc89887d9 100644 --- a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -194,6 +194,7 @@ public class HostJoinDaoImpl extends GenericDaoBase implements float cpuUtil = (float)hostStats.getCpuUtilization(); cpuUsed = decimalFormat.format(cpuUtil) + "%"; hostResponse.setCpuUsed(cpuUsed); + hostResponse.setCpuAverageLoad(hostStats.getLoadAverage()); hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue()); hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue()); hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue());