You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by nv...@apache.org on 2022/04/22 11:53:05 UTC

[cloudstack] branch main updated: Fix VM stats inconsistencies (#6245)

This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new f4e95e3105 Fix VM stats inconsistencies (#6245)
f4e95e3105 is described below

commit f4e95e310587b084770b6778836c196d01fbeac5
Author: JoaoJandre <48...@users.noreply.github.com>
AuthorDate: Fri Apr 22 08:52:57 2022 -0300

    Fix VM stats inconsistencies (#6245)
    
    * Fix VM stats inconsistencies
    
    * Address reviews
    
    * Address review
    
    Co-authored-by: João Paraquetti <jo...@scclouds.com.br>
    Co-authored-by: Joao <Jo...@gitlab.com>
---
 .../cloudstack/api/response/StatsResponse.java     | 28 ++++++++--------
 .../cloudstack/api/response/UserVmResponse.java    | 24 ++++++-------
 .../cloudstack/api/response/VolumeResponse.java    | 12 +++----
 .../cloudstack/api/response/StatsResponseTest.java |  4 +--
 .../java/com/cloud/agent/api/VmStatsEntry.java     |  8 ++---
 .../java/com/cloud/agent/api/VmStatsEntryBase.java |  8 ++---
 .../kvm/resource/LibvirtComputingResource.java     | 39 ++++++++++++++++++----
 .../kvm/resource/LibvirtComputingResourceTest.java | 22 +++++++++---
 .../cloudstack/metrics/MetricsServiceImpl.java     |  2 +-
 .../cloudstack/response/VmMetricsResponse.java     | 10 +++---
 .../cloudstack/response/VolumeMetricsResponse.java |  2 +-
 ui/public/locales/ar.json                          |  4 +--
 ui/public/locales/ca.json                          |  4 +--
 ui/public/locales/de_DE.json                       |  4 +--
 ui/public/locales/el_GR.json                       |  4 +--
 ui/public/locales/en.json                          |  6 ++--
 ui/public/locales/es.json                          |  4 +--
 ui/public/locales/fr_FR.json                       |  4 +--
 ui/public/locales/hu.json                          |  4 +--
 ui/public/locales/it_IT.json                       |  4 +--
 ui/public/locales/ko_KR.json                       |  4 +--
 ui/public/locales/nb_NO.json                       |  4 +--
 ui/public/locales/nl_NL.json                       |  4 +--
 ui/public/locales/pl.json                          |  4 +--
 ui/public/locales/pt_BR.json                       |  6 ++--
 ui/src/config/section/compute.js                   |  8 +++--
 26 files changed, 137 insertions(+), 90 deletions(-)

diff --git a/api/src/main/java/org/apache/cloudstack/api/response/StatsResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/StatsResponse.java
index 475d471bdf..74bc961823 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/StatsResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/StatsResponse.java
@@ -35,51 +35,51 @@ public class StatsResponse extends BaseResponse {
     private String cpuUsed;
 
     @SerializedName(ApiConstants.DISK_IO_READ)
-    @Param(description = "the VM's disk read (IO)")
+    @Param(description = "the VM's disk number of read requests (IO) made in the last collection cycle as defined by vm.stats.interval configuration")
     protected Long diskIORead;
 
     @SerializedName(ApiConstants.DISK_IO_WRITE)
-    @Param(description = "the VM's disk write (IO)")
+    @Param(description = "the VM's disk number of write requests (IO) made in the last collection cycle as defined by vm.stats.interval configuration")
     protected Long diskIOWrite;
 
     @SerializedName(ApiConstants.DISK_IO_PSTOTAL)
-    @Param(description = "the total disk iops")
+    @Param(description = "the total disk iops since the last stats retrieval")
     protected Long diskIopsTotal = 0L;
 
     @SerializedName(ApiConstants.DISK_KBS_READ)
-    @Param(description = "the VM's disk read (bytes)")
+    @Param(description = "the VM's disk read in KiB")
     private Long diskKbsRead;
 
     @SerializedName(ApiConstants.DISK_KBS_WRITE)
-    @Param(description = "the VM's disk write (bytes)")
+    @Param(description = "the VM's disk write in KiB")
     private Long diskKbsWrite;
 
     @SerializedName("memoryintfreekbs")
-    @Param(description = "the internal memory free of the VM or zero if it cannot be calculated")
+    @Param(description = "the VM's free memory in KB or -1 if it cannot be gathered")
     private Long memoryIntFreeKBs;
 
     @SerializedName("memorykbs")
-    @Param(description = "the memory used by the VM in Kbps")
+    @Param(description = "the memory used by the VM in KB")
     private Long memoryKBs;
 
     @SerializedName("memorytargetkbs")
-    @Param(description = "the target memory in VM in Kbps")
+    @Param(description = "the target memory in VM (KB)")
     private Long memoryTargetKBs;
 
     @SerializedName("networkkbsread")
-    @Param(description = "the incoming network traffic on the VM")
+    @Param(description = "the incoming network traffic on the VM in KiB")
     protected Long networkKbsRead;
 
     @SerializedName("networkkbswrite")
-    @Param(description = "the outgoing network traffic on the host")
+    @Param(description = "the outgoing network traffic on the host in KiB")
     protected Long networkKbsWrite;
 
     @SerializedName("networkread")
-    @Param(description = "the network read in MiB")
+    @Param(description = "the amount of downloaded data by the VM in MiB")
     protected String networkRead;
 
     @SerializedName("networkwrite")
-    @Param(description = "the network write in MiB")
+    @Param(description = "the amount of uploaded data by the VM in MiB")
     protected String networkWrite;
 
     public void setTimestamp(Date timestamp) {
@@ -123,14 +123,14 @@ public class StatsResponse extends BaseResponse {
     public void setNetworkKbsRead(Long networkKbsRead) {
         this.networkKbsRead = networkKbsRead;
         if (networkKbsRead != null) {
-            this.networkRead = String.format("%.2f MB", networkKbsRead / 1024.0);
+            this.networkRead = String.format("%.2f MiB", networkKbsRead / 1024.0);
         }
     }
 
     public void setNetworkKbsWrite(Long networkKbsWrite) {
         this.networkKbsWrite = networkKbsWrite;
         if (networkKbsWrite != null) {
-            this.networkWrite = String.format("%.2f MB", networkKbsWrite / 1024.0);
+            this.networkWrite = String.format("%.2f MiB", networkKbsWrite / 1024.0);
         }
     }
 
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
index 835c30c8ee..76715fe76c 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -175,11 +175,11 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
     private Boolean forVirtualNetwork;
 
     @SerializedName(ApiConstants.CPU_NUMBER)
-    @Param(description = "the number of cpu this virtual machine is running with")
+    @Param(description = "the number of vCPUs this virtual machine is using")
     private Integer cpuNumber;
 
     @SerializedName(ApiConstants.CPU_SPEED)
-    @Param(description = "the speed of each cpu")
+    @Param(description = "the speed of each vCPU")
     private Integer cpuSpeed;
 
     @SerializedName(ApiConstants.MEMORY)
@@ -187,7 +187,7 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
     private Integer memory;
 
     @SerializedName(ApiConstants.VGPU)
-    @Param(description = "the vgpu type used by the virtual machine", since = "4.4")
+    @Param(description = "the vGPU type used by the virtual machine", since = "4.4")
     private String vgpu;
 
     @SerializedName("cpuused")
@@ -195,39 +195,39 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
     private String cpuUsed;
 
     @SerializedName("networkkbsread")
-    @Param(description = "the incoming network traffic on the vm")
+    @Param(description = "the incoming network traffic on the VM in KiB")
     private Long networkKbsRead;
 
     @SerializedName("networkkbswrite")
-    @Param(description = "the outgoing network traffic on the host")
+    @Param(description = "the outgoing network traffic on the host in KiB")
     private Long networkKbsWrite;
 
     @SerializedName(ApiConstants.DISK_KBS_READ)
-    @Param(description = "the read (bytes) of disk on the vm")
+    @Param(description = "the VM's disk read in KiB")
     private Long diskKbsRead;
 
     @SerializedName(ApiConstants.DISK_KBS_WRITE)
-    @Param(description = "the write (bytes) of disk on the vm")
+    @Param(description = "the VM's disk write in KiB")
     private Long diskKbsWrite;
 
     @SerializedName("memorykbs")
-    @Param(description = "the memory used by the vm")
+    @Param(description = "the memory used by the VM in KiB")
     private Long memoryKBs;
 
     @SerializedName("memoryintfreekbs")
-    @Param(description = "the internal memory that's free in vm or zero if it can not be calculated")
+    @Param(description = "the internal memory (KiB) that's free in VM or zero if it can not be calculated")
     private Long memoryIntFreeKBs;
 
     @SerializedName("memorytargetkbs")
-    @Param(description = "the target memory in vm")
+    @Param(description = "the target memory in VM (KiB)")
     private Long memoryTargetKBs;
 
     @SerializedName(ApiConstants.DISK_IO_READ)
-    @Param(description = "the read (io) of disk on the vm")
+    @Param(description = "the read (IO) of disk on the VM")
     private Long diskIORead;
 
     @SerializedName(ApiConstants.DISK_IO_WRITE)
-    @Param(description = "the write (io) of disk on the vm")
+    @Param(description = "the write (IO) of disk on the VM")
     private Long diskIOWrite;
 
     @SerializedName("guestosid")
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java
index b5d9735ffb..a0f59ac3db 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java
@@ -153,27 +153,27 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co
     private Long bytesWriteRate;
 
     @SerializedName("diskIopsReadRate")
-    @Param(description = "io requests read rate of the disk volume per the disk offering")
+    @Param(description = "IO requests read rate of the disk volume per the disk offering")
     private Long iopsReadRate;
 
     @SerializedName("diskIopsWriteRate")
-    @Param(description = "io requests write rate of the disk volume per the disk offering")
+    @Param(description = "IO requests write rate of the disk volume per the disk offering")
     private Long iopsWriteRate;
 
     @SerializedName(ApiConstants.DISK_KBS_READ)
-    @Param(description = "the read (bytes) of disk on the vm")
+    @Param(description = "the VM's disk read in KiB")
     private Long diskKbsRead;
 
     @SerializedName(ApiConstants.DISK_KBS_WRITE)
-    @Param(description = "the write (bytes) of disk on the vm")
+    @Param(description = "the VM's disk write in KiB")
     private Long diskKbsWrite;
 
     @SerializedName(ApiConstants.DISK_IO_READ)
-    @Param(description = "the read (io) of disk on the vm")
+    @Param(description = "the read (IO) of disk on the vm")
     private Long diskIORead;
 
     @SerializedName(ApiConstants.DISK_IO_WRITE)
-    @Param(description = "the write (io) of disk on the vm")
+    @Param(description = "the write (IO) of disk on the vm")
     private Long diskIOWrite;
 
     @SerializedName(ApiConstants.HYPERVISOR)
diff --git a/api/src/test/java/org/apache/cloudstack/api/response/StatsResponseTest.java b/api/src/test/java/org/apache/cloudstack/api/response/StatsResponseTest.java
index b6ba8533da..07f9b59a37 100644
--- a/api/src/test/java/org/apache/cloudstack/api/response/StatsResponseTest.java
+++ b/api/src/test/java/org/apache/cloudstack/api/response/StatsResponseTest.java
@@ -106,7 +106,7 @@ public class StatsResponseTest {
     @Test
     public void setNetworkKbsReadTestWithInputNotNull() {
         Long expectedNetworkKbsRead = Long.valueOf("100");
-        String expectedNetworkRead = String.format("0%s10 MB", decimalSeparator); // the actual result is 0.097 but the value is rounded to 0.10
+        String expectedNetworkRead = String.format("0%s10 MiB", decimalSeparator); // the actual result is 0.097 but the value is rounded to 0.10
 
         statsResponseMock.setNetworkKbsRead(expectedNetworkKbsRead);
 
@@ -125,7 +125,7 @@ public class StatsResponseTest {
     @Test
     public void setNetworkKbsWriteTestWithInputNotNull() {
         Long expectedNetworkKbsWrite = Long.valueOf("100");
-        String expectedNetworkWrite = String.format("0%s10 MB", decimalSeparator); // the actual result is 0.097 but the value is rounded to 0.10
+        String expectedNetworkWrite = String.format("0%s10 MiB", decimalSeparator); // the actual result is 0.097 but the value is rounded to 0.10
 
         statsResponseMock.setNetworkKbsWrite(expectedNetworkKbsWrite);
 
diff --git a/core/src/main/java/com/cloud/agent/api/VmStatsEntry.java b/core/src/main/java/com/cloud/agent/api/VmStatsEntry.java
index e09a3c05c8..9c792b8825 100644
--- a/core/src/main/java/com/cloud/agent/api/VmStatsEntry.java
+++ b/core/src/main/java/com/cloud/agent/api/VmStatsEntry.java
@@ -37,11 +37,11 @@ public class VmStatsEntry extends VmStatsEntryBase {
      * @param intFreeMemoryKBs the internal free memory (in KBs).
      * @param targetMemoryKBs the target memory (in KBs).
      * @param cpuUtilization the CPU utilization.
-     * @param networkReadKBs the network read (in KBs).
-     * @param networkWriteKBs the network write (in KBs).
+     * @param networkReadKBs the network read (in KiBs).
+     * @param networkWriteKBs the network write (in KiBs).
      * @param numCPUs the number of CPUs.
-     * @param diskReadKBs the disk read (in KBs).
-     * @param diskWriteKBs the disk write (in KBs).
+     * @param diskReadKBs the disk read (in KiBs).
+     * @param diskWriteKBs the disk write (in KiBs).
      * @param diskReadIOs the disk read I/O.
      * @param diskWriteIOs the disk write I/O.
      * @param entityType the entity type.
diff --git a/core/src/main/java/com/cloud/agent/api/VmStatsEntryBase.java b/core/src/main/java/com/cloud/agent/api/VmStatsEntryBase.java
index b9f671b88f..6c95d1cb34 100644
--- a/core/src/main/java/com/cloud/agent/api/VmStatsEntryBase.java
+++ b/core/src/main/java/com/cloud/agent/api/VmStatsEntryBase.java
@@ -48,11 +48,11 @@ public class VmStatsEntryBase implements VmStats {
      * @param intFreeMemoryKBs the internal free memory (in KBs).
      * @param targetMemoryKBs the target memory (in KBs).
      * @param cpuUtilization the CPU utilization.
-     * @param networkReadKBs the network read (in KBs).
-     * @param networkWriteKBs the network write (in KBs).
+     * @param networkReadKBs the network read (in KiBs).
+     * @param networkWriteKBs the network write (in KiBs).
      * @param numCPUs the number of CPUs.
-     * @param diskReadKBs the disk read (in KBs).
-     * @param diskWriteKBs the disk write (in KBs).
+     * @param diskReadKBs the disk read (in KiBs).
+     * @param diskWriteKBs the disk write (in KiBs).
      * @param diskReadIOs the disk read I/O.
      * @param diskWriteIOs the disk write I/O.
      * @param entityType the entity type.
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 97be335b84..c513be6be2 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -307,7 +307,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
 
     private long _hvVersion;
     private Duration _timeout;
-    private static final int NUMMEMSTATS =2;
+    /**
+     * Since the memoryStats method returns an array that isn't ordered, we pass a big number to get all the array and then search for the information we want.
+     * */
+    private static final int NUMMEMSTATS = 20;
+
+    /**
+     * Unused memory's tag to search in the array returned by the Domain.memoryStats() method.
+     * */
+    private static final int UNUSEDMEMORY = 4;
+
 
     private KVMHAMonitor _monitor;
     public static final String SSHPUBKEYPATH = SSHKEYSPATH + File.separator + "id_rsa.pub.cloud";
@@ -4050,17 +4059,35 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
 
     /**
      * This method retrieves the memory statistics from the domain given as parameters.
-     * If no memory statistic is found, it will return {@link NumberUtils#LONG_ZERO} as the value of free memory in the domain.
+     * If no memory statistic is found, it will return {@link NumberUtils#LONG_MINUS_ONE} as the value of free memory in the domain.
      * If it can retrieve the domain memory statistics, it will return the free memory statistic; that means, it returns the value at the first position of the array returned by {@link Domain#memoryStats(int)}.
      *
      * @return the amount of free memory in KBs
      */
     protected long getMemoryFreeInKBs(Domain dm) throws LibvirtException {
-        MemoryStatistic[] mems = dm.memoryStats(NUMMEMSTATS);
-        if (ArrayUtils.isEmpty(mems)) {
-            return NumberUtils.LONG_ZERO;
+        MemoryStatistic[] memoryStats = dm.memoryStats(NUMMEMSTATS);
+
+        if(s_logger.isTraceEnabled()){
+            s_logger.trace(String.format("Retrieved memory statistics (information about tags can be found on the libvirt documentation):", ArrayUtils.toString(memoryStats)));
+        }
+
+        long freeMemory = NumberUtils.LONG_MINUS_ONE;
+
+        if (ArrayUtils.isEmpty(memoryStats)){
+            return freeMemory;
+        }
+
+        for (int i = 0; i < memoryStats.length; i++) {
+            if(memoryStats[i].getTag() == UNUSEDMEMORY) {
+                freeMemory = memoryStats[i].getValue();
+                break;
+            }
+        }
+
+        if (freeMemory == NumberUtils.LONG_MINUS_ONE){
+            s_logger.warn("Couldn't retrieve free memory, returning -1.");
         }
-        return mems[0].getValue();
+        return freeMemory;
     }
 
     private boolean canBridgeFirewall(final String prvNic) {
diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
index 0da2373c1f..ffe54f73da 100644
--- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
+++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
@@ -907,7 +907,8 @@ public class LibvirtComputingResourceTest {
         final MemoryStatistic[] domainMem = new MemoryStatistic[2];
         domainMem[0] = Mockito.mock(MemoryStatistic.class);
         Mockito.when(domain.getInfo()).thenReturn(domainInfo);
-        Mockito.when(domain.memoryStats(2)).thenReturn(domainMem);
+        Mockito.when(domain.memoryStats(20)).thenReturn(domainMem);
+        Mockito.when(domainMem[0].getTag()).thenReturn(4);
         Mockito.when(connect.domainLookupByName(VMNAME)).thenReturn(domain);
         final NodeInfo nodeInfo = new NodeInfo();
         nodeInfo.cpus = 8;
@@ -5585,21 +5586,34 @@ public class LibvirtComputingResourceTest {
         Domain domainMock = getDomainConfiguredToReturnMemoryStatistic(null);
         long memoryFreeInKBs = libvirtComputingResource.getMemoryFreeInKBs(domainMock);
 
-        Assert.assertEquals(0, memoryFreeInKBs);
+        Assert.assertEquals(-1, memoryFreeInKBs);
+    }
+
+    @Test
+    public void getMemoryFreeInKBsTestDomainReturningIncompleteArray() throws LibvirtException {
+        LibvirtComputingResource libvirtComputingResource = new LibvirtComputingResource();
+
+        MemoryStatistic[] mem = createMemoryStatisticFreeMemory100();
+        mem[0].setTag(0);
+        Domain domainMock = getDomainConfiguredToReturnMemoryStatistic(mem);
+        long memoryFreeInKBs = libvirtComputingResource.getMemoryFreeInKBs(domainMock);
+
+        Assert.assertEquals(-1, memoryFreeInKBs);
     }
 
     private MemoryStatistic[] createMemoryStatisticFreeMemory100() {
         virDomainMemoryStats stat = new virDomainMemoryStats();
         stat.val = 100;
+        stat.tag = 4;
 
-        MemoryStatistic[] mem = new MemoryStatistic[2];
+        MemoryStatistic[] mem = new MemoryStatistic[1];
         mem[0] = new MemoryStatistic(stat);
         return mem;
     }
 
     private Domain getDomainConfiguredToReturnMemoryStatistic(MemoryStatistic[] mem) throws LibvirtException {
         Domain domainMock = Mockito.mock(Domain.class);
-        when(domainMock.memoryStats(2)).thenReturn(mem);
+        when(domainMock.memoryStats(20)).thenReturn(mem);
         return domainMock;
     }
 
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 2968314938..3d24990050 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
@@ -340,7 +340,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
             response.setDiskIOWrite((long)statsEntry.getDiskWriteIOs());
             long totalMemory = (long)statsEntry.getMemoryKBs();
             long freeMemory = (long)statsEntry.getIntFreeMemoryKBs();
-            long correctedFreeMemory = freeMemory >= totalMemory ? 0 : freeMemory;
+            long correctedFreeMemory = freeMemory >= totalMemory ? -1 : freeMemory;
             response.setMemoryKBs(totalMemory);
             response.setMemoryIntFreeKBs(correctedFreeMemory);
             response.setMemoryTargetKBs((long)statsEntry.getTargetMemoryKBs());
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java
index 4ac388ddb9..fb5e8e5e10 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java
@@ -73,31 +73,31 @@ public class VmMetricsResponse extends UserVmResponse {
 
     public void setMemTotal(final Integer memory) {
         if (memory != null) {
-            this.memTotal = String.format("%.2f GB", memory / 1024.0);
+            this.memTotal = String.format("%.2f GiB", memory / 1024.0);
         }
     }
 
     public void setNetworkRead(final Long networkReadKbs) {
         if (networkReadKbs != null) {
-            this.networkRead = String.format("%.2f MB", networkReadKbs / 1024.0);
+            this.networkRead = String.format("%.2f MiB", networkReadKbs / 1024.0);
         }
     }
 
     public void setNetworkWrite(final Long networkWriteKbs) {
         if (networkWriteKbs != null) {
-            this.networkWrite = String.format("%.2f MB", networkWriteKbs / 1024.0);
+            this.networkWrite = String.format("%.2f MiB", networkWriteKbs / 1024.0);
         }
     }
 
     public void setDiskRead(final Long diskReadKbs) {
         if (diskReadKbs != null) {
-            this.networkRead = String.format("%.2f MB", diskReadKbs / 1024.0);
+            this.diskRead = String.format("%.2f MiB", diskReadKbs / 1024.0);
         }
     }
 
     public void setDiskWrite(final Long diskWriteKbs) {
         if (diskWriteKbs != null) {
-            this.networkWrite = String.format("%.2f MB", diskWriteKbs / 1024.0);
+            this.diskWrite = String.format("%.2f MiB", diskWriteKbs / 1024.0);
         }
     }
 
diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VolumeMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VolumeMetricsResponse.java
index c67315cf59..c2004817dd 100644
--- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VolumeMetricsResponse.java
+++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VolumeMetricsResponse.java
@@ -41,7 +41,7 @@ public class VolumeMetricsResponse extends VolumeResponse {
 
     public void setDiskSizeGB(final Long size) {
         if (size != null) {
-            this.diskSizeGB = String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
+            this.diskSizeGB = String.format("%.2f GiB", size / (1024.0 * 1024.0 * 1024.0));
         }
     }
 
diff --git a/ui/public/locales/ar.json b/ui/public/locales/ar.json
index e3ff3799a9..e9deefcde5 100644
--- a/ui/public/locales/ar.json
+++ b/ui/public/locales/ar.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Disk Write Rate (IOPS)",
 "label.diskioread": "Disk Read (IO)",
 "label.diskiowrite": "Disk Write (IO)",
-"label.diskkbsread": "Disk Read (Bytes)",
-"label.diskkbswrite": "Disk Write (Bytes)",
+"label.diskkbsread": "Disk Read (KiB)",
+"label.diskkbswrite": "Disk Write (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Disk Offering",
 "label.diskofferingid": "Disk Offering",
diff --git a/ui/public/locales/ca.json b/ui/public/locales/ca.json
index 8a089447d1..5601bb5eed 100644
--- a/ui/public/locales/ca.json
+++ b/ui/public/locales/ca.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Disk Write Rate (IOPS)",
 "label.diskioread": "Disk Read (IO)",
 "label.diskiowrite": "Disk Write (IO)",
-"label.diskkbsread": "Disk Read (Bytes)",
-"label.diskkbswrite": "Disk Write (Bytes)",
+"label.diskkbsread": "Disk Read (KiB)",
+"label.diskkbswrite": "Disk Write (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Disk Offering",
 "label.diskofferingid": "Disk Offering",
diff --git a/ui/public/locales/de_DE.json b/ui/public/locales/de_DE.json
index c88711008e..53110463de 100644
--- a/ui/public/locales/de_DE.json
+++ b/ui/public/locales/de_DE.json
@@ -741,8 +741,8 @@
 "label.diskiopswriterate": "Festplatten-Schreibrate (IOPS)",
 "label.diskioread": "Festplatte Lesen (EA)",
 "label.diskiowrite": "Festplatte Schreiben (EA)",
-"label.diskkbsread": "Festplatte Lesen (Bytes)",
-"label.diskkbswrite": "Festplatte Schreiben (Bytes)",
+"label.diskkbsread": "Festplatte Lesen (KiB)",
+"label.diskkbswrite": "Festplatte Schreiben (KiB)",
 "label.diskoffering": "Festplattenangebot",
 "label.diskofferingdisplaytext": "Festplattenangebot",
 "label.diskofferingid": "Festplattenangebot",
diff --git a/ui/public/locales/el_GR.json b/ui/public/locales/el_GR.json
index 0f1260e4ea..1cfc433b74 100644
--- a/ui/public/locales/el_GR.json
+++ b/ui/public/locales/el_GR.json
@@ -768,8 +768,8 @@
 "label.diskiopswriterate" : "Ρυθμός εγγραφής δίσκου (IOPS)",
 "label.diskioread" : "Ανάγνωση δίσκου (IO)",
 "label.diskiowrite" : "Εγγραφή δίσκου (IO)",
-"label.diskkbsread" : "Ανάγνωση δίσκου (byte)",
-"label.diskkbswrite" : "Εγγραφή δίσκου (byte)",
+"label.diskkbsread" : "Ανάγνωση δίσκου (KiB)",
+"label.diskkbswrite" : "Εγγραφή δίσκου (KiB)",
 "label.diskoffering" : "Προσφορά δίσκου",
 "label.diskofferingdisplaytext" : "Προσφορά δίσκου",
 "label.diskofferingid" : "Προσφορά δίσκου",
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 0d98e9bdab..f56bb0ba29 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -836,8 +836,10 @@
 "label.diskiopswriterate": "Disk Write Rate (IOPS)",
 "label.diskioread": "Disk Read (IO)",
 "label.diskiowrite": "Disk Write (IO)",
-"label.diskkbsread": "Disk Read (Bytes)",
-"label.diskkbswrite": "Disk Write (Bytes)",
+"label.diskkbsread": "Disk Read (KiB)",
+"label.diskkbswrite": "Disk Write (KiB)",
+"label.diskread": "Disk Read",
+"label.diskwrite": "Disk Write",
 "label.diskoffering": "Disk Offering",
 "label.diskofferingdisplaytext": "Disk Offering",
 "label.diskofferingid": "Disk Offering",
diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json
index e54bd076a7..16095aa068 100644
--- a/ui/public/locales/es.json
+++ b/ui/public/locales/es.json
@@ -634,8 +634,8 @@
 "label.diskiopswriterate": "Tasa Escritura de Disco (IOPS)",
 "label.diskioread": "Lectura Disco (IO)",
 "label.diskiowrite": "Escritura Disco (IO)",
-"label.diskkbsread": "Lectura Disco (Bytes)",
-"label.diskkbswrite": "Escritura Disco (Bytes)",
+"label.diskkbsread": "Lectura Disco (KiB)",
+"label.diskkbswrite": "Escritura Disco (KiB)",
 "label.diskoffering": "Oferta de Disco",
 "label.diskofferingdisplaytext": "Oferta de Disco",
 "label.diskofferingid": "Oferta de Disco",
diff --git a/ui/public/locales/fr_FR.json b/ui/public/locales/fr_FR.json
index cec5cc0cc3..4418ce909f 100644
--- a/ui/public/locales/fr_FR.json
+++ b/ui/public/locales/fr_FR.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "D\u00e9bit \u00e9criture disque (IOPS)",
 "label.diskioread": "Lecture Disque (IO)",
 "label.diskiowrite": "\u00c9criture Disque (IO)",
-"label.diskkbsread": "Lecture Disque (Octets)",
-"label.diskkbswrite": "\u00c9criture Disque (Octets)",
+"label.diskkbsread": "Lecture Disque (KiB)",
+"label.diskkbswrite": "\u00c9criture Disque (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Offre de Disque",
 "label.diskofferingid": "Offre de Disque",
diff --git a/ui/public/locales/hu.json b/ui/public/locales/hu.json
index e24078ed2b..8132b9c823 100644
--- a/ui/public/locales/hu.json
+++ b/ui/public/locales/hu.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "\u00cdr\u00e1si r\u00e1ta (IOPS)",
 "label.diskioread": "Merevlemez \u00edr\u00e1s (IO)",
 "label.diskiowrite": "Merevlemez \u00edr\u00e1s (IO)",
-"label.diskkbsread": "Merevlemez olvas\u00e1s (Byte)",
-"label.diskkbswrite": "Merevlemez \u00edr\u00e1s (byte)",
+"label.diskkbsread": "Merevlemez olvas\u00e1s (KiB)",
+"label.diskkbswrite": "Merevlemez \u00edr\u00e1s (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Merevlemez aj\u00e1nlat",
 "label.diskofferingid": "Merevlemez aj\u00e1nlat",
diff --git a/ui/public/locales/it_IT.json b/ui/public/locales/it_IT.json
index df280ad075..e1b2ff15a5 100644
--- a/ui/public/locales/it_IT.json
+++ b/ui/public/locales/it_IT.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Disk Write Rate (IOPS)",
 "label.diskioread": "Disk Read (IO)",
 "label.diskiowrite": "Disk Write (IO)",
-"label.diskkbsread": "Disk Read (Bytes)",
-"label.diskkbswrite": "Disk Write (Bytes)",
+"label.diskkbsread": "Disk Read (KiB)",
+"label.diskkbswrite": "Disk Write (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Offerta Disco",
 "label.diskofferingid": "Offerta Disco",
diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json
index 24e40b6868..eb90d9ccc0 100644
--- a/ui/public/locales/ko_KR.json
+++ b/ui/public/locales/ko_KR.json
@@ -767,8 +767,8 @@
 "label.diskiopswriterate": "\ub514\uc2a4\ud06c \uc4f0\uae30 \uc18d\ub3c4(IOPS)",
 "label.diskioread": "\ub514\uc2a4\ud06c \uc77d\uae30(IO)",
 "label.diskiowrite": "\ub514\uc2a4\ud06c \uc4f0\uae30(IO)",
-"label.diskkbsread": "\ub514\uc2a4\ud06c \uc77d\uae30(Bytes)",
-"label.diskkbswrite": "\ub514\uc2a4\ud06c \uc4f0\uae30(Bytes)",
+"label.diskkbsread": "\ub514\uc2a4\ud06c \uc77d\uae30 (KiB)",
+"label.diskkbswrite": "\ub514\uc2a4\ud06c \uc4f0\uae30 (KiB)",
 "label.diskoffering": "\ub514\uc2a4\ud06c \uc624\ud37c\ub9c1",
 "label.diskofferingdisplaytext": "\ub514\uc2a4\ud06c \uc624\ud37c\ub9c1",
 "label.diskofferingid": "\ub514\uc2a4\ud06c \uc624\ud37c\ub9c1",
diff --git a/ui/public/locales/nb_NO.json b/ui/public/locales/nb_NO.json
index c667e58ce9..a43a47a9bb 100644
--- a/ui/public/locales/nb_NO.json
+++ b/ui/public/locales/nb_NO.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Diskskrivehastighet (IOPS)",
 "label.diskioread": "Disk lese (IO)",
 "label.diskiowrite": "Disk skrive (IO)",
-"label.diskkbsread": "Disk lese (Bytes)",
-"label.diskkbswrite": "Disk skrive (Bytes)",
+"label.diskkbsread": "Disk lese (KiB)",
+"label.diskkbswrite": "Disk skrive (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Disktilbud",
 "label.diskofferingid": "Disktilbud",
diff --git a/ui/public/locales/nl_NL.json b/ui/public/locales/nl_NL.json
index e687d3bd45..bfaac77bee 100644
--- a/ui/public/locales/nl_NL.json
+++ b/ui/public/locales/nl_NL.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Schrijf snelheid Schijf (IOPS)",
 "label.diskioread": "Schijf Lezen (IO)",
 "label.diskiowrite": "Schijf Schrijven (IO)",
-"label.diskkbsread": "Schijf lezen (Bytes)",
-"label.diskkbswrite": "Schijf Schrijven (Bytes)",
+"label.diskkbsread": "Schijf lezen (KiB)",
+"label.diskkbswrite": "Schijf Schrijven (KiB)",
 "label.diskoffering": "opslagaanbieding",
 "label.diskofferingdisplaytext": "Schijf Aanbieding",
 "label.diskofferingid": "Schijf Aanbieding",
diff --git a/ui/public/locales/pl.json b/ui/public/locales/pl.json
index 511859a1c9..07a726c062 100644
--- a/ui/public/locales/pl.json
+++ b/ui/public/locales/pl.json
@@ -623,8 +623,8 @@
 "label.diskiopswriterate": "Disk Write Rate (IOPS)",
 "label.diskioread": "Disk Read (IO)",
 "label.diskiowrite": "Disk Write (IO)",
-"label.diskkbsread": "Disk Read (Bytes)",
-"label.diskkbswrite": "Disk Write (Bytes)",
+"label.diskkbsread": "Disk Read (KiB)",
+"label.diskkbswrite": "Disk Write (KiB)",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Disk Offering",
 "label.diskofferingid": "Disk Offering",
diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json
index 8edede3f2f..c81c95b3c1 100644
--- a/ui/public/locales/pt_BR.json
+++ b/ui/public/locales/pt_BR.json
@@ -623,8 +623,10 @@
 "label.diskiopswriterate": "Taxa de Escrita no Disco (IOPS)",
 "label.diskioread": "Leitura do Disk (I/O)",
 "label.diskiowrite": "Escrita no Disco (I/O)",
-"label.diskkbsread": "Leitura do Disco (Bytes)",
-"label.diskkbswrite": "Escrita no Disco (Bytes)",
+"label.diskkbsread": "Leitura do Disco (KiB)",
+"label.diskkbswrite": "Escrita no Disco (KiB)",
+"label.diskread": "Leitura do Disco",
+"label.diskwrite": "Escrita no Disco",
 "label.diskoffering": "diskoffering",
 "label.diskofferingdisplaytext": "Oferta de Disco",
 "label.diskofferingid": "Oferta de Disco",
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 48871b2ee2..28afc06a8c 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -50,11 +50,13 @@ export default {
         const metricsFields = ['cpunumber', 'cpuused', 'cputotal',
           {
             memoryused: (record) => {
-              return record.memorykbs && record.memoryintfreekbs ? parseFloat(100.0 * (record.memorykbs - record.memoryintfreekbs) / record.memorykbs).toFixed(2) + '%' : '0.0%'
+              if (record.memoryintfreekbs <= 0 || record.memorykbs <= 0) {
+                return '-'
+              }
+              return parseFloat(100.0 * (record.memorykbs - record.memoryintfreekbs) / record.memorykbs).toFixed(2) + '%'
             }
           },
-          'memorytotal', 'networkread', 'networkwrite', 'diskkbsread', 'diskkbswrite', 'diskiopstotal'
-        ]
+          'memorytotal', 'networkread', 'networkwrite', 'diskread', 'diskwrite', 'diskiopstotal']
 
         if (store.getters.metrics) {
           fields.push(...metricsFields)