diff --git a/.travis.yml b/.travis.yml index da81633bb17..b8fbf0af3d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,6 +48,7 @@ env: smoke/test_list_ids_parameter smoke/test_loadbalance smoke/test_login + smoke/test_metrics_api smoke/test_multipleips_per_nic smoke/test_network smoke/test_network_acl diff --git a/api/src/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java index 432ca921c4d..74ad764608c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java @@ -125,18 +125,22 @@ public class ListClustersCmd extends BaseListCmd { return s_name; } - @Override - public void execute() { + protected List getClusterResponses() { Pair, Integer> result = _mgr.searchForClusters(this); - ListResponse response = new ListResponse(); List clusterResponses = new ArrayList(); for (Cluster cluster : result.first()) { ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, showCapacities); clusterResponse.setObjectName("cluster"); clusterResponses.add(clusterResponse); } + return clusterResponses; + } - response.setResponses(clusterResponses, result.second()); + @Override + public void execute() { + List clusterResponses = getClusterResponses(); + ListResponse response = new ListResponse(); + response.setResponses(clusterResponses, clusterResponses.size()); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java index 424fc05aed1..3391fdca1e3 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java @@ -132,6 +132,10 @@ public class ListHostsCmd extends BaseListCmd { return state; } + public void setType(String type) { + this.type = type; + } + public String getType() { return type; } @@ -198,19 +202,16 @@ public class ListHostsCmd extends BaseListCmd { return ApiCommandJobType.Host; } - @Override - public void execute() { - ListResponse response = null; + protected ListResponse getHostResponses() { + ListResponse response = new ListResponse<>(); if (getVirtualMachineId() == null) { response = _queryService.searchForServers(this); } else { Pair, Integer> result; Ternary, Integer>, List, Map> hostsForMigration = - _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); + _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); result = hostsForMigration.first(); List hostsWithCapacity = hostsForMigration.second(); - - response = new ListResponse(); List hostResponses = new ArrayList(); for (Host host : result.first()) { HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails()); @@ -222,9 +223,14 @@ public class ListHostsCmd extends BaseListCmd { hostResponse.setObjectName("host"); hostResponses.add(hostResponse); } - response.setResponses(hostResponses, result.second()); } + return response; + } + + @Override + public void execute() { + ListResponse response = getHostResponses(); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java index ab9c8c37674..90fe800a8bc 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -458,4 +458,163 @@ public class HostResponse extends BaseResponse { } + public String getName() { + return name; + } + + public Status getState() { + return state; + } + + public Date getDisconnectedOn() { + return disconnectedOn; + } + + public Host.Type getHostType() { + return hostType; + } + + public String getOsCategoryId() { + return osCategoryId; + } + + public String getOsCategoryName() { + return osCategoryName; + } + + public String getIpAddress() { + return ipAddress; + } + + public String getZoneId() { + return zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public String getPodId() { + return podId; + } + + public String getPodName() { + return podName; + } + + public String getVersion() { + return version; + } + + public HypervisorType getHypervisor() { + return hypervisor; + } + + public Integer getCpuSockets() { + return cpuSockets; + } + + public Integer getCpuNumber() { + return cpuNumber; + } + + public Long getCpuSpeed() { + return cpuSpeed; + } + + public String getCpuUsed() { + return cpuUsed; + } + + public Long getAverageLoad() { + return averageLoad; + } + + public Long getNetworkKbsRead() { + return networkKbsRead; + } + + public Long getNetworkKbsWrite() { + return networkKbsWrite; + } + + public Long getMemoryTotal() { + return memoryTotal; + } + + public Long getMemoryAllocated() { + return memoryAllocated; + } + + public Long getMemoryUsed() { + return memoryUsed; + } + + public List getGpuGroup() { + return gpuGroup; + } + + public Long getDiskSizeTotal() { + return diskSizeTotal; + } + + public Long getDiskSizeAllocated() { + return diskSizeAllocated; + } + + public String getCapabilities() { + return capabilities; + } + + public Date getLastPinged() { + return lastPinged; + } + + public Long getManagementServerId() { + return managementServerId; + } + + public String getClusterId() { + return clusterId; + } + + public String getClusterName() { + return clusterName; + } + + public String getClusterType() { + return clusterType; + } + + public Boolean getLocalStorageActive() { + return localStorageActive; + } + + public Date getCreated() { + return created; + } + + public Date getRemoved() { + return removed; + } + + public String getEvents() { + return events; + } + + public Boolean getHasEnoughCapacity() { + return hasEnoughCapacity; + } + + public Boolean getSuitableForMigration() { + return suitableForMigration; + } + + public String getHypervisorVersion() { + return hypervisorVersion; + } + + public Boolean getHaHost() { + return haHost; + } } diff --git a/api/src/org/apache/cloudstack/api/response/NicResponse.java b/api/src/org/apache/cloudstack/api/response/NicResponse.java index 73358360a05..7689123cbaf 100644 --- a/api/src/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NicResponse.java @@ -16,15 +16,14 @@ // under the License. package org.apache.cloudstack.api.response; -import java.util.List; - +import com.cloud.serializer.Param; +import com.cloud.vm.Nic; +import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import com.cloud.serializer.Param; -import com.cloud.vm.Nic; -import com.google.gson.annotations.SerializedName; +import java.util.List; @SuppressWarnings("unused") @EntityReference(value = Nic.class) @@ -221,4 +220,79 @@ public class NicResponse extends BaseResponse { this.nsxLogicalSwitchPort = nsxLogicalSwitchPort; } + public String getNetworkId() { + return networkId; + } + + public String getNetworkName() { + return networkName; + } + + public String getNetmask() { + return netmask; + } + + public String getGateway() { + return gateway; + } + + public String getIsolationUri() { + return isolationUri; + } + + public String getBroadcastUri() { + return broadcastUri; + } + + public String getTrafficType() { + return trafficType; + } + + public String getType() { + return type; + } + + public Boolean getDefault() { + return isDefault; + } + + public String getMacAddress() { + return macAddress; + } + + public String getIpaddress() { + return ipaddress; + } + + public String getIp6Gateway() { + return ip6Gateway; + } + + public String getIp6Cidr() { + return ip6Cidr; + } + + public String getIp6Address() { + return ip6Address; + } + + public List getSecondaryIps() { + return secondaryIps; + } + + public String getDeviceId() { + return deviceId; + } + + public String getVmId() { + return vmId; + } + + public String getNsxLogicalSwitch() { + return nsxLogicalSwitch; + } + + public String getNsxLogicalSwitchPort() { + return nsxLogicalSwitchPort; + } } diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 3571866fe74..b7f7d0b41ee 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -309,4 +309,12 @@ public class StoragePoolResponse extends BaseResponse { public void setOverProvisionFactor(String overProvisionFactor) { this.overProvisionFactor = overProvisionFactor; } + + public String getOverProvisionFactor() { + return overProvisionFactor; + } + + public Boolean getSuitableForMigration() { + return suitableForMigration; + } } diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java index b681d4f70df..2ff1eaa717b 100644 --- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java @@ -813,4 +813,28 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co public void setOsTypeId(Long osTypeId) { this.osTypeId = osTypeId; } + + public Set getTagIds() { + return tagIds; + } + + public void setTagIds(Set tagIds) { + this.tagIds = tagIds; + } + + public Map getDetails() { + return details; + } + + public Boolean getDynamicallyScalable() { + return isDynamicallyScalable; + } + + public void setDynamicallyScalable(Boolean dynamicallyScalable) { + isDynamicallyScalable = dynamicallyScalable; + } + + public Long getOsTypeId() { + return osTypeId; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java index a934563e9fe..e25adf618d8 100644 --- a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java @@ -16,18 +16,17 @@ // under the License. package org.apache.cloudstack.api.response; -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; 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 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; @EntityReference(value = Volume.class) @SuppressWarnings("unused") @@ -514,4 +513,140 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co public void setTags(Set tags) { this.tags = tags; } + + public String getName() { + return name; + } + + public String getZoneId() { + return zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public String getVolumeType() { + return volumeType; + } + + public Long getDeviceId() { + return deviceId; + } + + public String getVirtualMachineId() { + return virtualMachineId; + } + + public String getVirtualMachineName() { + return virtualMachineName; + } + + public String getVirtualMachineDisplayName() { + return virtualMachineDisplayName; + } + + public String getVirtualMachineState() { + return virtualMachineState; + } + + public String getProvisioningType() { + return provisioningType; + } + + public Long getSize() { + return size; + } + + public Long getMinIops() { + return minIops; + } + + public Long getMaxIops() { + return maxIops; + } + + public Date getCreated() { + return created; + } + + public String getState() { + return state; + } + + public String getAccountName() { + return accountName; + } + + public String getProjectId() { + return projectId; + } + + public String getProjectName() { + return projectName; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public String getStorageType() { + return storageType; + } + + public String getHypervisor() { + return hypervisor; + } + + public String getDiskOfferingId() { + return diskOfferingId; + } + + public String getDiskOfferingName() { + return diskOfferingName; + } + + public String getDiskOfferingDisplayText() { + return diskOfferingDisplayText; + } + + public String getStoragePoolName() { + return storagePoolName; + } + + public String getSnapshotId() { + return snapshotId; + } + + public Date getAttached() { + return attached; + } + + public String getServiceOfferingId() { + return serviceOfferingId; + } + + public String getServiceOfferingName() { + return serviceOfferingName; + } + + public String getServiceOfferingDisplayText() { + return serviceOfferingDisplayText; + } + + public Boolean getExtractable() { + return extractable; + } + + public String getStatus() { + return status; + } + + public Boolean getDisplayVolume() { + return displayVolume; + } } diff --git a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java index 4266077e813..61bab02d321 100644 --- a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java @@ -239,4 +239,92 @@ public class ZoneResponse extends BaseResponse { } this.resourceDetails = new HashMap<>(details); } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getDns1() { + return dns1; + } + + public String getDns2() { + return dns2; + } + + public String getInternalDns1() { + return internalDns1; + } + + public String getInternalDns2() { + return internalDns2; + } + + public String getGuestCidrAddress() { + return guestCidrAddress; + } + + public String getStatus() { + return status; + } + + public String getDisplayText() { + return displayText; + } + + public String getDomain() { + return domain; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public String getNetworkType() { + return networkType; + } + + public boolean isSecurityGroupsEnabled() { + return securityGroupsEnabled; + } + + public String getAllocationState() { + return allocationState; + } + + public String getZoneToken() { + return zoneToken; + } + + public String getDhcpProvider() { + return dhcpProvider; + } + + public List getCapacitites() { + return capacitites; + } + + public boolean isLocalStorageEnabled() { + return localStorageEnabled; + } + + public Set getTags() { + return tags; + } + + public Map getResourceDetails() { + return resourceDetails; + } } diff --git a/client/pom.xml b/client/pom.xml index d5ddd65e925..1f246ffb0ec 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -101,6 +101,11 @@ cloud-plugin-user-authenticator-sha256salted ${project.version} + + org.apache.cloudstack + cloud-plugin-metrics + ${project.version} + org.apache.cloudstack cloud-plugin-network-nvp diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java index 06bc5a3afc6..de8d604fb4c 100644 --- a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java +++ b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java @@ -16,13 +16,13 @@ // under the License. package com.cloud.dc.dao; -import java.util.List; -import java.util.Map; - import com.cloud.dc.ClusterVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.GenericDao; +import java.util.List; +import java.util.Map; + public interface ClusterDao extends GenericDao { List listByPodId(long podId); @@ -44,7 +44,7 @@ public interface ClusterDao extends GenericDao { List listClustersByDcId(long zoneId); - List listAllCusters(long zoneId); + List listAllClusters(Long zoneId); boolean getSupportsResigning(long clusterId); } diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java index 0c5bd6f4a79..b1fce6195ba 100644 --- a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java +++ b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java @@ -16,18 +16,6 @@ // under the License. package com.cloud.dc.dao; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; - -import org.springframework.stereotype.Component; - import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; import com.cloud.dc.ClusterVO; @@ -43,6 +31,16 @@ import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.exception.CloudRuntimeException; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Component public class ClusterDaoImpl extends GenericDaoBase implements ClusterDao { @@ -259,9 +257,11 @@ public class ClusterDaoImpl extends GenericDaoBase implements C } @Override - public List listAllCusters(long zoneId) { + public List listAllClusters(Long zoneId) { SearchCriteria sc = ClusterIdSearch.create(); - sc.setParameters("dataCenterId", zoneId); + if (zoneId != null) { + sc.setParameters("dataCenterId", zoneId); + } return customSearch(sc, null); } diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDao.java b/engine/schema/src/com/cloud/dc/dao/HostPodDao.java index 39c8a499192..1a000d8830c 100644 --- a/engine/schema/src/com/cloud/dc/dao/HostPodDao.java +++ b/engine/schema/src/com/cloud/dc/dao/HostPodDao.java @@ -31,5 +31,5 @@ public interface HostPodDao extends GenericDao { public List listDisabledPods(long zoneId); - public List listAllPods(long zoneId); + public List listAllPods(Long zoneId); } diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java index 8d689e3a4a8..1c83b3a4a78 100644 --- a/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java +++ b/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java @@ -130,9 +130,11 @@ public class HostPodDaoImpl extends GenericDaoBase implements H } @Override - public List listAllPods(long zoneId) { + public List listAllPods(Long zoneId) { SearchCriteria sc = PodIdSearch.create(); - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); + if (zoneId != null) { + sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId); + } return customSearch(sc, null); } } diff --git a/plugins/metrics/pom.xml b/plugins/metrics/pom.xml new file mode 100644 index 00000000000..946b235dcd4 --- /dev/null +++ b/plugins/metrics/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + cloud-plugin-metrics + Apache CloudStack Plugin - Metrics + + org.apache.cloudstack + cloudstack-plugins + 4.9.3.0-SNAPSHOT + ../pom.xml + + + + org.apache.cloudstack + cloud-api + ${project.version} + + + org.apache.cloudstack + cloud-utils + ${project.version} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xmx1024m + + + + + diff --git a/plugins/metrics/resources/META-INF/cloudstack/metrics/module.properties b/plugins/metrics/resources/META-INF/cloudstack/metrics/module.properties new file mode 100644 index 00000000000..149b83afde1 --- /dev/null +++ b/plugins/metrics/resources/META-INF/cloudstack/metrics/module.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +name=metrics +parent=api diff --git a/plugins/metrics/resources/META-INF/cloudstack/metrics/spring-metrics-context.xml b/plugins/metrics/resources/META-INF/cloudstack/metrics/spring-metrics-context.xml new file mode 100644 index 00000000000..65846417e11 --- /dev/null +++ b/plugins/metrics/resources/META-INF/cloudstack/metrics/spring-metrics-context.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListClustersMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListClustersMetricsCmd.java new file mode 100644 index 00000000000..ef259e19a73 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListClustersMetricsCmd.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.ClusterMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListClustersMetricsCmd.APINAME, description = "Lists clusters metrics", responseObject = ClusterMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin}) +public class ListClustersMetricsCmd extends ListClustersCmd { + public static final String APINAME = "listClustersMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + final List metricsResponses = metricsService.listClusterMetrics(getClusterResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListHostsMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListHostsMetricsCmd.java new file mode 100644 index 00000000000..90100631d6b --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListHostsMetricsCmd.java @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + + +import com.cloud.host.Host; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.HostMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListHostsMetricsCmd.APINAME, description = "Lists hosts metrics", responseObject = HostMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin}) +public class ListHostsMetricsCmd extends ListHostsCmd { + public static final String APINAME = "listHostsMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + setType(Host.Type.Routing.toString()); + final List metricsResponses = metricsService.listHostMetrics(getHostResponses().getResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListInfrastructureCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListInfrastructureCmd.java new file mode 100644 index 00000000000..4ea24c3f66b --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListInfrastructureCmd.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.InfrastructureResponse; + +import javax.inject.Inject; + +@APICommand(name = ListInfrastructureCmd.APINAME, description = "Lists infrastructure", responseObject = InfrastructureResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin}) +public class ListInfrastructureCmd extends BaseCmd { + public static final String APINAME = "listInfrastructure"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccountId(); + } + + @Override + public void execute() { + final InfrastructureResponse response = metricsService.listInfrastructure(); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListStoragePoolsMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListStoragePoolsMetricsCmd.java new file mode 100644 index 00000000000..420656800fa --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListStoragePoolsMetricsCmd.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.StoragePoolMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListStoragePoolsMetricsCmd.APINAME, description = "Lists storage pool metrics", responseObject = StoragePoolMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin}) +public class ListStoragePoolsMetricsCmd extends ListStoragePoolsCmd { + public static final String APINAME = "listStoragePoolsMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + final List metricsResponses = metricsService.listStoragePoolMetrics(_queryService.searchForStoragePools(this).getResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListVMsMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListVMsMetricsCmd.java new file mode 100644 index 00000000000..2321f519472 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListVMsMetricsCmd.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.admin.vm.ListVMsCmdByAdmin; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.VmMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListVMsMetricsCmd.APINAME, description = "Lists VM metrics", responseObject = VmMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class ListVMsMetricsCmd extends ListVMsCmdByAdmin { + public static final String APINAME = "listVirtualMachinesMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + final List metricsResponses = metricsService.listVmMetrics(_queryService.searchForUserVMs(this).getResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListVolumesMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListVolumesMetricsCmd.java new file mode 100644 index 00000000000..54ac92226ae --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListVolumesMetricsCmd.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.VolumeMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListVolumesMetricsCmd.APINAME, description = "Lists volume metrics", responseObject = VolumeMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class ListVolumesMetricsCmd extends ListVolumesCmdByAdmin { + public static final String APINAME = "listVolumesMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + final List metricsResponses = metricsService.listVolumeMetrics(_queryService.searchForVolumes(this).getResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/api/ListZonesMetricsCmd.java b/plugins/metrics/src/org/apache/cloudstack/api/ListZonesMetricsCmd.java new file mode 100644 index 00000000000..1a51a5fbe00 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/api/ListZonesMetricsCmd.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.command.user.zone.ListZonesCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.metrics.MetricsService; +import org.apache.cloudstack.response.ZoneMetricsResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = ListZonesMetricsCmd.APINAME, description = "Lists zone metrics", responseObject = ZoneMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Full, + since = "4.9.3", authorized = {RoleType.Admin}) +public class ListZonesMetricsCmd extends ListZonesCmd { + public static final String APINAME = "listZonesMetrics"; + + @Inject + private MetricsService metricsService; + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public void execute() { + final List metricsResponses = metricsService.listZoneMetrics(_queryService.listDataCenters(this).getResponses()); + ListResponse response = new ListResponse<>(); + response.setResponses(metricsResponses, metricsResponses.size()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + +} diff --git a/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsService.java b/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsService.java new file mode 100644 index 00000000000..deb1da89c9f --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsService.java @@ -0,0 +1,46 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.metrics; + +import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.response.ClusterMetricsResponse; +import org.apache.cloudstack.response.HostMetricsResponse; +import org.apache.cloudstack.response.InfrastructureResponse; +import org.apache.cloudstack.response.StoragePoolMetricsResponse; +import org.apache.cloudstack.response.VmMetricsResponse; +import org.apache.cloudstack.response.VolumeMetricsResponse; +import org.apache.cloudstack.response.ZoneMetricsResponse; + +import java.util.List; + +public interface MetricsService extends PluggableService { + InfrastructureResponse listInfrastructure(); + + List listVolumeMetrics(List volumeResponses); + List listVmMetrics(List vmResponses); + List listStoragePoolMetrics(List poolResponses); + List listHostMetrics(List poolResponses); + List listClusterMetrics(List poolResponses); + List listZoneMetrics(List poolResponses); +} diff --git a/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsServiceImpl.java new file mode 100644 index 00000000000..5cab7bcf19c --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -0,0 +1,563 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.metrics; + +import com.cloud.alert.AlertManager; +import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.HostJoinDao; +import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.capacity.Capacity; +import com.cloud.capacity.CapacityManager; +import com.cloud.capacity.dao.CapacityDao; +import com.cloud.capacity.dao.CapacityDaoImpl; +import com.cloud.dc.DataCenter; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.deploy.DeploymentClusterPlanner; +import com.cloud.host.Host; +import com.cloud.host.HostStats; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.org.Cluster; +import com.cloud.org.Grouping; +import com.cloud.org.Managed; +import com.cloud.utils.component.ComponentLifecycleBase; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ListClustersMetricsCmd; +import org.apache.cloudstack.api.ListHostsMetricsCmd; +import org.apache.cloudstack.api.ListInfrastructureCmd; +import org.apache.cloudstack.api.ListStoragePoolsMetricsCmd; +import org.apache.cloudstack.api.ListVMsMetricsCmd; +import org.apache.cloudstack.api.ListVolumesMetricsCmd; +import org.apache.cloudstack.api.ListZonesMetricsCmd; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.response.ClusterMetricsResponse; +import org.apache.cloudstack.response.HostMetricsResponse; +import org.apache.cloudstack.response.InfrastructureResponse; +import org.apache.cloudstack.response.StoragePoolMetricsResponse; +import org.apache.cloudstack.response.VmMetricsResponse; +import org.apache.cloudstack.response.VolumeMetricsResponse; +import org.apache.cloudstack.response.ZoneMetricsResponse; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.commons.beanutils.BeanUtils; + +import javax.inject.Inject; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +public class MetricsServiceImpl extends ComponentLifecycleBase implements MetricsService { + + @Inject + private DataCenterDao dataCenterDao; + @Inject + private HostPodDao podDao; + @Inject + private ClusterDao clusterDao; + @Inject + private HostDao hostDao; + @Inject + private HostJoinDao hostJoinDao; + @Inject + private PrimaryDataStoreDao storagePoolDao; + @Inject + private ImageStoreDao imageStoreDao; + @Inject + private VMInstanceDao vmInstanceDao; + @Inject + private DomainRouterDao domainRouterDao; + @Inject + private CapacityDao capacityDao; + + protected MetricsServiceImpl() { + super(); + } + + private Double findRatioValue(final String value) { + if (value != null) { + return Double.valueOf(value); + } + return 1.0; + } + + private void updateHostMetrics(final Metrics metrics, final HostJoinVO host) { + metrics.incrTotalHosts(); + metrics.addCpuAllocated(host.getCpuReservedCapacity() + host.getCpuUsedCapacity()); + metrics.addMemoryAllocated(host.getMemReservedCapacity() + host.getMemUsedCapacity()); + final HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId()); + if (hostStats != null) { + metrics.addCpuUsedPercentage(hostStats.getCpuUtilization()); + metrics.addMemoryUsed((long) hostStats.getUsedMemory()); + metrics.setMaximumCpuUsage(hostStats.getCpuUtilization()); + metrics.setMaximumMemoryUsage((long) hostStats.getUsedMemory()); + } + } + + @Override + public InfrastructureResponse listInfrastructure() { + final InfrastructureResponse response = new InfrastructureResponse(); + response.setZones(dataCenterDao.listAllZones().size()); + response.setPods(podDao.listAllPods(null).size()); + response.setClusters(clusterDao.listAllClusters(null).size()); + response.setHosts(hostDao.listByType(Host.Type.Routing).size()); + response.setStoragePools(storagePoolDao.listAll().size()); + response.setImageStores(imageStoreDao.listImageStores().size()); + response.setSystemvms(vmInstanceDao.listByTypes(VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm).size()); + response.setRouters(domainRouterDao.listAll().size()); + int cpuSockets = 0; + for (final Host host : hostDao.listByType(Host.Type.Routing)) { + if (host.getCpuSockets() != null) { + cpuSockets += host.getCpuSockets(); + } + } + response.setCpuSockets(cpuSockets); + return response; + } + + @Override + public List listVolumeMetrics(List volumeResponses) { + final List metricsResponses = new ArrayList<>(); + for (final VolumeResponse volumeResponse: volumeResponses) { + VolumeMetricsResponse metricsResponse = new VolumeMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, volumeResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate volume metrics response"); + } + + metricsResponse.setDiskSizeGB(volumeResponse.getSize()); + metricsResponse.setStorageType(volumeResponse.getStorageType(), volumeResponse.getVolumeType()); + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + @Override + public List listVmMetrics(List vmResponses) { + final List metricsResponses = new ArrayList<>(); + for (final UserVmResponse vmResponse: vmResponses) { + VmMetricsResponse metricsResponse = new VmMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, vmResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate vm metrics response"); + } + + metricsResponse.setIpAddress(vmResponse.getNics()); + metricsResponse.setCpuTotal(vmResponse.getCpuNumber(), vmResponse.getCpuSpeed()); + metricsResponse.setMemTotal(vmResponse.getMemory()); + metricsResponse.setNetworkRead(vmResponse.getNetworkKbsRead()); + metricsResponse.setNetworkWrite(vmResponse.getNetworkKbsWrite()); + metricsResponse.setDiskRead(vmResponse.getDiskKbsRead()); + metricsResponse.setDiskWrite(vmResponse.getDiskKbsWrite()); + metricsResponse.setDiskIopsTotal(vmResponse.getDiskIORead(), vmResponse.getDiskIOWrite()); + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + @Override + public List listStoragePoolMetrics(List poolResponses) { + final List metricsResponses = new ArrayList<>(); + for (final StoragePoolResponse poolResponse: poolResponses) { + StoragePoolMetricsResponse metricsResponse = new StoragePoolMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, poolResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate storagepool metrics response"); + } + + Long poolClusterId = null; + final Cluster cluster = clusterDao.findByUuid(poolResponse.getClusterId()); + if (cluster != null) { + poolClusterId = cluster.getId(); + } + final Double storageThreshold = AlertManager.StorageCapacityThreshold.valueIn(poolClusterId); + final Double storageDisableThreshold = CapacityManager.StorageCapacityDisableThreshold.valueIn(poolClusterId); + + metricsResponse.setDiskSizeUsedGB(poolResponse.getDiskSizeUsed()); + metricsResponse.setDiskSizeTotalGB(poolResponse.getDiskSizeTotal(), poolResponse.getOverProvisionFactor()); + metricsResponse.setDiskSizeAllocatedGB(poolResponse.getDiskSizeAllocated()); + metricsResponse.setDiskSizeUnallocatedGB(poolResponse.getDiskSizeTotal(), poolResponse.getDiskSizeAllocated(), poolResponse.getOverProvisionFactor()); + metricsResponse.setStorageUsedThreshold(poolResponse.getDiskSizeTotal(), poolResponse.getDiskSizeUsed(), poolResponse.getOverProvisionFactor(), storageThreshold); + metricsResponse.setStorageUsedDisableThreshold(poolResponse.getDiskSizeTotal(), poolResponse.getDiskSizeUsed(), poolResponse.getOverProvisionFactor(), storageDisableThreshold); + metricsResponse.setStorageAllocatedThreshold(poolResponse.getDiskSizeTotal(), poolResponse.getDiskSizeAllocated(), poolResponse.getOverProvisionFactor(), storageThreshold); + metricsResponse.setStorageAllocatedDisableThreshold(poolResponse.getDiskSizeTotal(), poolResponse.getDiskSizeUsed(), poolResponse.getOverProvisionFactor(), storageDisableThreshold); + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + @Override + public List listHostMetrics(List hostResponses) { + final List metricsResponses = new ArrayList<>(); + for (final HostResponse hostResponse: hostResponses) { + HostMetricsResponse metricsResponse = new HostMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, hostResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate host metrics response"); + } + + final Host host = hostDao.findByUuid(hostResponse.getId()); + if (host == null) { + continue; + } + final Long hostId = host.getId(); + final Long clusterId = host.getClusterId(); + + // Thresholds + final Double cpuThreshold = AlertManager.CPUCapacityThreshold.valueIn(clusterId); + final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId); + final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId); + final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.valueIn(clusterId); + // Over commit ratios + final Double cpuOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "cpuOvercommitRatio")); + final Double memoryOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "memoryOvercommitRatio")); + + Long upInstances = 0L; + Long totalInstances = 0L; + for (final VMInstanceVO instance: vmInstanceDao.listByHostId(hostId)) { + if (instance == null) { + continue; + } + if (instance.getType() == VirtualMachine.Type.User) { + totalInstances++; + if (instance.getState() == VirtualMachine.State.Running) { + upInstances++; + } + } + } + metricsResponse.setPowerState(hostResponse.getOutOfBandManagementResponse().getPowerState()); + metricsResponse.setInstances(upInstances, totalInstances); + metricsResponse.setCpuTotal(hostResponse.getCpuNumber(), hostResponse.getCpuSpeed(), cpuOvercommitRatio); + metricsResponse.setCpuUsed(hostResponse.getCpuUsed(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); + metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); + metricsResponse.setMemTotal(hostResponse.getMemoryTotal(), memoryOvercommitRatio); + metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated()); + metricsResponse.setMemUsed(hostResponse.getMemoryUsed()); + metricsResponse.setNetworkRead(hostResponse.getNetworkKbsRead()); + metricsResponse.setNetworkWrite(hostResponse.getNetworkKbsWrite()); + // CPU thresholds + metricsResponse.setCpuUsageThreshold(hostResponse.getCpuUsed(), cpuThreshold); + metricsResponse.setCpuUsageDisableThreshold(hostResponse.getCpuUsed(), cpuDisableThreshold); + metricsResponse.setCpuAllocatedThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuThreshold); + metricsResponse.setCpuAllocatedDisableThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuDisableThreshold); + // Memory thresholds + metricsResponse.setMemoryUsageThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryThreshold); + metricsResponse.setMemoryUsageDisableThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryDisableThreshold); + metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryThreshold); + metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryDisableThreshold); + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + private CapacityDaoImpl.SummedCapacity getCapacity(final int capacityType, final Long zoneId, final Long clusterId) { + final List capacities = capacityDao.findCapacityBy(capacityType, zoneId, null, clusterId); + if (capacities == null || capacities.size() < 1) { + return null; + } + return capacities.get(0); + } + + @Override + public List listClusterMetrics(List clusterResponses) { + final List metricsResponses = new ArrayList<>(); + for (final ClusterResponse clusterResponse: clusterResponses) { + ClusterMetricsResponse metricsResponse = new ClusterMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, clusterResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate cluster metrics response"); + } + + final Cluster cluster = clusterDao.findByUuid(clusterResponse.getId()); + if (cluster == null) { + continue; + } + final Long clusterId = cluster.getId(); + + // Thresholds + final Double cpuThreshold = AlertManager.CPUCapacityThreshold.valueIn(clusterId); + final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId); + final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId); + final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.valueIn(clusterId); + + final Double cpuOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "cpuOvercommitRatio")); + final Double memoryOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "memoryOvercommitRatio")); + + // CPU and memory capacities + final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, null, clusterId); + final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, null, clusterId); + final Metrics metrics = new Metrics(cpuCapacity, memoryCapacity); + + for (final HostJoinVO host: hostJoinDao.findByClusterId(clusterId, Host.Type.Routing)) { + if (host.getStatus() == Status.Up) { + metrics.incrUpResources(); + } + metrics.incrTotalResources(); + updateHostMetrics(metrics, host); + } + + metricsResponse.setState(clusterResponse.getAllocationState(), clusterResponse.getManagedState()); + metricsResponse.setResources(metrics.getUpResources(), metrics.getTotalResources()); + // CPU + metricsResponse.setCpuTotal(metrics.getTotalCpu()); + metricsResponse.setCpuAllocated(metrics.getCpuAllocated(), metrics.getTotalCpu()); + if (metrics.getCpuUsedPercentage() > 0L) { + metricsResponse.setCpuUsed(metrics.getCpuUsedPercentage(), metrics.getTotalHosts()); + metricsResponse.setCpuMaxDeviation(metrics.getMaximumCpuUsage(), metrics.getCpuUsedPercentage(), metrics.getTotalHosts()); + } + // Memory + metricsResponse.setMemTotal(metrics.getTotalMemory()); + metricsResponse.setMemAllocated(metrics.getMemoryAllocated(), metrics.getTotalMemory()); + if (metrics.getMemoryUsed() > 0L) { + metricsResponse.setMemUsed(metrics.getMemoryUsed(), metrics.getTotalMemory()); + metricsResponse.setMemMaxDeviation(metrics.getMaximumMemoryUsage(), metrics.getMemoryUsed(), metrics.getTotalHosts()); + } + // CPU thresholds + metricsResponse.setCpuUsageThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuThreshold); + metricsResponse.setCpuUsageDisableThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuDisableThreshold); + metricsResponse.setCpuAllocatedThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuOvercommitRatio, cpuThreshold); + metricsResponse.setCpuAllocatedDisableThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuOvercommitRatio, cpuDisableThreshold); + // Memory thresholds + metricsResponse.setMemoryUsageThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryThreshold); + metricsResponse.setMemoryUsageDisableThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryDisableThreshold); + metricsResponse.setMemoryAllocatedThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryOvercommitRatio, memoryThreshold); + metricsResponse.setMemoryAllocatedDisableThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryOvercommitRatio, memoryDisableThreshold); + + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + @Override + public List listZoneMetrics(List zoneResponses) { + final List metricsResponses = new ArrayList<>(); + for (final ZoneResponse zoneResponse: zoneResponses) { + ZoneMetricsResponse metricsResponse = new ZoneMetricsResponse(); + + try { + BeanUtils.copyProperties(metricsResponse, zoneResponse); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate zone metrics response"); + } + + final DataCenter zone = dataCenterDao.findByUuid(zoneResponse.getId()); + if (zone == null) { + continue; + } + final Long zoneId = zone.getId(); + + // Thresholds + final Double cpuThreshold = AlertManager.CPUCapacityThreshold.value(); + final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.value(); + final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.value(); + final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.value(); + + // CPU and memory capacities + final CapacityDaoImpl.SummedCapacity cpuCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_CPU, zoneId, null); + final CapacityDaoImpl.SummedCapacity memoryCapacity = getCapacity((int) Capacity.CAPACITY_TYPE_MEMORY, zoneId, null); + final Metrics metrics = new Metrics(cpuCapacity, memoryCapacity); + + for (final Cluster cluster : clusterDao.listClustersByDcId(zoneId)) { + metrics.incrTotalResources(); + if (cluster.getAllocationState() == Grouping.AllocationState.Enabled + && cluster.getManagedState() == Managed.ManagedState.Managed) { + metrics.incrUpResources(); + } + + for (final HostJoinVO host: hostJoinDao.findByClusterId(cluster.getId(), Host.Type.Routing)) { + updateHostMetrics(metrics, host); + } + } + + metricsResponse.setState(zoneResponse.getAllocationState()); + metricsResponse.setResource(metrics.getUpResources(), metrics.getTotalResources()); + // CPU + metricsResponse.setCpuTotal(metrics.getTotalCpu()); + metricsResponse.setCpuAllocated(metrics.getCpuAllocated(), metrics.getTotalCpu()); + if (metrics.getCpuUsedPercentage() > 0L) { + metricsResponse.setCpuUsed(metrics.getCpuUsedPercentage(), metrics.getTotalHosts()); + metricsResponse.setCpuMaxDeviation(metrics.getMaximumCpuUsage(), metrics.getCpuUsedPercentage(), metrics.getTotalHosts()); + } + // Memory + metricsResponse.setMemTotal(metrics.getTotalMemory()); + metricsResponse.setMemAllocated(metrics.getMemoryAllocated(), metrics.getTotalMemory()); + if (metrics.getMemoryUsed() > 0L) { + metricsResponse.setMemUsed(metrics.getMemoryUsed(), metrics.getTotalMemory()); + metricsResponse.setMemMaxDeviation(metrics.getMaximumMemoryUsage(), metrics.getMemoryUsed(), metrics.getTotalHosts()); + } + // CPU thresholds + metricsResponse.setCpuUsageThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuThreshold); + metricsResponse.setCpuUsageDisableThreshold(metrics.getCpuUsedPercentage(), metrics.getTotalHosts(), cpuDisableThreshold); + metricsResponse.setCpuAllocatedThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuThreshold); + metricsResponse.setCpuAllocatedDisableThreshold(metrics.getCpuAllocated(), metrics.getTotalCpu(), cpuDisableThreshold); + // Memory thresholds + metricsResponse.setMemoryUsageThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryThreshold); + metricsResponse.setMemoryUsageDisableThreshold(metrics.getMemoryUsed(), metrics.getTotalMemory(), memoryDisableThreshold); + metricsResponse.setMemoryAllocatedThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryThreshold); + metricsResponse.setMemoryAllocatedDisableThreshold(metrics.getMemoryAllocated(), metrics.getTotalMemory(), memoryDisableThreshold); + + metricsResponses.add(metricsResponse); + } + return metricsResponses; + } + + @Override + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(ListInfrastructureCmd.class); + cmdList.add(ListVolumesMetricsCmd.class); + cmdList.add(ListVMsMetricsCmd.class); + cmdList.add(ListStoragePoolsMetricsCmd.class); + cmdList.add(ListHostsMetricsCmd.class); + cmdList.add(ListClustersMetricsCmd.class); + cmdList.add(ListZonesMetricsCmd.class); + return cmdList; + } + + private class Metrics { + // CPU metrics + private Long totalCpu = 0L; + private Long cpuAllocated = 0L; + private Double cpuUsedPercentage = 0.0; + private Double maximumCpuUsage = 0.0; + // Memory metrics + private Long totalMemory = 0L; + private Long memoryUsed = 0L; + private Long memoryAllocated = 0L; + private Long maximumMemoryUsage = 0L; + // Counters + private Long totalHosts = 0L; + private Long totalResources = 0L; + private Long upResources = 0L; + + public Metrics(final CapacityDaoImpl.SummedCapacity totalCpu, final CapacityDaoImpl.SummedCapacity totalMemory) { + if (totalCpu != null) { + this.totalCpu = totalCpu.getTotalCapacity(); + } + if (totalMemory != null) { + this.totalMemory = totalMemory.getTotalCapacity(); + } + } + + public void addCpuAllocated(Long cpuAllocated) { + this.cpuAllocated += cpuAllocated; + } + + public void addCpuUsedPercentage(Double cpuUsedPercentage) { + this.cpuUsedPercentage += cpuUsedPercentage; + } + + public void setMaximumCpuUsage(Double maximumCpuUsage) { + if (this.maximumCpuUsage == null || (maximumCpuUsage != null && maximumCpuUsage > this.maximumCpuUsage)) { + this.maximumCpuUsage = maximumCpuUsage; + } + } + + public void addMemoryUsed(Long memoryUsed) { + this.memoryUsed += memoryUsed; + } + + public void addMemoryAllocated(Long memoryAllocated) { + this.memoryAllocated += memoryAllocated; + } + + public void setMaximumMemoryUsage(Long maximumMemoryUsage) { + if (this.maximumMemoryUsage == null || (maximumMemoryUsage != null && maximumMemoryUsage > this.maximumMemoryUsage)) { + this.maximumMemoryUsage = maximumMemoryUsage; + } + } + + public void incrTotalHosts() { + this.totalHosts++; + } + + public void incrTotalResources() { + this.totalResources++; + } + + public void incrUpResources() { + this.upResources++; + } + + public Long getTotalCpu() { + return totalCpu; + } + + public Long getCpuAllocated() { + return cpuAllocated; + } + + public Double getCpuUsedPercentage() { + return cpuUsedPercentage; + } + + public Double getMaximumCpuUsage() { + return maximumCpuUsage; + } + + public Long getTotalMemory() { + return totalMemory; + } + + public Long getMemoryUsed() { + return memoryUsed; + } + + public Long getMemoryAllocated() { + return memoryAllocated; + } + + public Long getMaximumMemoryUsage() { + return maximumMemoryUsage; + } + + public Long getTotalHosts() { + return totalHosts; + } + + public Long getTotalResources() { + return totalResources; + } + + public Long getUpResources() { + return upResources; + } + } + +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/ClusterMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/ClusterMetricsResponse.java new file mode 100644 index 00000000000..dde1ab76327 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/ClusterMetricsResponse.java @@ -0,0 +1,211 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.response.ClusterResponse; + +public class ClusterMetricsResponse extends ClusterResponse { + @SerializedName("state") + @Param(description = "state of the cluster") + private String state; + + @SerializedName("hosts") + @Param(description = "running / total hosts in the cluster") + private String resources; + + @SerializedName("cputotal") + @Param(description = "the total cpu capacity in Ghz") + private String cpuTotal; + + @SerializedName("cpuused") + @Param(description = "the total cpu used in Ghz") + private String cpuUsed; + + @SerializedName("cpuallocated") + @Param(description = "the total cpu allocated in Ghz") + private String cpuAllocated; + + @SerializedName("cpumaxdeviation") + @Param(description = "the maximum cpu deviation") + private String cpuMaxDeviation; + + @SerializedName("memorytotal") + @Param(description = "the total cpu capacity in GiB") + private String memTotal; + + @SerializedName("memoryused") + @Param(description = "the total cpu used in GiB") + private String memUsed; + + @SerializedName("memoryallocated") + @Param(description = "the total cpu allocated in GiB") + private String memAllocated; + + @SerializedName("memorymaxdeviation") + @Param(description = "the maximum memory deviation") + private String memMaxDeviation; + + @SerializedName("cputhreshold") + @Param(description = "cpu usage notification threshold exceeded") + private Boolean cpuThresholdExceeded; + + @SerializedName("cpudisablethreshold") + @Param(description = "cpu usage disable threshold exceeded") + private Boolean cpuDisableThresholdExceeded; + + @SerializedName("cpuallocatedthreshold") + @Param(description = "cpu allocated notification threshold exceeded") + private Boolean cpuAllocatedThresholdExceeded; + + @SerializedName("cpuallocateddisablethreshold") + @Param(description = "cpu allocated disable threshold exceeded") + private Boolean cpuAllocatedDisableThresholdExceeded; + + @SerializedName("memorythreshold") + @Param(description = "memory usage notification threshold exceeded") + private Boolean memoryThresholdExceeded; + + @SerializedName("memorydisablethreshold") + @Param(description = "memory usage disable threshold exceeded") + private Boolean memoryDisableThresholdExceeded; + + @SerializedName("memoryallocatedthreshold") + @Param(description = "memory allocated notification threshold exceeded") + private Boolean memoryAllocatedThresholdExceeded; + + @SerializedName("memoryallocateddisablethreshold") + @Param(description = "memory allocated disable threshold exceeded") + private Boolean memoryAllocatedDisableThresholdExceeded; + + public void setState(final String allocationState, final String managedState) { + this.state = allocationState; + if (managedState.equals("Unmanaged")) { + this.state = managedState; + } + if (managedState.equals("Managed")) { + this.state = allocationState; + } + } + + public void setResources(final Long upResources, final Long totalResources) { + if (upResources != null && totalResources != null) { + this.resources = String.format("%d / %d", upResources, totalResources); + } + } + + public void setCpuTotal(final Long cpuTotal) { + if (cpuTotal != null) { + this.cpuTotal = String.format("%.2f Ghz", cpuTotal / 1000.0); + } + } + + public void setCpuUsed(final Double cpuUsedPercentage, final Long totalHosts) { + if (cpuUsedPercentage != null && totalHosts != null && totalHosts != 0) { + this.cpuUsed = String.format("%.2f%%", 1.0 * cpuUsedPercentage / totalHosts); + } + } + + public void setCpuAllocated(final Long cpuAllocated, final Long cpuTotal) { + if (cpuAllocated != null && cpuTotal != null && cpuTotal != 0) { + this.cpuAllocated = String.format("%.2f%%", cpuAllocated * 100.0 / cpuTotal); + } + } + + public void setCpuMaxDeviation(final Double maxCpuDeviation, final Double totalCpuUsed, final Long totalHosts) { + if (maxCpuDeviation != null && totalCpuUsed != null && totalHosts != null && totalHosts != 0) { + final Double averageCpuUsage = totalCpuUsed / totalHosts; + this.cpuMaxDeviation = String.format("%.2f%%", (maxCpuDeviation - averageCpuUsage) * 100.0 / averageCpuUsage); + } + } + + public void setMemTotal(final Long memTotal) { + if (memTotal != null) { + this.memTotal = String.format("%.2f GB", memTotal / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setMemUsed( final Long memUsed, final Long memTotal) { + if (memUsed != null && memTotal != null && memTotal != 0) { + this.memUsed = String.format("%.2f%%", memUsed * 100.0 / memTotal); + } + } + + public void setMemAllocated(final Long memAllocated, final Long memTotal) { + if (memAllocated != null && memTotal != null && memTotal != 0) { + this.memAllocated = String.format("%.2f%%", memAllocated * 100.0 / memTotal); + } + } + + public void setMemMaxDeviation(final Long maxMemoryUsage, final Long totalMemory, final Long totalHosts) { + if (maxMemoryUsage != null && totalMemory != null && totalHosts != null && totalHosts != 0) { + final Double averageMemoryUsage = 1.0 * totalMemory / totalHosts; + this.memMaxDeviation = String.format("%.2f%%", (maxMemoryUsage - averageMemoryUsage) * 100.0 / averageMemoryUsage); + } + } + + public void setCpuUsageThreshold(final Double cpuUsed, final Long totalHosts, final Double threshold) { + if (cpuUsed != null && totalHosts != null && threshold != null && totalHosts != 0) { + this.cpuThresholdExceeded = (cpuUsed / (100.0 * totalHosts)) > threshold; + } + } + + public void setCpuUsageDisableThreshold(final Double cpuUsed, final Long totalHosts, final Float threshold) { + if (cpuUsed != null && totalHosts != null && threshold != null && totalHosts != 0) { + this.cpuDisableThresholdExceeded = (cpuUsed / (100.0 * totalHosts)) > threshold; + } + } + + public void setCpuAllocatedThreshold(final Long cpuAllocated, final Long cpuUsed, final Double overCommitRatio, final Double threshold) { + if (cpuAllocated != null && cpuUsed != null && overCommitRatio != null && threshold != null && cpuUsed != 0) { + this.cpuAllocatedThresholdExceeded = (1.0 * cpuAllocated * overCommitRatio / cpuUsed) > threshold; + } + } + + public void setCpuAllocatedDisableThreshold(final Long cpuAllocated, final Long cpuUsed, final Double overCommitRatio, final Float threshold) { + if (cpuAllocated != null && cpuUsed != null && overCommitRatio != null && threshold != null && cpuUsed != 0) { + this.cpuAllocatedDisableThresholdExceeded = (1.0 * cpuAllocated * overCommitRatio / cpuUsed) > threshold; + } + } + + public void setMemoryUsageThreshold(final Long memUsed, final Long memTotal, final Double threshold) { + if (memUsed != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryThresholdExceeded = (1.0 * memUsed / memTotal) > threshold; + } + } + + public void setMemoryUsageDisableThreshold(final Long memUsed, final Long memTotal, final Float threshold) { + if (memUsed != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryDisableThresholdExceeded = (1.0 * memUsed / memTotal) > threshold; + } + } + + + public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Double threshold) { + if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null && memTotal != 0) { + this.memoryAllocatedThresholdExceeded = (1.0 * memAllocated * overCommitRatio / memTotal) > threshold; + } + } + + public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Float threshold) { + if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null && memTotal != 0) { + this.memoryAllocatedDisableThresholdExceeded = (1.0 * memAllocated * overCommitRatio / memTotal) > threshold; + } + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/HostMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/HostMetricsResponse.java new file mode 100644 index 00000000000..cdc9d16d845 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/HostMetricsResponse.java @@ -0,0 +1,204 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; + +public class HostMetricsResponse extends HostResponse { + @SerializedName("powerstate") + @Param(description = "out-of-band management power state") + private OutOfBandManagement.PowerState powerState; + + @SerializedName("instances") + @Param(description = "instances on the host") + private String instances; + + @SerializedName("cputotalghz") + @Param(description = "the total cpu capacity in Ghz") + private String cpuTotal; + + @SerializedName("cpuusedghz") + @Param(description = "the total cpu used in Ghz") + private String cpuUsed; + + @SerializedName("cpuallocatedghz") + @Param(description = "the total cpu allocated in Ghz") + private String cpuAllocated; + + @SerializedName("memorytotalgb") + @Param(description = "the total cpu capacity in GiB") + private String memTotal; + + @SerializedName("memoryusedgb") + @Param(description = "the total cpu used in GiB") + private String memUsed; + + @SerializedName("memoryallocatedgb") + @Param(description = "the total cpu allocated in GiB") + private String memAllocated; + + @SerializedName("networkread") + @Param(description = "network read in GiB") + private String networkRead; + + @SerializedName("networkwrite") + @Param(description = "network write in GiB") + private String networkWrite; + + @SerializedName("cputhreshold") + @Param(description = "cpu usage notification threshold exceeded") + private Boolean cpuThresholdExceeded; + + @SerializedName("cpudisablethreshold") + @Param(description = "cpu usage disable threshold exceeded") + private Boolean cpuDisableThresholdExceeded; + + @SerializedName("cpuallocatedthreshold") + @Param(description = "cpu allocated notification threshold exceeded") + private Boolean cpuAllocatedThresholdExceeded; + + @SerializedName("cpuallocateddisablethreshold") + @Param(description = "cpu allocated disable threshold exceeded") + private Boolean cpuAllocatedDisableThresholdExceeded; + + @SerializedName("memorythreshold") + @Param(description = "memory usage notification threshold exceeded") + private Boolean memoryThresholdExceeded; + + @SerializedName("memorydisablethreshold") + @Param(description = "memory usage disable threshold exceeded") + private Boolean memoryDisableThresholdExceeded; + + @SerializedName("memoryallocatedthreshold") + @Param(description = "memory allocated notification threshold exceeded") + private Boolean memoryAllocatedThresholdExceeded; + + @SerializedName("memoryallocateddisablethreshold") + @Param(description = "memory allocated disable threshold exceeded") + private Boolean memoryAllocatedDisableThresholdExceeded; + + public void setPowerState(final OutOfBandManagement.PowerState powerState) { + this.powerState = powerState; + } + + public void setInstances(final Long running, final Long total) { + if (running != null && total != null) { + this.instances = String.format("%d / %d", running, total); + } + } + + public void setCpuTotal(final Integer cpuNumber, final Long cpuSpeed, final Double overcommitRatio) { + if (cpuNumber != null && cpuSpeed != null && overcommitRatio != null) { + this.cpuTotal = String.format("%.2f Ghz (x %.1f)", cpuNumber * cpuSpeed / 1000.0, overcommitRatio); + } + } + + public void setCpuUsed(final String cpuUsed, final Integer cpuNumber, final Long cpuSpeed) { + if (cpuUsed != null && cpuNumber != null && cpuSpeed != null) { + this.cpuUsed = String.format("%.2f Ghz", Double.valueOf(cpuUsed.replace("%", "")) * cpuNumber * cpuSpeed / (100.0 * 1000.0)); + } + } + + 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)); + } + } + + public void setMemTotal(final Long memTotal, final Double overcommitRatio) { + if (memTotal != null && overcommitRatio != null) { + this.memTotal = String.format("%.2f GB (x %.1f)", memTotal / (1024.0 * 1024.0 * 1024.0), overcommitRatio); + } + } + + public void setMemUsed(final Long memUsed) { + if (memUsed != null) { + this.memUsed = String.format("%.2f GB", memUsed / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setMemAllocated(final Long memAllocated) { + if (memAllocated != null) { + this.memAllocated = String.format("%.2f GB", memAllocated / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setNetworkRead(final Long networkReadKbs) { + if (networkReadKbs != null) { + this.networkRead = String.format("%.2f GB", networkReadKbs / (1024.0 * 1024.0)); + } + } + + public void setNetworkWrite(final Long networkWriteKbs) { + if (networkWriteKbs != null) { + this.networkWrite = String.format("%.2f GB", networkWriteKbs / (1024.0 * 1024.0)); + } + } + + public void setCpuUsageThreshold(final String cpuUsed, final Double threshold) { + if (cpuUsed != null && threshold != null) { + this.cpuThresholdExceeded = Double.valueOf(cpuUsed.replace("%", "")) > (100.0 * threshold); + } + } + + public void setCpuUsageDisableThreshold(final String cpuUsed, final Float threshold) { + if (cpuUsed != null && threshold != null) { + this.cpuDisableThresholdExceeded = Double.valueOf(cpuUsed.replace("%", "")) > (100.0 * threshold); + } + } + + public void setCpuAllocatedThreshold(final String cpuAllocated, final Double overCommitRatio, final Double threshold) { + if (cpuAllocated != null && overCommitRatio != null && threshold != null) { + this.cpuAllocatedThresholdExceeded = (Double.valueOf(cpuAllocated.replace("%", "")) * overCommitRatio) > (100.0 * threshold); + } + } + + public void setCpuAllocatedDisableThreshold(final String cpuAllocated, final Double overCommitRatio, final Float threshold) { + if (cpuAllocated != null && overCommitRatio != null && threshold != null) { + this.cpuAllocatedDisableThresholdExceeded = (Double.valueOf(cpuAllocated.replace("%", "")) * overCommitRatio) > (100.0 * threshold); + } + } + + public void setMemoryUsageThreshold(final Long memUsed, final Long memTotal, final Double threshold) { + if (memUsed != null && memTotal != null && threshold != null) { + this.memoryThresholdExceeded = memUsed > (memTotal * threshold); + } + } + + public void setMemoryUsageDisableThreshold(final Long memUsed, final Long memTotal, final Float threshold) { + if (memUsed != null && memTotal != null && threshold != null) { + this.memoryDisableThresholdExceeded = memUsed > (memTotal * threshold); + } + } + + public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Double threshold) { + if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { + this.memoryAllocatedThresholdExceeded = (memAllocated * overCommitRatio) > (memTotal * threshold); + } + } + + public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Float threshold) { + if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { + this.memoryAllocatedDisableThresholdExceeded = (memAllocated * overCommitRatio) > (memTotal * threshold); + } + } + +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/InfrastructureResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/InfrastructureResponse.java new file mode 100644 index 00000000000..a4db345d21d --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/InfrastructureResponse.java @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponse; + +public class InfrastructureResponse extends BaseResponse { + + @SerializedName("zones") + @Param(description = "Number of zones") + private Integer zones; + + @SerializedName("pods") + @Param(description = "Number of pods") + private Integer pods; + + @SerializedName("clusters") + @Param(description = "Number of clusters") + private Integer clusters; + + @SerializedName("hosts") + @Param(description = "Number of hypervisor hosts") + private Integer hosts; + + @SerializedName("storagepools") + @Param(description = "Number of storage pools") + private Integer storagePools; + + @SerializedName("imagestores") + @Param(description = "Number of images stores") + private Integer imageStores; + + @SerializedName("systemvms") + @Param(description = "Number of systemvms") + private Integer systemvms; + + @SerializedName("routers") + @Param(description = "Number of routers") + private Integer routers; + + @SerializedName("cpusockets") + @Param(description = "Number of cpu sockets") + private Integer cpuSockets; + + public InfrastructureResponse() { + setObjectName("infrastructure"); + } + + public void setZones(final Integer zones) { + this.zones = zones; + } + + public void setPods(final Integer pods) { + this.pods = pods; + } + + public void setClusters(final Integer clusters) { + this.clusters = clusters; + } + + public void setHosts(final Integer hosts) { + this.hosts = hosts; + } + + public void setStoragePools(final Integer storagePools) { + this.storagePools = storagePools; + } + + public void setImageStores(final Integer imageStores) { + this.imageStores = imageStores; + } + + public void setSystemvms(final Integer systemvms) { + this.systemvms = systemvms; + } + + public void setRouters(final Integer routers) { + this.routers = routers; + } + + public void setCpuSockets(final Integer cpuSockets) { + this.cpuSockets = cpuSockets; + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/StoragePoolMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/StoragePoolMetricsResponse.java new file mode 100644 index 00000000000..f20f797aa3e --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/StoragePoolMetricsResponse.java @@ -0,0 +1,105 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.response.StoragePoolResponse; + +public class StoragePoolMetricsResponse extends StoragePoolResponse { + @SerializedName("disksizeusedgb") + @Param(description = "disk size used in GiB") + private String diskSizeUsedGB; + + @SerializedName("disksizetotalgb") + @Param(description = "disk size in GiB") + private String diskSizeTotalGB; + + @SerializedName("disksizeallocatedgb") + @Param(description = "disk size allocated in GiB") + private String diskSizeAllocatedGB; + + @SerializedName("disksizeunallocatedgb") + @Param(description = "disk size unallocated in GiB") + private String diskSizeUnallocatedGB; + + @SerializedName("storageusagethreshold") + @Param(description = "storage usage notification threshold exceeded") + private Boolean storageUsedThreshold; + + @SerializedName("storageusagedisablethreshold") + @Param(description = "storage usage disable threshold exceeded") + private Boolean storageUsedDisableThreshold; + + @SerializedName("storageallocatedthreshold") + @Param(description = "storage allocated notification threshold exceeded") + private Boolean storageAllocatedThreshold; + + @SerializedName("storageallocateddisablethreshold") + @Param(description = "storage allocated disable threshold exceeded") + private Boolean storageAllocatedDisableThreshold; + + public void setDiskSizeUsedGB(final Long diskSizeUsed) { + if (diskSizeUsed != null) { + this.diskSizeUsedGB = String.format("%.2f GB", diskSizeUsed / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setDiskSizeTotalGB(final Long totalDiskSize, final String overProvisionFactor) { + if (totalDiskSize != null && overProvisionFactor != null) { + this.diskSizeTotalGB = String.format("%.2f GB (x%s)", totalDiskSize / (1024.0 * 1024.0 * 1024.0), overProvisionFactor); + } + } + + public void setDiskSizeAllocatedGB(final Long diskSizeAllocated) { + if (diskSizeAllocated != null) { + this.diskSizeAllocatedGB = String.format("%.2f GB", diskSizeAllocated / (1024.0 * 1024.0 * 1024.0)); + + } + } + + public void setDiskSizeUnallocatedGB(final Long totalDiskSize, final Long diskSizeAllocated, final String overProvisionFactor) { + if (totalDiskSize != null && diskSizeAllocated != null && overProvisionFactor != null) { + this.diskSizeUnallocatedGB = String.format("%.2f GB", ((Double.valueOf(overProvisionFactor) * totalDiskSize) - diskSizeAllocated) / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setStorageUsedThreshold(final Long totalDiskSize, final Long diskSizeUsed, final String overProvisionFactor, final Double threshold) { + if (totalDiskSize != null && diskSizeUsed != null && overProvisionFactor != null && threshold != null) { + this.storageUsedThreshold = diskSizeUsed > (totalDiskSize * Double.valueOf(overProvisionFactor) * threshold) ; + } + } + + public void setStorageUsedDisableThreshold(final Long totalDiskSize, final Long diskSizeUsed, final String overProvisionFactor, final Double threshold) { + if (totalDiskSize != null && diskSizeUsed != null && overProvisionFactor != null && threshold != null) { + this.storageUsedDisableThreshold = diskSizeUsed > (totalDiskSize * Double.valueOf(overProvisionFactor) * threshold); + } + } + + public void setStorageAllocatedThreshold(final Long totalDiskSize, final Long diskSizeAllocated, final String overProvisionFactor, final Double threshold) { + if (totalDiskSize != null && diskSizeAllocated != null && overProvisionFactor != null && threshold != null) { + this.storageAllocatedThreshold = diskSizeAllocated > (totalDiskSize * Double.valueOf(overProvisionFactor) * threshold); + } + } + + public void setStorageAllocatedDisableThreshold(final Long totalDiskSize, final Long diskSizeAllocated, final String overProvisionFactor, final Double threshold) { + if (totalDiskSize != null && diskSizeAllocated != null && overProvisionFactor != null && threshold != null) { + this.storageAllocatedDisableThreshold = diskSizeAllocated > (totalDiskSize * Double.valueOf(overProvisionFactor) * threshold); + } + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/VmMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/VmMetricsResponse.java new file mode 100644 index 00000000000..a4057aeb059 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/VmMetricsResponse.java @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.response.NicResponse; +import org.apache.cloudstack.api.response.UserVmResponse; + +import java.util.Set; + +public class VmMetricsResponse extends UserVmResponse { + @SerializedName(ApiConstants.IP_ADDRESS) + @Param(description = "the VM's primary IP address") + private String ipAddress; + + @SerializedName("cputotal") + @Param(description = "the total cpu capacity in Ghz") + private String cpuTotal; + + @SerializedName("memorytotal") + @Param(description = "the total memory capacity in GiB") + private String memTotal; + + @SerializedName("networkread") + @Param(description = "network read in MiB") + private String networkRead; + + @SerializedName("networkwrite") + @Param(description = "network write in MiB") + private String networkWrite; + + @SerializedName("diskread") + @Param(description = "disk read in MiB") + private String diskRead; + + @SerializedName("diskwrite") + @Param(description = "disk write in MiB") + private String diskWrite; + + @SerializedName("diskiopstotal") + @Param(description = "the total disk iops") + private Long diskIopsTotal; + + public void setIpAddress(final Set nics) { + if (nics != null && nics.size() > 0) { + this.ipAddress = nics.iterator().next().getIpaddress(); + } + } + + public void setCpuTotal(final Integer cpuNumber, final Integer cpuSpeed) { + if (cpuNumber != null && cpuSpeed != null) { + this.cpuTotal = String.format("%.1f Ghz", cpuNumber * cpuSpeed / 1000.0); + } + } + + public void setMemTotal(final Integer memory) { + if (memory != null) { + this.memTotal = String.format("%.2f GB", memory / 1024.0); + } + } + + public void setNetworkRead(final Long networkReadKbs) { + if (networkReadKbs != null) { + this.networkRead = String.format("%.2f MB", networkReadKbs / 1024.0); + } + } + + public void setNetworkWrite(final Long networkWriteKbs) { + if (networkWriteKbs != null) { + this.networkWrite = String.format("%.2f MB", networkWriteKbs / 1024.0); + } + } + + public void setDiskRead(final Long diskReadKbs) { + if (diskReadKbs != null) { + this.networkRead = String.format("%.2f MB", diskReadKbs / 1024.0); + } + } + + public void setDiskWrite(final Long diskWriteKbs) { + if (diskWriteKbs != null) { + this.networkWrite = String.format("%.2f MB", diskWriteKbs / 1024.0); + } + } + + public void setDiskIopsTotal(final Long diskIoRead, final Long diskIoWrite) { + if (diskIoRead != null && diskIoWrite != null) { + this.diskIopsTotal = diskIoRead + diskIoWrite; + } + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/VolumeMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/VolumeMetricsResponse.java new file mode 100644 index 00000000000..ef8515f1396 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/VolumeMetricsResponse.java @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.common.base.Strings; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.response.VolumeResponse; + +public class VolumeMetricsResponse extends VolumeResponse { + @SerializedName("sizegb") + @Param(description = "disk size in GiB") + private String diskSizeGB; + + public void setStorageType(final String storageType, final String volumeType) { + if (!Strings.isNullOrEmpty(storageType) && !Strings.isNullOrEmpty(volumeType)) { + this.setStorageType(String.format("%s (%s)", storageType.substring(0, 1).toUpperCase() + storageType.substring(1), volumeType)); + } + } + + public void setDiskSizeGB(final Long size) { + if (size != null) { + this.diskSizeGB = String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0)); + } + } +} diff --git a/plugins/metrics/src/org/apache/cloudstack/response/ZoneMetricsResponse.java b/plugins/metrics/src/org/apache/cloudstack/response/ZoneMetricsResponse.java new file mode 100644 index 00000000000..71560178564 --- /dev/null +++ b/plugins/metrics/src/org/apache/cloudstack/response/ZoneMetricsResponse.java @@ -0,0 +1,206 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.response.ZoneResponse; + +public class ZoneMetricsResponse extends ZoneResponse { + @SerializedName("state") + @Param(description = "state of the cluster") + private String state; + + @SerializedName("clusters") + @Param(description = "healthy / total clusters in the zone") + private String resources; + + @SerializedName("cputotal") + @Param(description = "the total cpu capacity in Ghz") + private String cpuTotal; + + @SerializedName("cpuused") + @Param(description = "the total cpu used in Ghz") + private String cpuUsed; + + @SerializedName("cpuallocated") + @Param(description = "the total cpu allocated in Ghz") + private String cpuAllocated; + + @SerializedName("cpumaxdeviation") + @Param(description = "the maximum cpu deviation") + private String cpuMaxDeviation; + + @SerializedName("memorytotal") + @Param(description = "the total cpu capacity in GiB") + private String memTotal; + + @SerializedName("memoryused") + @Param(description = "the total cpu used in GiB") + private String memUsed; + + @SerializedName("memoryallocated") + @Param(description = "the total cpu allocated in GiB") + private String memAllocated; + + @SerializedName("memorymaxdeviation") + @Param(description = "the maximum memory deviation") + private String memMaxDeviation; + + @SerializedName("cputhreshold") + @Param(description = "cpu usage notification threshold exceeded") + private Boolean cpuThresholdExceeded; + + @SerializedName("cpudisablethreshold") + @Param(description = "cpu usage disable threshold exceeded") + private Boolean cpuDisableThresholdExceeded; + + @SerializedName("cpuallocatedthreshold") + @Param(description = "cpu allocated notification threshold exceeded") + private Boolean cpuAllocatedThresholdExceeded; + + @SerializedName("cpuallocateddisablethreshold") + @Param(description = "cpu allocated disable threshold exceeded") + private Boolean cpuAllocatedDisableThresholdExceeded; + + @SerializedName("memorythreshold") + @Param(description = "memory usage notification threshold exceeded") + private Boolean memoryThresholdExceeded; + + @SerializedName("memorydisablethreshold") + @Param(description = "memory usage disable threshold exceeded") + private Boolean memoryDisableThresholdExceeded; + + @SerializedName("memoryallocatedthreshold") + @Param(description = "memory allocated notification threshold exceeded") + private Boolean memoryAllocatedThresholdExceeded; + + @SerializedName("memoryallocateddisablethreshold") + @Param(description = "memory allocated disable threshold exceeded") + private Boolean memoryAllocatedDisableThresholdExceeded; + + + public void setState(final String allocationState) { + this.state = allocationState; + } + + public void setResource(final Long upResources, final Long totalResources) { + if (upResources != null && totalResources != null) { + this.resources = String.format("%d / %d", upResources, totalResources); + } + } + + public void setCpuTotal(final Long cpuTotal) { + if (cpuTotal != null) { + this.cpuTotal = String.format("%.2f Ghz", cpuTotal / 1000.0); + } + } + + public void setCpuUsed(final Double cpuUsedPercentage, final Long totalHosts) { + if (cpuUsedPercentage != null && totalHosts != null && totalHosts != 0) { + this.cpuUsed = String.format("%.2f%%", 1.0 * cpuUsedPercentage / totalHosts); + } + } + + public void setCpuAllocated(final Long cpuAllocated, final Long cpuTotal) { + if (cpuAllocated != null && cpuTotal != null && cpuTotal != 0) { + this.cpuAllocated = String.format("%.2f%%", cpuAllocated * 100.0 / cpuTotal); + } + } + + public void setCpuMaxDeviation(final Double maxCpuDeviation, final Double totalCpuUsed, final Long totalHosts) { + if (maxCpuDeviation != null && totalCpuUsed != null && totalHosts != null && totalHosts != 0) { + final Double averageCpuUsage = totalCpuUsed / totalHosts; + this.cpuMaxDeviation = String.format("%.2f%%", (maxCpuDeviation - averageCpuUsage) * 100.0 / averageCpuUsage); + } + } + + public void setMemTotal(final Long memTotal) { + if (memTotal != null) { + this.memTotal = String.format("%.2f GB", memTotal / (1024.0 * 1024.0 * 1024.0)); + } + } + + public void setMemUsed( final Long memUsed, final Long memTotal) { + if (memUsed != null && memTotal != null) { + this.memUsed = String.format("%.2f%%", memUsed * 100.0 / memTotal); + } + } + + public void setMemAllocated(final Long memAllocated, final Long memTotal) { + if (memAllocated != null && memTotal != null && memTotal != 0) { + this.memAllocated = String.format("%.2f%%", memAllocated * 100.0 / memTotal); + } + } + + public void setMemMaxDeviation(final Long maxMemoryUsage, final Long totalMemory, final Long totalHosts) { + if (maxMemoryUsage != null && totalMemory != null && totalHosts != null && totalHosts != 0) { + final Long averageMemoryUsage = totalMemory / totalHosts; + this.memMaxDeviation = String.format("%.2f%%", (maxMemoryUsage - averageMemoryUsage) * 100.0 / averageMemoryUsage); + } + } + + public void setCpuUsageThreshold(final Double cpuUsed, final Long totalHosts, final Double threshold) { + if (cpuUsed != null && totalHosts != null && threshold != null && totalHosts != 0) { + this.cpuThresholdExceeded = (cpuUsed / (100.0 * totalHosts)) > threshold; + } + } + + public void setCpuUsageDisableThreshold(final Double cpuUsed, final Long totalHosts, final Float threshold) { + if (cpuUsed != null && totalHosts != null && threshold != null && totalHosts != 0) { + this.cpuDisableThresholdExceeded = (cpuUsed / (100.0 * totalHosts)) > threshold; + } + } + + public void setCpuAllocatedThreshold(final Long cpuAllocated, final Long cpuUsed, final Double threshold) { + if (cpuAllocated != null && cpuUsed != null && threshold != null && cpuUsed != 0) { + this.cpuAllocatedThresholdExceeded = (1.0 * cpuAllocated / cpuUsed) > threshold; + } + } + + public void setCpuAllocatedDisableThreshold(final Long cpuAllocated, final Long cpuUsed, final Float threshold) { + if (cpuAllocated != null && cpuUsed != null && threshold != null && cpuUsed != 0) { + this.cpuAllocatedDisableThresholdExceeded = (1.0 * cpuAllocated / cpuUsed) > threshold; + } + } + + public void setMemoryUsageThreshold(final Long memUsed, final Long memTotal, final Double threshold) { + if (memUsed != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryThresholdExceeded = (1.0 * memUsed / memTotal) > threshold; + } + } + + public void setMemoryUsageDisableThreshold(final Long memUsed, final Long memTotal, final Float threshold) { + if (memUsed != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryDisableThresholdExceeded = (1.0 * memUsed / memTotal) > threshold; + } + } + + + public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double threshold) { + if (memAllocated != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryAllocatedThresholdExceeded = (1.0 * memAllocated / memTotal) > threshold; + } + } + + public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Float threshold) { + if (memAllocated != null && memTotal != null && threshold != null && memTotal != 0) { + this.memoryAllocatedDisableThresholdExceeded = (1.0 * memAllocated / memTotal) > threshold; + } + } +} diff --git a/plugins/pom.xml b/plugins/pom.xml index 40cee26541f..72a7bc1dbad 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -69,6 +69,7 @@ hypervisors/ucs hypervisors/hyperv hypervisors/ovm3 + metrics network-elements/elastic-loadbalancer network-elements/ovs network-elements/juniper-contrail diff --git a/server/src/com/cloud/api/query/dao/HostJoinDao.java b/server/src/com/cloud/api/query/dao/HostJoinDao.java index f0ac1831d45..e7dc5d5ff04 100644 --- a/server/src/com/cloud/api/query/dao/HostJoinDao.java +++ b/server/src/com/cloud/api/query/dao/HostJoinDao.java @@ -41,4 +41,6 @@ public interface HostJoinDao extends GenericDao { List searchByIds(Long... ids); + List findByClusterId(Long clusterId, Host.Type type); + } diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java index 6c15a8be4d8..58a03664c13 100644 --- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -65,6 +65,8 @@ public class HostJoinDaoImpl extends GenericDaoBase implements private final SearchBuilder hostIdSearch; + private final SearchBuilder ClusterSearch; + protected HostJoinDaoImpl() { hostSearch = createSearchBuilder(); @@ -75,6 +77,11 @@ public class HostJoinDaoImpl extends GenericDaoBase implements hostIdSearch.and("id", hostIdSearch.entity().getId(), SearchCriteria.Op.EQ); hostIdSearch.done(); + ClusterSearch = createSearchBuilder(); + ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); + ClusterSearch.and("type", ClusterSearch.entity().getType(), SearchCriteria.Op.EQ); + ClusterSearch.done(); + this._count = "select count(distinct id) from host_view WHERE "; } @@ -432,4 +439,12 @@ public class HostJoinDaoImpl extends GenericDaoBase implements return uvList; } + @Override + public List findByClusterId(Long clusterId, Host.Type type) { + SearchCriteria sc = ClusterSearch.create(); + sc.setParameters("clusterId", clusterId); + sc.setParameters("type", type); + return listBy(sc); + } + } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index ef0ad19079f..80c417e1f53 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -588,7 +588,7 @@ StateListener { List allDedicatedPods = _dedicatedDao.listAllPods(); allPodsInDc.retainAll(allDedicatedPods); - List allClustersInDc = _clusterDao.listAllCusters(dc.getId()); + List allClustersInDc = _clusterDao.listAllClusters(dc.getId()); List allDedicatedClusters = _dedicatedDao.listAllClusters(); allClustersInDc.retainAll(allDedicatedClusters); diff --git a/test/integration/smoke/test_metrics_api.py b/test/integration/smoke/test_metrics_api.py new file mode 100644 index 00000000000..27c4a1bd75b --- /dev/null +++ b/test/integration/smoke/test_metrics_api.py @@ -0,0 +1,210 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.lib.utils import (random_gen) +from nose.plugins.attrib import attr + +import time + +_multiprocess_shared_ = True + +class TestMetrics(cloudstackTestCase): + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + self.dbclient = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.host = list_hosts(self.apiclient, + zoneid=self.zone.id, + type='Routing')[0] + self.cluster = self.apiclient.listClusters(listClusters.listClustersCmd())[0] + self.disk_offering = DiskOffering.create( + self.apiclient, + self.services["disk_offering"] + ) + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"] + ) + self.template = get_template( + self.apiclient, + self.zone.id, + self.services["ostype"] + ) + + self.cleanup = [] + self.cleanup.append(self.disk_offering) + self.cleanup.append(self.service_offering) + + def tearDown(self): + try: + #Clean up + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_hosts_metrics(self): + + cmd = listHostsMetrics.listHostsMetricsCmd() + cmd.id = self.host.id + cmd.type = 'Routing' + + host_metric = self.apiclient.listHostsMetrics(cmd)[0] + + self.assertEqual(host_metric.cpuallocated, self.host.cpuallocated) + self.assertEqual(host_metric.memoryallocated, self.host.memoryallocated) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_clusters_metrics(self): + + cmd = listClustersMetrics.listClustersMetricsCmd() + cmd.id = self.cluster.id + + cluster_metric = self.apiclient.listClustersMetrics(cmd)[0] + + self.assertEqual(cluster_metric.id, self.cluster.id) + self.assertTrue(hasattr(cluster_metric, 'cpuallocated')) + self.assertTrue(hasattr(cluster_metric, 'cpumaxdeviation')) + self.assertTrue(hasattr(cluster_metric, 'memoryallocated')) + self.assertTrue(hasattr(cluster_metric, 'memoryused')) + self.assertTrue(hasattr(cluster_metric, 'memorymaxdeviation')) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_zones_metrics(self): + cmd = listZonesMetrics.listZonesMetricsCmd() + cmd.id = self.zone.id + + zone_metrics = self.apiclient.listZonesMetrics(cmd)[0] + + self.assertTrue(hasattr(zone_metrics, 'cpuallocated')) + self.assertTrue(hasattr(zone_metrics, 'cpumaxdeviation')) + self.assertTrue(hasattr(zone_metrics, 'cputotal')) + self.assertTrue(hasattr(zone_metrics, 'cpuused')) + self.assertTrue(hasattr(zone_metrics, 'memoryallocated')) + self.assertTrue(hasattr(zone_metrics, 'memorymaxdeviation')) + self.assertTrue(hasattr(zone_metrics, 'memoryused')) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_vms_metrics(self): + #deploy VM + self.small_virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + zoneid=self.zone.id + ) + self.cleanup.append(self.small_virtual_machine) + + + cmd = listVirtualMachinesMetrics.listVirtualMachinesMetricsCmd() + cmd.id = self.small_virtual_machine.id + + lvmm = self.apiclient.listVirtualMachinesMetrics(cmd)[0] + + self.assertEqual(lvmm.id, self.small_virtual_machine.id) + + self.assertTrue(hasattr(lvmm, 'cputotal')) + self.assertTrue(hasattr(lvmm, 'cpuused')) + self.assertTrue(hasattr(lvmm, 'diskiowrite')) + self.assertTrue(hasattr(lvmm, 'diskkbswrite')) + self.assertTrue(hasattr(lvmm, 'networkread')) + self.assertTrue(hasattr(lvmm, 'networkwrite')) + + return + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_pstorage_metrics(self): + #list StoragePools + sp = self.apiclient.listStoragePools(listStoragePools.listStoragePoolsCmd())[0] + + #list StoragePoolsMetrics + cmd = listStoragePoolsMetrics.listStoragePoolsMetricsCmd() + cmd.id = sp.id + + sp_metrics = self.apiclient.listStoragePoolsMetrics(cmd)[0] + + self.assertEqual(sp_metrics.disksizeallocated, sp.disksizeallocated) + self.assertEqual(sp_metrics.state, sp.state) + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_volumes_metrics(self): + volume = Volume.create( + self.apiclient, + self.services['volume'], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume) + + cmd = listVolumes.listVolumesCmd() + cmd.id = volume.id + + lv = self.apiclient.listVolumes(cmd)[0] + + cmd = listVolumesMetrics.listVolumesMetricsCmd() + cmd.id = lv.id + lvm = self.apiclient.listVolumesMetrics(cmd)[0] + + self.assertEqual(lv.size, lvm.size) + self.assertTrue(hasattr(lvm, 'diskBytesReadRate')) + self.assertTrue(hasattr(lvm, 'diskBytesWriteRate')) + self.assertTrue(hasattr(lvm, 'diskIopsReadRate')) + self.assertTrue(hasattr(lvm, 'diskIopsWriteRate')) + + return + + @attr(tags = ["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_list_infrastructure_metrics(self): + cmd = listInfrastructure.listInfrastructureCmd() + li = self.apiclient.listInfrastructure(cmd) + + self.assertTrue(hasattr(li, 'clusters')) + self.assertEqual(li.clusters, len(self.apiclient.listClusters(listClusters.listClustersCmd()))) + self.assertTrue(hasattr(li, 'hosts')) + + self.assertEqual(li.hosts, len(list_hosts(self.apiclient, + zoneid=self.zone.id, + type='Routing'))) + + self.assertTrue(hasattr(li, 'imagestores')) + self.assertEqual(li.imagestores, len(self.apiclient.listImageStores(listImageStores.listImageStoresCmd()))) + + self.assertTrue(hasattr(li, 'pods')) + self.assertEqual(li.pods, len(self.apiclient.listPods(listPods.listPodsCmd()))) + + self.assertTrue(hasattr(li, 'routers')) + + self.assertTrue(hasattr(li, 'storagepools')) + self.assertEqual(li.storagepools, len(self.apiclient.listStoragePools(listStoragePools.listStoragePoolsCmd()))) + + self.assertTrue(hasattr(li, 'zones')) + self.assertEqual(li.zones, len(self.apiclient.listZones(listZones.listZonesCmd()))) + + self.assertTrue(hasattr(li, 'systemvms')) + self.assertTrue(hasattr(li, 'cpusockets')) diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index e6ef6748119..0fd97754176 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -168,7 +168,9 @@ known_categories = { 'CacheStore' : 'Cache Store', 'IAM' : 'IAM', 'OvsElement' : 'Ovs Element', - 'StratosphereSsp' : ' Stratosphere SSP' + 'StratosphereSsp' : ' Stratosphere SSP', + 'Metrics' : 'Metrics', + 'Infrastructure' : 'Metrics', } diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js index 554aab777d1..3152af76a05 100644 --- a/ui/scripts/metrics.js +++ b/ui/scripts/metrics.js @@ -56,15 +56,15 @@ label: 'label.metrics.cpu.usage', collapsible: true, columns: { - cpuusedavg: { + cpuused: { label: 'label.metrics.cpu.used.avg', thresholdcolor: true, thresholds: { - notification: 'cpunotificationthreshold', + notification: 'cputhreshold', disable: 'cpudisablethreshold' } }, - cpumaxdev: { + cpumaxdeviation: { label: 'label.metrics.cpu.max.dev' } } @@ -77,8 +77,8 @@ label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'cpunotificationthreshold', - disable: 'cpudisablethreshold' + notification: 'cpuallocatedthreshold', + disable: 'cpuallocateddisablethreshold' } }, cputotal: { @@ -90,15 +90,15 @@ label: 'label.metrics.memory.usage', collapsible: true, columns: { - memusedavg: { + memoryused: { label: 'label.metrics.memory.used.avg', thresholdcolor: true, thresholds: { - notification: 'memnotificationthreshold', - disable: 'memdisablethreshold' + notification: 'memorythreshold', + disable: 'memorydisablethreshold' } }, - memmaxdev: { + memorymaxdeviation: { label: 'label.metrics.memory.max.dev' } } @@ -107,15 +107,15 @@ label: 'label.metrics.memory.allocated', collapsible: true, columns: { - memallocated: { + memoryallocated: { label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'memnotificationthreshold', - disable: 'memdisablethreshold' + notification: 'memoryallocatedthreshold', + disable: 'memoryallocateddisablethreshold' } }, - memtotal: { + memorytotal: { label: 'label.metrics.memory.total' } } @@ -125,129 +125,11 @@ var data = {}; listViewDataProvider(args, data); $.ajax({ - url: createURL('listZones'), + url: createURL('listZonesMetrics'), data: data, success: function(json) { - var items = json.listzonesresponse.zone; - if (items) { - $.each(items, function(idx, zone) { - items[idx].clusters = 0; - items[idx].clustersUp = 0; - items[idx].hosts = 0; - items[idx].cpuusedavg = 0.0; - items[idx].cpumaxdev = 0.0; - items[idx].cpuallocated = 0.0; - items[idx].cputotal = 0.0; - items[idx].maxCpuUsed = 0.0; - items[idx].memusedavg = 0.0; - items[idx].memmaxdev = 0.0; - items[idx].memallocated = 0.0; - items[idx].memtotal = 0.0; - items[idx].maxMemUsed = 0.0; - - // Threshold color coding - items[idx].cpunotificationthreshold = 75.0; - items[idx].cpudisablethreshold = 95.0; - items[idx].memnotificationthreshold = 75.0; - items[idx].memdisablethreshold = 95.0; - - $.ajax({ - url: createURL('listClusters'), - data: {zoneid: zone.id, pagesize: -1}, - success: function(json) { - if (json && json.listclustersresponse && json.listclustersresponse.cluster && json.listclustersresponse.count) { - items[idx].clusters += parseInt(json.listclustersresponse.count); - $.each(json.listclustersresponse.cluster, function(i, cluster) { - if (cluster.allocationstate == 'Enabled' && cluster.managedstate == 'Managed') { - items[idx].clustersUp += 1; - } - $.ajax({ - url: createURL('listHosts'), - data: {clusterid: cluster.id, type: 'routing', pagesize: -1}, - success: function(json) { - if (json && json.listhostsresponse && json.listhostsresponse.host && json.listhostsresponse.count) { - items[idx].hosts += parseInt(json.listhostsresponse.count); - $.each(json.listhostsresponse.host, function(i, host) { - if (host.hasOwnProperty('cpuused')) { - var hostCpuUsage = parseFloat(host.cpuused); - items[idx].cpuusedavg += hostCpuUsage; - if (hostCpuUsage > items[idx].maxCpuUsed) { - items[idx].maxCpuUsed = hostCpuUsage; - } - } - - if (host.hasOwnProperty('cpuallocated')) { - items[idx].cpuallocated += parseFloat(host.cpuallocated.replace('%', '')); - } - - if (host.hasOwnProperty('memoryused')) { - var hostMemoryUsage = 100.0 * parseFloat(host.memoryused) / parseFloat(host.memorytotal); - items[idx].memusedavg += hostMemoryUsage; - if (hostMemoryUsage > items[idx].maxMemUsed) { - items[idx].maxMemUsed = hostMemoryUsage; - } - } - - if (host.hasOwnProperty('memoryallocated')) { - items[idx].memallocated += parseFloat(100.0 * parseFloat(host.memoryallocated)/parseFloat(host.memorytotal)); - } - }); - } - }, - async: false - }); - }); - } - }, - async: false - }); - - $.ajax({ - url: createURL('listCapacity'), - data: {zoneid: zone.id}, - success: function(json) { - if (json && json.listcapacityresponse && json.listcapacityresponse.capacity) { - $.each(json.listcapacityresponse.capacity, function(i, capacity) { - // CPU - if (capacity.type == 1) { - items[idx].cputotal = parseInt(capacity.capacitytotal)/1000.0; - } - // Memory - if (capacity.type == 0) { - items[idx].memtotal = parseInt(capacity.capacitytotal)/(1024.0*1024.0*1024.0); - } - }); - } - }, - async: false - }); - - if (items[idx].hosts != 0) { - items[idx].cpuusedavg = (items[idx].cpuusedavg / items[idx].hosts); - items[idx].cpumaxdev = (items[idx].maxCpuUsed - items[idx].cpuusedavg); - items[idx].cpuallocated = (items[idx].cpuallocated / items[idx].hosts); - - items[idx].memusedavg = (items[idx].memusedavg / items[idx].hosts); - items[idx].memmaxdev = (items[idx].maxMemUsed - items[idx].memusedavg); - items[idx].memallocated = (items[idx].memallocated / items[idx].hosts); - } - // Format data - items[idx].cpuusedavg = (items[idx].cpuusedavg).toFixed(2) + "%"; - items[idx].cpumaxdev = (items[idx].cpumaxdev).toFixed(2) + "%"; - items[idx].cpuallocated = (items[idx].cpuallocated).toFixed(2) + "%"; - items[idx].cputotal = (items[idx].cputotal).toFixed(2) + " Ghz"; - - items[idx].memusedavg = (items[idx].memusedavg).toFixed(2) + "%"; - items[idx].memmaxdev = (items[idx].memmaxdev).toFixed(2) + "%"; - items[idx].memallocated = (items[idx].memallocated).toFixed(2) + "%"; - items[idx].memtotal = (items[idx].memtotal).toFixed(2) + " GB"; - - items[idx].clusters = items[idx].clustersUp + ' / ' + items[idx].clusters; - items[idx].state = items[idx].allocationstate; - }); - } args.response.success({ - data: items + data: json.listzonesmetricsresponse.zone }); } }); @@ -290,15 +172,15 @@ label: 'label.metrics.cpu.usage', collapsible: true, columns: { - cpuusedavg: { + cpuused: { label: 'label.metrics.cpu.used.avg', thresholdcolor: true, thresholds: { - notification: 'cpunotificationthreshold', + notification: 'cputhreshold', disable: 'cpudisablethreshold' } }, - cpumaxdev: { + cpumaxdeviation: { label: 'label.metrics.cpu.max.dev' } } @@ -311,8 +193,8 @@ label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'cpunotificationthreshold', - disable: 'cpudisablethreshold' + notification: 'cpuallocatedthreshold', + disable: 'cpuallocateddisablethreshold' } }, cputotal: { @@ -324,15 +206,15 @@ label: 'label.metrics.memory.usage', collapsible: true, columns: { - memusedavg: { + memoryused: { label: 'label.metrics.memory.used.avg', thresholdcolor: true, thresholds: { - notification: 'memnotificationthreshold', - disable: 'memdisablethreshold' + notification: 'memorythreshold', + disable: 'memorydisablethreshold' } }, - memmaxdev: { + memorymaxdeviation: { label: 'label.metrics.memory.max.dev' } } @@ -341,15 +223,15 @@ label: 'label.metrics.memory.allocated', collapsible: true, columns: { - memallocated: { + memoryallocated: { label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'memnotificationthreshold', - disable: 'memdisablethreshold' + notification: 'memoryallocatedthreshold', + disable: 'memoryallocateddisablethreshold' } }, - memtotal: { + memorytotal: { label: 'label.metrics.memory.total' } } @@ -372,154 +254,11 @@ } $.ajax({ - url: createURL('listClusters'), + url: createURL('listClustersMetrics'), data: data, success: function(json) { - var items = json.listclustersresponse.cluster; - if (items) { - $.each(items, function(idx, cluster) { - items[idx].hosts = 0; - items[idx].hostsUp = 0; - items[idx].cpuusedavg = 0.0; - items[idx].cpumaxdev = 0.0; - items[idx].cpuallocated = 0.0; - items[idx].cputotal = 0.0; - items[idx].maxCpuUsed = 0; - items[idx].memusedavg = 0.0; - items[idx].memmaxdev = 0.0; - items[idx].memallocated = 0.0; - items[idx].memtotal = 0.0; - items[idx].maxMemUsed = 0.0; - - // Threshold color coding - items[idx].cpunotificationthreshold = 75.0; - items[idx].cpudisablethreshold = 95.0; - items[idx].memnotificationthreshold = 75.0; - items[idx].memdisablethreshold = 95.0; - - $.ajax({ - url: createURL('listConfigurations'), - data: {clusterid: cluster.id, listAll: true}, - success: function(json) { - if (json.listconfigurationsresponse && json.listconfigurationsresponse.configuration) { - $.each(json.listconfigurationsresponse.configuration, function(i, config) { - switch (config.name) { - case 'cluster.cpu.allocated.capacity.disablethreshold': - items[idx].cpudisablethreshold = 100 * parseFloat(config.value); - break; - case 'cluster.cpu.allocated.capacity.notificationthreshold': - items[idx].cpunotificationthreshold = 100 * parseFloat(config.value); - break; - case 'cluster.memory.allocated.capacity.disablethreshold': - items[idx].memdisablethreshold = 100 * parseFloat(config.value); - break; - case 'cluster.memory.allocated.capacity.notificationthreshold': - items[idx].memnotificationthreshold = 100 * parseFloat(config.value); - break; - } - }); - } - }, - async: false - }); - - $.ajax({ - url: createURL('listHosts'), - data: {clusterid: cluster.id, type: 'routing', pagesize: -1}, - success: function(json) { - if (json && json.listhostsresponse && json.listhostsresponse.host && json.listhostsresponse.count) { - items[idx].hosts += parseInt(json.listhostsresponse.count); - $.each(json.listhostsresponse.host, function(i, host) { - if (host.state == 'Up') { - items[idx].hostsUp += 1; - } - if (host.hasOwnProperty('cpuused')) { - var hostCpuUsage = parseFloat(host.cpuused); - items[idx].cpuusedavg += hostCpuUsage; - if (hostCpuUsage > items[idx].maxCpuUsed) { - items[idx].maxCpuUsed = hostCpuUsage; - } - } - - if (host.hasOwnProperty('cpuallocated')) { - items[idx].cpuallocated += parseFloat(host.cpuallocated.replace('%', '')); - } - - if (host.hasOwnProperty('memoryused')) { - var hostMemoryUsage = 100.0 * parseFloat(host.memoryused) / parseFloat(host.memorytotal); - items[idx].memusedavg += hostMemoryUsage; - if (hostMemoryUsage > items[idx].maxMemUsed) { - items[idx].maxMemUsed = hostMemoryUsage; - } - } - - if (host.hasOwnProperty('memoryallocated')) { - items[idx].memallocated += parseFloat(100.0 * parseFloat(host.memoryallocated)/parseFloat(host.memorytotal)); - } - }); - } - }, - async: false - }); - - $.ajax({ - url: createURL('listCapacity'), - data: {clusterid: cluster.id}, - success: function(json) { - if (json && json.listcapacityresponse && json.listcapacityresponse.capacity) { - $.each(json.listcapacityresponse.capacity, function(i, capacity) { - // CPU - if (capacity.type == 1) { - items[idx].cputotal = parseInt(capacity.capacitytotal)/1000.0; - } - // Memory - if (capacity.type == 0) { - items[idx].memtotal = parseInt(capacity.capacitytotal)/(1024.0*1024.0*1024.0); - } - }); - } - }, - async: false - }); - - if (items[idx].hosts != 0) { - items[idx].cpuusedavg = (items[idx].cpuusedavg / items[idx].hosts); - items[idx].cpumaxdev = (items[idx].maxCpuUsed - items[idx].cpuusedavg); - items[idx].cpuallocated = (items[idx].cpuallocated / items[idx].hosts); - - items[idx].memusedavg = (items[idx].memusedavg / items[idx].hosts); - items[idx].memmaxdev = (items[idx].maxMemUsed - items[idx].memusedavg); - items[idx].memallocated = (items[idx].memallocated / items[idx].hosts); - } - - // Format data - items[idx].cpuusedavg = (items[idx].cpuusedavg).toFixed(2) + "%"; - items[idx].cpumaxdev = (items[idx].cpumaxdev).toFixed(2) + "%"; - items[idx].cpuallocated = (items[idx].cpuallocated).toFixed(2) + "%"; - items[idx].cputotal = (items[idx].cputotal).toFixed(2) + " Ghz"; - - items[idx].memusedavg = (items[idx].memusedavg).toFixed(2) + "%"; - items[idx].memmaxdev = (items[idx].memmaxdev).toFixed(2) + "%"; - items[idx].memallocated = (items[idx].memallocated).toFixed(2) + "%"; - items[idx].memtotal = (items[idx].memtotal).toFixed(2) + " GB"; - items[idx].hosts = items[idx].hostsUp + ' / ' + items[idx].hosts; - - items[idx].state = items[idx].allocationstate; - if (items[idx].managedstate == 'Unmanaged') { - items[idx].state = 'Unmanaged'; - } - - if (items[idx].managedstate == 'Managed' && items[idx].allocationstate == 'Enabled') { - items[idx].state = 'Enabled'; - } - - if (items[idx].managedstate == 'Managed' && items[idx].allocationstate == 'Disabled') { - items[idx].state = 'Disabled'; - } - }); - } args.response.success({ - data: items + data: json.listclustersmetricsresponse.cluster }); } }); @@ -560,7 +299,7 @@ }, compact: true }, - outofbandmanagementpowerstate: { + powerstate: { label: 'label.metrics.outofbandmanagementpowerstate', converter: function (str) { // For localization @@ -580,25 +319,25 @@ label: 'label.metrics.cpu.usage', collapsible: true, columns: { - cores: { - label: 'label.metrics.num.cpu.cores' + cpunumber: { + label: 'label.metrics.num.cpu.cores', }, - cputotal: { + cputotalghz: { label: 'label.metrics.cpu.total' }, - cpuusedavg: { + cpuusedghz: { label: 'label.metrics.cpu.used.avg', thresholdcolor: true, thresholds: { - notification: 'cpunotificationthreshold', + notification: 'cputhreshold', disable: 'cpudisablethreshold' } }, - cpuallocated: { + cpuallocatedghz: { label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'cpuallocatednotificationthreshold', + notification: 'cpuallocatedthreshold', disable: 'cpuallocateddisablethreshold' } } @@ -608,23 +347,23 @@ label: 'label.metrics.memory.usage', collapsible: true, columns: { - memtotal: { + memorytotalgb: { label: 'label.metrics.memory.total' }, - memusedavg: { + memoryusedgb: { label: 'label.metrics.memory.used.avg', thresholdcolor: true, thresholds: { - notification: 'memnotificationthreshold', - disable: 'memdisablethreshold' + notification: 'memorythreshold', + disable: 'memorydisablethreshold' } }, - memallocated: { + memoryallocatedgb: { label: 'label.metrics.allocated', thresholdcolor: true, thresholds: { - notification: 'memallocatednotificationthreshold', - disable: 'memallocateddisablethreshold' + notification: 'memoryallocatedthreshold', + disable: 'memoryallocateddisablethreshold' } } } @@ -670,123 +409,11 @@ } $.ajax({ - url: createURL('listHosts'), + url: createURL('listHostsMetrics'), data: data, success: function(json) { - var items = json.listhostsresponse.host; - if (items) { - $.each(items, function(idx, host) { - if (host && host.outofbandmanagement) { - items[idx].outofbandmanagementpowerstate = host.outofbandmanagement.powerstate; - } - items[idx].cores = host.cpunumber; - items[idx].cputotal = (parseFloat(host.cpunumber) * parseFloat(host.cpuspeed) / 1000.0).toFixed(2); - if (host.cpuused) { - items[idx].cpuusedavg = (parseFloat(host.cpuused) * items[idx].cputotal / 100.0).toFixed(2) + ' Ghz'; - } else { - items[idx].cpuusedavg = ''; - } - items[idx].cpuallocated = (parseFloat(host.cpuallocated) * items[idx].cputotal / 100.0).toFixed(2) + ' Ghz'; - items[idx].memtotal = (parseFloat(host.memorytotal)/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - items[idx].memallocated = (parseFloat(host.memoryallocated)/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - if (host.memoryused) { - items[idx].memusedavg = (parseFloat(host.memoryused)/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - } else { - items[idx].memusedavg = ''; - } - if (host.networkkbsread && host.networkkbswrite) { - items[idx].networkread = (parseFloat(host.networkkbsread)/(1024.0*1024.0)).toFixed(2) + ' GB'; - items[idx].networkwrite = (parseFloat(host.networkkbswrite)/(1024.0*1024.0)).toFixed(2) + ' GB'; - } else { - items[idx].networkread = ''; - items[idx].networkwrite = ''; - } - - var cpuOverCommit = 1.0; - var memOverCommit = 1.0; - $.ajax({ - url: createURL('listClusters'), - data: {clusterid: host.clusterid, listAll: true}, - success: function(json) { - if (json.listclustersresponse && json.listclustersresponse.cluster) { - var cluster = json.listclustersresponse.cluster[0]; - cpuOverCommit = parseFloat(cluster.cpuovercommitratio); - memOverCommit = parseFloat(cluster.memoryovercommitratio); - } - }, - async: false - }); - - // Threshold color coding - items[idx].cpunotificationthreshold = 0.75 * parseFloat(items[idx].cputotal); - items[idx].cpudisablethreshold = 0.95 * parseFloat(items[idx].cputotal); - items[idx].cpuallocatednotificationthreshold = 0.75 * cpuOverCommit * parseFloat(items[idx].cputotal); - items[idx].cpuallocateddisablethreshold = 0.95 * cpuOverCommit * parseFloat(items[idx].cputotal); - - items[idx].memnotificationthreshold = 0.75 * parseFloat(items[idx].memtotal); - items[idx].memdisablethreshold = 0.95 * parseFloat(items[idx].memtotal); - items[idx].memallocatednotificationthreshold = 0.75 * memOverCommit * parseFloat(items[idx].memtotal); - items[idx].memallocateddisablethreshold = 0.95 * memOverCommit * parseFloat(items[idx].memtotal); - - $.ajax({ - url: createURL('listConfigurations'), - data: {clusterid: host.clusterid, listAll: true}, - success: function(json) { - if (json.listconfigurationsresponse && json.listconfigurationsresponse.configuration) { - $.each(json.listconfigurationsresponse.configuration, function(i, config) { - switch (config.name) { - case 'cluster.cpu.allocated.capacity.disablethreshold': - items[idx].cpudisablethreshold = parseFloat(config.value) * parseFloat(items[idx].cputotal); - items[idx].cpuallocateddisablethreshold = parseFloat(config.value) * cpuOverCommit * parseFloat(items[idx].cputotal); - break; - case 'cluster.cpu.allocated.capacity.notificationthreshold': - items[idx].cpunotificationthreshold = parseFloat(config.value) * parseFloat(items[idx].cputotal); - items[idx].cpuallocatednotificationthreshold = parseFloat(config.value) * cpuOverCommit * parseFloat(items[idx].cputotal); - break; - case 'cluster.memory.allocated.capacity.disablethreshold': - items[idx].memdisablethreshold = parseFloat(config.value) * parseFloat(items[idx].memtotal); - items[idx].memallocateddisablethreshold = parseFloat(config.value) * memOverCommit * parseFloat(items[idx].memtotal); - break; - case 'cluster.memory.allocated.capacity.notificationthreshold': - items[idx].memnotificationthreshold = parseFloat(config.value) * parseFloat(items[idx].memtotal); - items[idx].memallocatednotificationthreshold = parseFloat(config.value) * memOverCommit * parseFloat(items[idx].memtotal); - break; - } - }); - } - }, - async: false - }); - - - items[idx].cputotal = items[idx].cputotal + ' Ghz (x' + cpuOverCommit + ')'; - items[idx].memtotal = items[idx].memtotal + ' (x' + memOverCommit + ')'; - - items[idx].instances = 0; - items[idx].instancesUp = 0; - $.ajax({ - url: createURL('listVirtualMachines'), - data: {hostid: host.id, listAll: true}, - success: function(json) { - if (json && json.listvirtualmachinesresponse && json.listvirtualmachinesresponse.virtualmachine) { - var vms = json.listvirtualmachinesresponse.virtualmachine; - if (vms) { - $.each(vms, function(_, vm) { - items[idx].instances += 1; - if (vm.state == 'Running') { - items[idx].instancesUp += 1; - } - }); - } - } - }, - async: false - }); - items[idx].instances = items[idx].instancesUp + ' / ' + items[idx].instances; - }); - } args.response.success({ - data: items + data: json.listhostsmetricsresponse.host }); } }); @@ -838,14 +465,14 @@ label: 'label.metrics.cpu.usage', collapsible: true, columns: { - cores: { - label: 'label.metrics.num.cpu.cores' + cpunumber: { + label: 'label.metrics.num.cpu.cores', }, cputotal: { label: 'label.metrics.cpu.total' }, cpuused: { - label: 'label.metrics.cpu.used.avg' + label: 'label.metrics.cpu.used.avg', } } }, @@ -853,7 +480,7 @@ label: 'label.metrics.memory.usage', collapsible: true, columns: { - memallocated: { + memorytotal: { label: 'label.metrics.allocated' } } @@ -874,10 +501,10 @@ label: 'label.metrics.disk.usage', collapsible: true, columns: { - diskread: { + diskioread: { label: 'label.metrics.disk.read' }, - diskwrite: { + diskiowrite: { label: 'label.metrics.disk.write' }, diskiopstotal: { @@ -899,45 +526,11 @@ } $.ajax({ - url: createURL('listVirtualMachines'), + url: createURL('listVirtualMachinesMetrics'), data: data, success: function(json) { - var items = []; - if (json && json.listvirtualmachinesresponse && json.listvirtualmachinesresponse.virtualmachine) { - items = json.listvirtualmachinesresponse.virtualmachine; - $.each(items, function(idx, vm) { - items[idx].cores = vm.cpunumber; - items[idx].cputotal = (parseFloat(vm.cpunumber) * parseFloat(vm.cpuspeed) / 1000.0).toFixed(1) + ' Ghz'; - items[idx].cpuusedavg = vm.cpuused; - items[idx].cpuallocated = vm.cpuallocated; - items[idx].memallocated = (parseFloat(vm.memory)/1024.0).toFixed(2) + ' GB'; - items[idx].networkread = (parseFloat(vm.networkkbsread)/(1024.0)).toFixed(2) + ' MB'; - items[idx].networkwrite = (parseFloat(vm.networkkbswrite)/(1024.0)).toFixed(2) + ' MB'; - items[idx].diskread = (parseFloat(vm.diskkbsread)/(1024.0)).toFixed(2) + ' MB'; - items[idx].diskwrite = (parseFloat(vm.diskkbswrite)/(1024.0)).toFixed(2) + ' MB'; - items[idx].diskiopstotal = parseFloat(vm.diskioread) + parseFloat(vm.diskiowrite); - if (vm.nic && vm.nic.length > 0 && vm.nic[0].ipaddress) { - items[idx].ipaddress = vm.nic[0].ipaddress; - } - - var keys = [{'cpuused': 'cpuusedavg'}, - {'networkkbsread': 'networkread'}, - {'networkkbswrite': 'networkwrite'}, - {'diskkbsread': 'diskread'}, - {'diskkbswrite': 'diskwrite'}, - {'diskioread': 'diskiopstotal'}]; - for (keyIdx in keys) { - var map = keys[keyIdx]; - var key = Object.keys(map)[0]; - var uiKey = map[key]; - if (!vm.hasOwnProperty(key)) { - items[idx][uiKey] = ''; - } - } - }); - } args.response.success({ - data: items + data: json.listvirtualmachinesmetricsresponse.virtualmachine }); } }); @@ -974,22 +567,22 @@ 'Expunging': 'off', 'Migrating': 'warning', 'UploadOp': 'transition', - 'Snapshotting': 'warning' + 'Snapshotting': 'warning', }, compact: true }, vmname: { label: 'label.metrics.vm.name' }, - disksize: { + sizegb: { label: 'label.metrics.disk.size' }, storagetype: { label: 'label.metrics.disk.storagetype' }, - storagepool: { + storage: { label: 'label.metrics.storagepool' - } + }, }, dataProvider: function(args) { var data = {listAll: true}; @@ -1008,25 +601,11 @@ } $.ajax({ - url: createURL('listVolumes'), + url: createURL('listVolumesMetrics'), data: data, success: function(json) { - var items = []; - if (json && json.listvolumesresponse && json.listvolumesresponse.volume) { - items = json.listvolumesresponse.volume; - $.each(items, function(idx, volume) { - items[idx].name = volume.name; - items[idx].state = volume.state; - items[idx].vmname = volume.vmname; - items[idx].disksize = parseFloat(volume.size)/(1024.0*1024.0*1024.0) + ' GB'; - items[idx].storagetype = volume.storagetype.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}) + ' (' + volume.type + ')'; - if (volume.storage) { - items[idx].storagepool = volume.storage; - } - }); - } args.response.success({ - data: items + data: json.listvolumesmetricsresponse.volume }); } }); @@ -1062,7 +641,7 @@ 'ErrorInMaintenance': 'off', 'PrepareForMaintenance': 'transition', 'CancelMaintenance': 'warning', - 'Maintenance': 'warning' + 'Maintenance': 'warning', }, compact: true }, @@ -1078,26 +657,26 @@ label: 'label.metrics.disk', collapsible: true, columns: { - disksizeused: { + disksizeusedgb: { label: 'label.metrics.disk.used', thresholdcolor: true, thresholds: { - notification: 'storagenotificationthreshold', - disable: 'storagedisablethreshold' + notification: 'storageusagethreshold', + disable: 'storageusagedisablethreshold' } }, - disksizetotal: { + disksizetotalgb: { label: 'label.metrics.disk.total' }, - disksizeallocated: { + disksizeallocatedgb: { label: 'label.metrics.disk.allocated', thresholdcolor: true, thresholds: { - notification: 'storageallocatednotificationthreshold', + notification: 'storageallocatedthreshold', disable: 'storageallocateddisablethreshold' } }, - disksizeunallocated: { + disksizeunallocatedgb: { label: 'label.metrics.disk.unallocated' } } @@ -1124,74 +703,11 @@ } $.ajax({ - url: createURL('listStoragePools'), + url: createURL('listStoragePoolsMetrics'), data: data, success: function(json) { - var items = []; - if (json && json.liststoragepoolsresponse && json.liststoragepoolsresponse.storagepool) { - items = json.liststoragepoolsresponse.storagepool; - $.each(items, function(idx, pool) { - items[idx].name = pool.name; - items[idx].state = pool.state; - items[idx].scope = pool.scope; - items[idx].type = pool.type; - items[idx].overprovisionfactor = parseFloat(pool.overprovisionfactor); - if (pool.disksizeused) { - items[idx].disksizeused = (parseFloat(pool.disksizeused)/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - } else { - items[idx].disksizeused = ''; - } - items[idx].disksizetotal = parseFloat(pool.disksizetotal); - items[idx].disksizeallocated = parseFloat(pool.disksizeallocated); - items[idx].disksizeunallocated = (items[idx].overprovisionfactor * items[idx].disksizetotal) - items[idx].disksizeallocated; - - // Format presentation - items[idx].disksizetotal = (items[idx].disksizetotal/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB (x' + items[idx].overprovisionfactor + ')'; - items[idx].disksizeallocated = (items[idx].disksizeallocated/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - items[idx].disksizeunallocated = (items[idx].disksizeunallocated/(1024.0*1024.0*1024.0)).toFixed(2) + ' GB'; - - // Threshold color coding - items[idx].storagenotificationthreshold = 0.75 * parseFloat(items[idx].disksizetotal); - items[idx].storagedisablethreshold = 0.95 * parseFloat(items[idx].disksizetotal); - items[idx].storageallocatednotificationthreshold = 0.75 * parseFloat(items[idx].disksizetotal) * items[idx].overprovisionfactor; - items[idx].storageallocateddisablethreshold = 0.95 * parseFloat(items[idx].disksizetotal) * items[idx].overprovisionfactor; - - - var getThresholds = function(data, items, idx) { - data.listAll = true; - $.ajax({ - url: createURL('listConfigurations'), - data: data, - success: function(json) { - if (json.listconfigurationsresponse && json.listconfigurationsresponse.configuration) { - $.each(json.listconfigurationsresponse.configuration, function(i, config) { - switch (config.name) { - case 'cluster.storage.allocated.capacity.notificationthreshold': - items[idx].storageallocatednotificationthreshold = parseFloat(config.value) * items[idx].overprovisionfactor * parseFloat(items[idx].disksizetotal); - break; - case 'cluster.storage.capacity.notificationthreshold': - items[idx].storagenotificationthreshold = parseFloat(config.value) * parseFloat(items[idx].disksizetotal); - break; - case 'pool.storage.allocated.capacity.disablethreshold': - items[idx].storageallocateddisablethreshold = parseFloat(config.value) * items[idx].overprovisionfactor * parseFloat(items[idx].disksizetotal); - break; - case 'pool.storage.capacity.disablethreshold': - items[idx].storagedisablethreshold = parseFloat(config.value) * parseFloat(items[idx].disksizetotal); - break; - } - }); - } - }, - async: false - }); - }; - // Update global and cluster level thresholds - getThresholds({}, items, idx); - getThresholds({clusterid: pool.clusterid}, items, idx); - }); - } args.response.success({ - data: items + data: json.liststoragepoolsmetricsresponse.storagepool }); } }); diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 98403ed9cf6..682e0a2263a 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -225,322 +225,25 @@ // System dashboard dashboard: { dataProvider: function (args) { - var dataFns = { - zoneCount: function (data) { - $.ajax({ - url: createURL('listZones'), - data: { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }, - success: function (json) { - args.response.success({ - data: { - zoneCount: json.listzonesresponse.count ? json.listzonesresponse.count: 0, - zones: json.listzonesresponse.zone - } - }); - } + $.ajax({ + url: createURL('listInfrastructure'), + success: function (json) { + var response = json.listinfrastructureresponse.infrastructure; + var data = {}; + data.zoneCount = response.zones; + data.podCount = response.pods; + data.clusterCount = response.clusters; + data.hostCount = response.hosts; + data.primaryStorageCount = response.storagepools; + data.secondaryStorageCount = response.imagestores; + data.systemVmCount = response.systemvms; + data.virtualRouterCount = response.routers; + data.socketCount = response.cpusockets; + args.response.success({ + data: data }); - dataFns.podCount(); - }, - - podCount: function (data) { - $.ajax({ - url: createURL('listPods'), - data: { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }, - success: function (json) { - args.response.success({ - data: { - podCount: json.listpodsresponse.count ? json.listpodsresponse.count: 0 - } - }); - } - }); - dataFns.clusterCount(); - }, - - clusterCount: function (data) { - $.ajax({ - url: createURL('listClusters'), - data: { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }, - success: function (json) { - args.response.success({ - data: { - clusterCount: json.listclustersresponse.count ? json.listclustersresponse.count: 0 - } - }); - } - }); - dataFns.hostCount(); - }, - - hostCount: function (data) { - var data2 = { - type: 'routing', - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }; - $.ajax({ - url: createURL('listHosts'), - data: data2, - success: function (json) { - args.response.success({ - data: { - hostCount: json.listhostsresponse.count ? json.listhostsresponse.count: 0 - } - }); - } - }); - dataFns.primaryStorageCount(); - }, - - primaryStorageCount: function (data) { - var data2 = { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }; - $.ajax({ - url: createURL('listStoragePools'), - data: data2, - success: function (json) { - args.response.success({ - data: { - primaryStorageCount: json.liststoragepoolsresponse.count ? json.liststoragepoolsresponse.count: 0 - } - }); - } - }); - dataFns.secondaryStorageCount(); - }, - - secondaryStorageCount: function (data) { - var data2 = { - type: 'SecondaryStorage', - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }; - $.ajax({ - url: createURL('listImageStores'), - data: data2, - success: function (json) { - args.response.success({ - data: { - secondaryStorageCount: json.listimagestoresresponse.imagestore ? json.listimagestoresresponse.count: 0 - } - }); - } - }); - dataFns.systemVmCount(); - }, - - systemVmCount: function (data) { - $.ajax({ - url: createURL('listSystemVms'), - data: { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }, - success: function (json) { - args.response.success({ - data: { - systemVmCount: json.listsystemvmsresponse.count ? json.listsystemvmsresponse.count: 0 - } - }); - } - }); - dataFns.virtualRouterCount(); - }, - - virtualRouterCount: function (data) { - var data2 = { - listAll: true, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }; - $.ajax({ - url: createURL('listRouters'), - data: data2, - success: function (json) { - var total1 = json.listroutersresponse.count ? json.listroutersresponse.count: 0; - var total2 = 0; //reset - - /* - * In project view, the first listRotuers API(without projectid=-1) will return the same objects as the second listRouters API(with projectid=-1), - * because in project view, all API calls are appended with projectid=[projectID]. - * Therefore, we only call the second listRouters API(with projectid=-1) in non-project view. - */ - if (cloudStack.context && cloudStack.context.projects == null) { //non-project view - var data3 = { - listAll: true, - projectid: -1, - page: 1, - pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property. - }; - $.ajax({ - url: createURL('listRouters'), - data: data3, - async: false, - success: function (json) { - total2 = json.listroutersresponse.count ? json.listroutersresponse.count : 0; - } - }); - } - - args.response.success({ - data: { - virtualRouterCount: (total1 + total2) - } - }); - } - }); - dataFns.capacity(); - }, - - capacity: function (data) { - $.ajax({ - url: createURL('listCapacity'), - success: function (json) { - var capacities = json.listcapacityresponse.capacity; - if(capacities) { - var capacityTotal = function (id, converter) { - var capacity = $.grep(capacities, function (capacity) { - return capacity.type == id; - })[0]; - - var total = capacity ? capacity.capacitytotal: 0; - - if (converter) { - return converter(total); - } - - return total; - }; - - args.response.success({ - data: { - cpuCapacityTotal: capacityTotal(1, cloudStack.converters.convertHz), - memCapacityTotal: capacityTotal(0, cloudStack.converters.convertBytes), - storageCapacityTotal: capacityTotal(2, cloudStack.converters.convertBytes) - } - }); - - } else { - - args.response.success({ - data: { - cpuCapacityTotal: cloudStack.converters.convertHz(0), - memCapacityTotal: cloudStack.converters.convertBytes(0), - storageCapacityTotal: cloudStack.converters.convertBytes(0) - } - }); - - } - } - }); - - dataFns.socketInfo(); - }, - - socketInfo: function (data) { - var socketCount = 0; - - function listHostFunction(hypervisor, pageSizeValue) { - var deferred = $.Deferred(); - var totalHostCount = 0; - var returnedHostCount = 0; - var returnedHostCpusocketsSum = 0; - - var callListHostsWithPage = function(page) { - $.ajax({ - url: createURL('listHosts'), - data: { - type: 'routing', - hypervisor: hypervisor, - page: page, - details: 'min', - pagesize: pageSizeValue - }, - success: function (json) { - if (json.listhostsresponse.count == undefined) { - deferred.resolve(); - return; - } - - totalHostCount = json.listhostsresponse.count; - returnedHostCount += json.listhostsresponse.host.length; - - var items = json.listhostsresponse.host; - for (var i = 0; i < items.length; i++) { - if (items[i].cpusockets != undefined && isNaN(items[i].cpusockets) == false) { - returnedHostCpusocketsSum += items[i].cpusockets; - } - } - - if (returnedHostCount < totalHostCount) { - callListHostsWithPage(++page); - } else { - socketCount += returnedHostCpusocketsSum; - deferred.resolve(); - } - } - }); - } - - callListHostsWithPage(1); - - return deferred; - - } - - $.ajax({ - url: createURL('listConfigurations'), - data: { - name : 'default.page.size' - }, - success: function (json) { - pageSizeValue = json.listconfigurationsresponse.configuration[0].value; - if(!pageSizeValue) { - return; - } - $.ajax({ - url: createURL('listHypervisors'), - success: function (json) { - var deferredArray = []; - - $(json.listhypervisorsresponse.hypervisor).map(function (index, hypervisor) { - deferredArray.push(listHostFunction(hypervisor.name, pageSizeValue)); - }); - - $.when.apply(null, deferredArray).then(function(){ - args.response.success({ - data: { - socketCount: socketCount - } - }); - }); - } - }); - } - }); - } - }; - - dataFns.zoneCount(); + }); } }, diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index e61f43c8372..fed61943861 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -1245,12 +1245,11 @@ if (field.thresholdcolor && field.thresholds) { if ((field.thresholds.disable in dataItem) && (field.thresholds.notification in dataItem)) { - var disableThreshold = parseFloat(dataItem[field.thresholds.disable]); - var notificationThreshold = parseFloat(dataItem[field.thresholds.notification]); - var value = parseFloat(content); - if (value >= disableThreshold) { + var disableThreshold = dataItem[field.thresholds.disable]; + var notificationThreshold = dataItem[field.thresholds.notification]; + if (disableThreshold) { $td.addClass('alert-disable-threshold'); - } else if (value >= notificationThreshold) { + } else if (notificationThreshold) { $td.addClass('alert-notification-threshold'); } }