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 7502b18488e..3c1d7bb93c6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -91,6 +91,11 @@ public class ApiConstants { public static final String DIRECT_DOWNLOAD = "directdownload"; public static final String DISK_OFFERING_ID = "diskofferingid"; public static final String NEW_DISK_OFFERING_ID = "newdiskofferingid"; + public static final String DISK_KBS_READ = "diskkbsread"; + public static final String DISK_KBS_WRITE = "diskkbswrite"; + public static final String DISK_IO_READ = "diskioread"; + public static final String DISK_IO_WRITE = "diskiowrite"; + public static final String DISK_IO_PSTOTAL = "diskiopstotal"; public static final String DISK_SIZE = "disksize"; public static final String UTILIZATION = "utilization"; public static final String DRIVER = "driver"; 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 bbf6b6cf614..8a2f1a169d6 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 @@ -188,11 +188,11 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the outgoing network traffic on the host") private Long networkKbsWrite; - @SerializedName("diskkbsread") + @SerializedName(ApiConstants.DISK_KBS_READ) @Param(description = "the read (bytes) of disk on the vm") private Long diskKbsRead; - @SerializedName("diskkbswrite") + @SerializedName(ApiConstants.DISK_KBS_WRITE) @Param(description = "the write (bytes) of disk on the vm") private Long diskKbsWrite; @@ -208,11 +208,11 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the target memory in vm") private Long memoryTargetKBs; - @SerializedName("diskioread") + @SerializedName(ApiConstants.DISK_IO_READ) @Param(description = "the read (io) of disk on the vm") private Long diskIORead; - @SerializedName("diskiowrite") + @SerializedName(ApiConstants.DISK_IO_WRITE) @Param(description = "the write (io) of disk on the vm") private Long diskIOWrite; 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 d845e414808..01d2c9b3d8f 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 @@ -16,17 +16,18 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.serializer.Param; -import com.cloud.storage.Volume; -import com.google.gson.annotations.SerializedName; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Set; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponseWithTagInformation; import org.apache.cloudstack.api.EntityReference; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.Set; +import com.cloud.serializer.Param; +import com.cloud.storage.Volume; +import com.google.gson.annotations.SerializedName; @EntityReference(value = Volume.class) @SuppressWarnings("unused") @@ -152,13 +153,29 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co private Long bytesWriteRate; @SerializedName("diskIopsReadRate") - @Param(description = "io requests read rate of the disk volume") + @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") + @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") + private Long diskKbsRead; + + @SerializedName(ApiConstants.DISK_KBS_WRITE) + @Param(description = "the write (bytes) of disk on the vm") + private Long diskKbsWrite; + + @SerializedName(ApiConstants.DISK_IO_READ) + @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") + private Long diskIOWrite; + @SerializedName(ApiConstants.HYPERVISOR) @Param(description = "Hypervisor the volume belongs to") private String hypervisor; @@ -395,10 +412,42 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co this.iopsWriteRate = iopsWriteRate; } + public Long getDiskKbsRead() { + return diskKbsRead; + } + + public void setDiskKbsRead(Long diskKbsRead) { + this.diskKbsRead = diskKbsRead; + } + + public Long getDiskKbsWrite() { + return diskKbsWrite; + } + + public void setDiskKbsWrite(Long diskKbsWrite) { + this.diskKbsWrite = diskKbsWrite; + } + public Long getIopsWriteRate() { return iopsWriteRate; } + public Long getDiskIORead() { + return diskIORead; + } + + public void setDiskIORead(Long diskIORead) { + this.diskIORead = diskIORead; + } + + public Long getDiskIOWrite() { + return diskIOWrite; + } + + public void setDiskIOWrite(Long diskIOWrite) { + this.diskIOWrite = diskIOWrite; + } + public void setHypervisor(String hypervisor) { this.hypervisor = hypervisor; } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 3d6732c0fbe..c195712e62a 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -42,68 +42,7 @@ import java.util.TimeZone; import java.util.UUID; import javax.naming.ConfigurationException; - -import org.apache.commons.lang.math.NumberUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; -import org.joda.time.Duration; - -import com.google.gson.Gson; -import com.vmware.vim25.AboutInfo; -import com.vmware.vim25.BoolPolicy; -import com.vmware.vim25.ComputeResourceSummary; -import com.vmware.vim25.CustomFieldStringValue; -import com.vmware.vim25.DVPortConfigInfo; -import com.vmware.vim25.DVPortConfigSpec; -import com.vmware.vim25.DasVmPriority; -import com.vmware.vim25.DatastoreSummary; -import com.vmware.vim25.DistributedVirtualPort; -import com.vmware.vim25.DistributedVirtualSwitchPortConnection; -import com.vmware.vim25.DistributedVirtualSwitchPortCriteria; -import com.vmware.vim25.DynamicProperty; -import com.vmware.vim25.GuestInfo; -import com.vmware.vim25.HostCapability; -import com.vmware.vim25.HostHostBusAdapter; -import com.vmware.vim25.HostInternetScsiHba; -import com.vmware.vim25.ManagedObjectReference; -import com.vmware.vim25.ObjectContent; -import com.vmware.vim25.OptionValue; -import com.vmware.vim25.PerfCounterInfo; -import com.vmware.vim25.PerfEntityMetric; -import com.vmware.vim25.PerfEntityMetricBase; -import com.vmware.vim25.PerfMetricId; -import com.vmware.vim25.PerfMetricIntSeries; -import com.vmware.vim25.PerfMetricSeries; -import com.vmware.vim25.PerfQuerySpec; -import com.vmware.vim25.PerfSampleInfo; -import com.vmware.vim25.RuntimeFaultFaultMsg; -import com.vmware.vim25.ToolsUnavailableFaultMsg; -import com.vmware.vim25.VMwareDVSPortSetting; -import com.vmware.vim25.VimPortType; -import com.vmware.vim25.VirtualDevice; -import com.vmware.vim25.VirtualDeviceBackingInfo; -import com.vmware.vim25.VirtualDeviceConfigSpec; -import com.vmware.vim25.VirtualDeviceConfigSpecOperation; -import com.vmware.vim25.VirtualDisk; -import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; -import com.vmware.vim25.VirtualEthernetCard; -import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; -import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo; -import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo; -import com.vmware.vim25.VirtualMachineConfigSpec; -import com.vmware.vim25.VirtualMachineFileInfo; -import com.vmware.vim25.VirtualMachineFileLayoutEx; -import com.vmware.vim25.VirtualMachineFileLayoutExFileInfo; -import com.vmware.vim25.VirtualMachineGuestOsIdentifier; -import com.vmware.vim25.VirtualMachinePowerState; -import com.vmware.vim25.VirtualMachineRelocateSpec; -import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator; -import com.vmware.vim25.VirtualMachineRuntimeInfo; -import com.vmware.vim25.VirtualMachineToolsStatus; -import com.vmware.vim25.VirtualMachineVideoCard; -import com.vmware.vim25.VirtualUSBController; -import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; +import javax.xml.datatype.XMLGregorianCalendar; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; @@ -114,6 +53,11 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; +import org.joda.time.Duration; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; @@ -211,6 +155,7 @@ import com.cloud.agent.api.UnregisterVMCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.ValidateSnapshotAnswer; import com.cloud.agent.api.ValidateSnapshotCommand; +import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.VolumeStatsEntry; import com.cloud.agent.api.check.CheckSshAnswer; @@ -310,6 +255,60 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VmDetailConstants; +import com.google.gson.Gson; +import com.vmware.vim25.AboutInfo; +import com.vmware.vim25.BoolPolicy; +import com.vmware.vim25.ComputeResourceSummary; +import com.vmware.vim25.CustomFieldStringValue; +import com.vmware.vim25.DVPortConfigInfo; +import com.vmware.vim25.DVPortConfigSpec; +import com.vmware.vim25.DasVmPriority; +import com.vmware.vim25.DatastoreSummary; +import com.vmware.vim25.DistributedVirtualPort; +import com.vmware.vim25.DistributedVirtualSwitchPortConnection; +import com.vmware.vim25.DistributedVirtualSwitchPortCriteria; +import com.vmware.vim25.DynamicProperty; +import com.vmware.vim25.GuestInfo; +import com.vmware.vim25.HostCapability; +import com.vmware.vim25.HostHostBusAdapter; +import com.vmware.vim25.HostInternetScsiHba; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.ObjectContent; +import com.vmware.vim25.OptionValue; +import com.vmware.vim25.PerfCounterInfo; +import com.vmware.vim25.PerfEntityMetric; +import com.vmware.vim25.PerfEntityMetricBase; +import com.vmware.vim25.PerfMetricId; +import com.vmware.vim25.PerfMetricIntSeries; +import com.vmware.vim25.PerfMetricSeries; +import com.vmware.vim25.PerfQuerySpec; +import com.vmware.vim25.RuntimeFaultFaultMsg; +import com.vmware.vim25.ToolsUnavailableFaultMsg; +import com.vmware.vim25.VMwareDVSPortSetting; +import com.vmware.vim25.VimPortType; +import com.vmware.vim25.VirtualDevice; +import com.vmware.vim25.VirtualDeviceBackingInfo; +import com.vmware.vim25.VirtualDeviceConfigSpec; +import com.vmware.vim25.VirtualDeviceConfigSpecOperation; +import com.vmware.vim25.VirtualDisk; +import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; +import com.vmware.vim25.VirtualEthernetCard; +import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo; +import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo; +import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo; +import com.vmware.vim25.VirtualMachineConfigSpec; +import com.vmware.vim25.VirtualMachineFileInfo; +import com.vmware.vim25.VirtualMachineFileLayoutEx; +import com.vmware.vim25.VirtualMachineFileLayoutExFileInfo; +import com.vmware.vim25.VirtualMachineGuestOsIdentifier; +import com.vmware.vim25.VirtualMachinePowerState; +import com.vmware.vim25.VirtualMachineRelocateSpec; +import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator; +import com.vmware.vim25.VirtualMachineRuntimeInfo; +import com.vmware.vim25.VirtualMachineToolsStatus; +import com.vmware.vim25.VirtualMachineVideoCard; +import com.vmware.vim25.VirtualUSBController; +import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec; public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService, VirtualRouterDeployer { private static final Logger s_logger = Logger.getLogger(VmwareResource.class); @@ -3469,6 +3468,120 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } protected Answer execute(GetVmDiskStatsCommand cmd) { + try { + final VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); + final ManagedObjectReference perfMgr = getServiceContext().getServiceContent().getPerfManager(); + VimPortType service = getServiceContext().getService(); + + final int intervalSeconds = 300; + final XMLGregorianCalendar startTime = VmwareHelper.getXMLGregorianCalendar(new Date(), intervalSeconds); + final XMLGregorianCalendar endTime = VmwareHelper.getXMLGregorianCalendar(new Date(), 0); + + PerfCounterInfo diskReadIOPerfCounterInfo = null; + PerfCounterInfo diskWriteIOPerfCounterInfo = null; + PerfCounterInfo diskReadKbsPerfCounterInfo = null; + PerfCounterInfo diskWriteKbsPerfCounterInfo = null; + + // https://pubs.vmware.com/vsphere-5-5/topic/com.vmware.wssdk.apiref.doc/virtual_disk_counters.html + List cInfo = getServiceContext().getVimClient().getDynamicProperty(perfMgr, "perfCounter"); + for (PerfCounterInfo info : cInfo) { + if ("virtualdisk".equalsIgnoreCase(info.getGroupInfo().getKey()) && "average".equalsIgnoreCase(info.getRollupType().value())) { + if ("numberReadAveraged".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskReadIOPerfCounterInfo = info; + } + if ("numberWriteAveraged".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskWriteIOPerfCounterInfo = info; + } + if ("read".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskReadKbsPerfCounterInfo = info; + } + if ("write".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskWriteKbsPerfCounterInfo = info; + } + } + } + + final ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter(); + final DatacenterMO dcMo = new DatacenterMO(getServiceContext(), dcMor); + + final HashMap> vmStatsMap = new HashMap<>(); + for (final String vmName : cmd.getVmNames()) { + final VirtualMachineMO vmMo = dcMo.findVm(vmName); + final List diskStats = new ArrayList<>(); + for (final VirtualDisk disk : vmMo.getAllDiskDevice()) { + final String diskBusName = vmMo.getDeviceBusName(vmMo.getAllDeviceList(), disk); + long readReq = 0; + long readBytes = 0; + long writeReq = 0; + long writeBytes = 0; + + final ArrayList perfMetricsIds = new ArrayList(); + if (diskReadIOPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskReadIOPerfCounterInfo, diskBusName)); + } + if (diskWriteIOPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskWriteIOPerfCounterInfo, diskBusName)); + } + if (diskReadKbsPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskReadKbsPerfCounterInfo, diskBusName)); + } + if (diskWriteKbsPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskWriteKbsPerfCounterInfo, diskBusName)); + } + + if (perfMetricsIds.size() > 0) { + final PerfQuerySpec qSpec = new PerfQuerySpec(); + qSpec.setEntity(vmMo.getMor()); + qSpec.setFormat("normal"); + qSpec.setIntervalId(intervalSeconds); + qSpec.setStartTime(startTime); + qSpec.setEndTime(endTime); + qSpec.getMetricId().addAll(perfMetricsIds); + + for (final PerfEntityMetricBase perfValue : service.queryPerf(perfMgr, Collections.singletonList(qSpec))) { + if (!(perfValue instanceof PerfEntityMetric)) { + continue; + } + final List values = ((PerfEntityMetric)perfValue).getValue(); + if (values == null || values.isEmpty()) { + continue; + } + for (final PerfMetricSeries value : values) { + if (!(value instanceof PerfMetricIntSeries) || !value.getId().getInstance().equals(diskBusName)) { + continue; + } + final List perfStats = ((PerfMetricIntSeries)value).getValue(); + if (perfStats.size() > 0) { + long sum = 0; + for (long val : perfStats) { + sum += val; + } + long avg = sum / perfStats.size(); + if (value.getId().getCounterId() == diskReadIOPerfCounterInfo.getKey()) { + readReq = avg; + } else if (value.getId().getCounterId() == diskWriteIOPerfCounterInfo.getKey()) { + writeReq = avg; + } else if (value.getId().getCounterId() == diskReadKbsPerfCounterInfo.getKey()) { + readBytes = avg * 1024; + } else if (value.getId().getCounterId() == diskWriteKbsPerfCounterInfo.getKey()) { + writeBytes = avg * 1024; + } + } + } + } + } + diskStats.add(new VmDiskStatsEntry(vmName, VmwareHelper.getDiskDeviceFileName(disk), writeReq, readReq, writeBytes, readBytes)); + } + if (diskStats.size() > 0) { + vmStatsMap.put(vmName, diskStats); + } + } + if (vmStatsMap.size() > 0) { + return new GetVmDiskStatsAnswer(cmd, "", cmd.getHostName(), vmStatsMap); + } + } catch (Exception e) { + s_logger.error("Unable to execute GetVmDiskStatsCommand due to " + VmwareHelper.getExceptionMessage(e), e); + } return new GetVmDiskStatsAnswer(cmd, null, null, null); } @@ -5857,12 +5970,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa HashMap vmResponseMap = new HashMap(); ManagedObjectReference perfMgr = getServiceContext().getServiceContent().getPerfManager(); VimPortType service = getServiceContext().getService(); + PerfCounterInfo rxPerfCounterInfo = null; PerfCounterInfo txPerfCounterInfo = null; + PerfCounterInfo diskReadIOPerfCounterInfo = null; + PerfCounterInfo diskWriteIOPerfCounterInfo = null; + PerfCounterInfo diskReadKbsPerfCounterInfo = null; + PerfCounterInfo diskWriteKbsPerfCounterInfo = null; + + final int intervalSeconds = 300; + final XMLGregorianCalendar startTime = VmwareHelper.getXMLGregorianCalendar(new Date(), intervalSeconds); + final XMLGregorianCalendar endTime = VmwareHelper.getXMLGregorianCalendar(new Date(), 0); List cInfo = getServiceContext().getVimClient().getDynamicProperty(perfMgr, "perfCounter"); for (PerfCounterInfo info : cInfo) { - if ("net".equalsIgnoreCase(info.getGroupInfo().getKey())) { + if ("net".equalsIgnoreCase(info.getGroupInfo().getKey()) && "average".equalsIgnoreCase(info.getRollupType().value())) { if ("transmitted".equalsIgnoreCase(info.getNameInfo().getKey())) { txPerfCounterInfo = info; } @@ -5870,6 +5992,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa rxPerfCounterInfo = info; } } + if ("virtualdisk".equalsIgnoreCase(info.getGroupInfo().getKey())) { + if ("numberReadAveraged".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskReadIOPerfCounterInfo = info; + } + if ("numberWriteAveraged".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskWriteIOPerfCounterInfo = info; + } + if ("read".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskReadKbsPerfCounterInfo = info; + } + if ("write".equalsIgnoreCase(info.getNameInfo().getKey())) { + diskWriteKbsPerfCounterInfo = info; + } + } } int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); @@ -5885,8 +6021,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa final String memMbStr = "config.hardware.memoryMB"; final String allocatedCpuStr = "summary.runtime.maxCpuUsage"; - ObjectContent[] ocs = - hyperHost.getVmPropertiesOnHyperHost(new String[] {"name", numCpuStr, cpuUseStr ,guestMemUseStr ,memLimitStr ,memMbStr,allocatedCpuStr ,instanceNameCustomField}); + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost(new String[] { + "name", numCpuStr, cpuUseStr, guestMemUseStr, memLimitStr, memMbStr,allocatedCpuStr, instanceNameCustomField + }); if (ocs != null && ocs.length > 0) { for (ObjectContent oc : ocs) { @@ -5923,7 +6060,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } maxCpuUsage = (maxCpuUsage/allocatedCpu)*100; - new VirtualMachineMO(hyperHost.getContext(), oc.getObj()); if (vmInternalCSName != null) { name = vmInternalCSName; } else { @@ -5937,60 +6073,86 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference vmMor = hyperHost.findVmOnHyperHost(name).getMor(); assert (vmMor != null); - ArrayList vmNetworkMetrics = new ArrayList(); - // get all the metrics from the available sample period - List perfMetrics = service.queryAvailablePerfMetric(perfMgr, vmMor, null, null, null); - if (perfMetrics != null) { - for (int index = 0; index < perfMetrics.size(); ++index) { - if (((rxPerfCounterInfo != null) && (perfMetrics.get(index).getCounterId() == rxPerfCounterInfo.getKey())) - || ((txPerfCounterInfo != null) && (perfMetrics.get(index).getCounterId() == txPerfCounterInfo.getKey()))) { - vmNetworkMetrics.add(perfMetrics.get(index)); - } - } - } - double networkReadKBs = 0; double networkWriteKBs = 0; - long sampleDuration = 0; + double diskReadIops = 0; + double diskWriteIops = 0; + double diskReadKbs = 0; + double diskWriteKbs = 0; - if (vmNetworkMetrics.size() != 0) { - PerfQuerySpec qSpec = new PerfQuerySpec(); + final ArrayList perfMetricsIds = new ArrayList(); + if (rxPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(rxPerfCounterInfo, "")); + } + if (txPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(txPerfCounterInfo, "")); + } + if (diskReadIOPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskReadIOPerfCounterInfo, "*")); + } + if (diskWriteIOPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskWriteIOPerfCounterInfo, "*")); + } + if (diskReadKbsPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskReadKbsPerfCounterInfo, "")); + } + if (diskWriteKbsPerfCounterInfo != null) { + perfMetricsIds.add(VmwareHelper.createPerfMetricId(diskWriteKbsPerfCounterInfo, "")); + } + + if (perfMetricsIds.size() > 0) { + final PerfQuerySpec qSpec = new PerfQuerySpec(); qSpec.setEntity(vmMor); - PerfMetricId[] availableMetricIds = vmNetworkMetrics.toArray(new PerfMetricId[0]); - qSpec.getMetricId().addAll(Arrays.asList(availableMetricIds)); - List qSpecs = new ArrayList(); - qSpecs.add(qSpec); - List values = service.queryPerf(perfMgr, qSpecs); - - for (int i = 0; i < values.size(); ++i) { - List infos = ((PerfEntityMetric)values.get(i)).getSampleInfo(); - if (infos != null && infos.size() > 0) { - int endMs = infos.get(infos.size() - 1).getTimestamp().getSecond() * 1000 + infos.get(infos.size() - 1).getTimestamp().getMillisecond(); - int beginMs = infos.get(0).getTimestamp().getSecond() * 1000 + infos.get(0).getTimestamp().getMillisecond(); - sampleDuration = (endMs - beginMs) / 1000; - List vals = ((PerfEntityMetric)values.get(i)).getValue(); - for (int vi = 0; ((vals != null) && (vi < vals.size())); ++vi) { - if (vals.get(vi) instanceof PerfMetricIntSeries) { - PerfMetricIntSeries val = (PerfMetricIntSeries)vals.get(vi); - List perfValues = val.getValue(); - Long sumRate = 0L; - for (int j = 0; j < infos.size(); j++) { // Size of the array matches the size as the PerfSampleInfo - sumRate += perfValues.get(j); - } - Long averageRate = sumRate / infos.size(); - if (vals.get(vi).getId().getCounterId() == rxPerfCounterInfo.getKey()) { - networkReadKBs = sampleDuration * averageRate; //get the average RX rate multiplied by sampled duration - } - if (vals.get(vi).getId().getCounterId() == txPerfCounterInfo.getKey()) { - networkWriteKBs = sampleDuration * averageRate;//get the average TX rate multiplied by sampled duration - } - } + qSpec.setFormat("normal"); + qSpec.setIntervalId(intervalSeconds); + qSpec.setStartTime(startTime); + qSpec.setEndTime(endTime); + qSpec.getMetricId().addAll(perfMetricsIds); + final List perfValues = service.queryPerf(perfMgr, Collections.singletonList(qSpec)); + for (final PerfEntityMetricBase perfValue : perfValues) { + if (!(perfValue instanceof PerfEntityMetric)) { + continue; + } + final List seriesList = ((PerfEntityMetric) perfValue).getValue(); + for (final PerfMetricSeries series : seriesList) { + if (!(series instanceof PerfMetricIntSeries)) { + continue; + } + final List values = ((PerfMetricIntSeries) series).getValue(); + double sum = 0; + for (final Long value : values) { + sum += value; + } + double avg = sum / values.size(); + if (series.getId().getCounterId() == rxPerfCounterInfo.getKey()) { + networkReadKBs = avg; + } + if (series.getId().getCounterId() == txPerfCounterInfo.getKey()) { + networkWriteKBs = avg; + } + if (series.getId().getCounterId() == diskReadIOPerfCounterInfo.getKey()) { + diskReadIops += avg; + } + if (series.getId().getCounterId() == diskWriteIOPerfCounterInfo.getKey()) { + diskWriteIops += avg; + } + if (series.getId().getCounterId() == diskReadKbsPerfCounterInfo.getKey()) { + diskReadKbs = avg; + } + if (series.getId().getCounterId() == diskWriteKbsPerfCounterInfo.getKey()) { + diskWriteKbs = avg; } } } } - vmResponseMap.put(name, new VmStatsEntry( NumberUtils.toDouble(memkb)*1024,NumberUtils.toDouble(guestMemusage)*1024,NumberUtils.toDouble(memlimit)*1024, - maxCpuUsage, networkReadKBs, networkWriteKBs, NumberUtils.toInt(numberCPUs), "vm")); + + final VmStatsEntry vmStats = new VmStatsEntry( NumberUtils.toDouble(memkb)*1024,NumberUtils.toDouble(guestMemusage)*1024,NumberUtils.toDouble(memlimit)*1024, + maxCpuUsage, networkReadKBs, networkWriteKBs, NumberUtils.toInt(numberCPUs), "vm"); + vmStats.setDiskReadIOs(diskReadIops); + vmStats.setDiskWriteIOs(diskWriteIops); + vmStats.setDiskReadKBs(diskReadKbs); + vmStats.setDiskWriteKBs(diskWriteKbs); + vmResponseMap.put(name, vmStats); } } diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmDiskStatsCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmDiskStatsCommandWrapper.java index 04090ce7436..d15e0a71727 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmDiskStatsCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmDiskStatsCommandWrapper.java @@ -33,4 +33,4 @@ public final class CitrixGetVmDiskStatsCommandWrapper extends CommandWrapper volSearch; @@ -102,6 +106,14 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation sc = createSearchCriteriaForHostTypeRoutingStateUpAndNotInMaintenance(); - sc.addAnd("hypervisorType", SearchCriteria.Op.EQ, HypervisorType.KVM); // support KVM only util 2013.06.25 + sc.addAnd("hypervisorType", SearchCriteria.Op.IN, HypervisorType.KVM, HypervisorType.VMware); List hosts = _hostDao.search(sc, null); for (HostVO host : hosts) { List vms = _userVmDao.listRunningByHostId(host.getId()); List vmIds = new ArrayList(); - for (UserVmVO vm : vms) { + for (UserVmVO vm : vms) { if (vm.getType() == VirtualMachine.Type.User) // user vm vmIds.add(vm.getId()); } diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 0727a2a8593..f3731ab6ffe 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -4670,8 +4670,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Override public void collectVmDiskStatistics(final UserVm userVm) { - // support KVM only util 2013.06.25 - if (!userVm.getHypervisorType().equals(HypervisorType.KVM)) { + // Only supported for KVM and VMware + if (!(userVm.getHypervisorType().equals(HypervisorType.KVM) || userVm.getHypervisorType().equals(HypervisorType.VMware))) { return; } s_logger.debug("Collect vm disk statistics from host before stopping Vm"); @@ -6684,4 +6684,4 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } } } -} \ No newline at end of file +} diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js index c3c68e1e233..2784eab2d8d 100644 --- a/ui/scripts/metrics.js +++ b/ui/scripts/metrics.js @@ -607,6 +607,21 @@ }, storage: { label: 'label.metrics.storagepool' + }, + disk: { + label: 'label.metrics.disk.usage', + collapsible: true, + columns: { + diskioread: { + label: 'label.metrics.disk.read' + }, + diskiowrite: { + label: 'label.metrics.disk.write' + }, + diskiopstotal: { + label: 'label.metrics.disk.iops.total' + } + } } }, dataProvider: function(args) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index d9d03d1484a..6a42f7f9aea 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -2709,7 +2709,7 @@ public class VirtualMachineMO extends BaseMO { return pathList; } - private String getDeviceBusName(List allDevices, VirtualDevice theDevice) throws Exception { + public String getDeviceBusName(List allDevices, VirtualDevice theDevice) throws Exception { for (VirtualDevice device : allDevices) { if (device.getKey() == theDevice.getControllerKey().intValue()) { if (device instanceof VirtualIDEController) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index bb7f3c5a140..6477eb1ecee 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -25,11 +25,16 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import java.util.Random; import java.util.UUID; import javax.annotation.Nonnull; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -41,6 +46,8 @@ import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.MethodFault; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.OptionValue; +import com.vmware.vim25.PerfCounterInfo; +import com.vmware.vim25.PerfMetricId; import com.vmware.vim25.ResourceAllocationInfo; import com.vmware.vim25.VirtualCdrom; import com.vmware.vim25.VirtualCdromIsoBackingInfo; @@ -637,6 +644,25 @@ public class VmwareHelper { return usbController; } + public static PerfMetricId createPerfMetricId(PerfCounterInfo counterInfo, String instance) { + PerfMetricId metricId = new PerfMetricId(); + metricId.setCounterId(counterInfo.getKey()); + metricId.setInstance(instance); + return metricId; + } + + public static String getDiskDeviceFileName(VirtualDisk diskDevice) { + VirtualDeviceBackingInfo backingInfo = diskDevice.getBacking(); + if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) { + final String vmdkName = ((VirtualDiskFlatVer2BackingInfo)backingInfo).getFileName().replace(".vmdk", ""); + if (vmdkName.contains("/")) { + return vmdkName.split("/", 2)[1]; + } + return vmdkName; + } + return null; + } + public static ManagedObjectReference getDiskDeviceDatastore(VirtualDisk diskDevice) throws Exception { VirtualDeviceBackingInfo backingInfo = diskDevice.getBacking(); assert (backingInfo instanceof VirtualDiskFlatVer2BackingInfo); @@ -773,4 +799,13 @@ public class VmwareHelper { return DiskControllerType.getType(dataDiskController) == DiskControllerType.osdefault; } + public static XMLGregorianCalendar getXMLGregorianCalendar(final Date date, final int offsetSeconds) throws DatatypeConfigurationException { + if (offsetSeconds > 0) { + date.setTime(date.getTime() - offsetSeconds * 1000); + } + final GregorianCalendar gregorianCalendar = new GregorianCalendar(); + gregorianCalendar.setTime(date); + return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar); + } + }