You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ra...@apache.org on 2017/04/06 06:35:54 UTC

[1/4] git commit: updated refs/heads/4.9 to 6548839

Repository: cloudstack
Updated Branches:
  refs/heads/4.9 9bf428162 -> 654883941


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/ui/scripts/metrics.js
----------------------------------------------------------------------
diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js
index 554aab7..3152af7 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
                         });
                     }
                 });

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 98403ed..682e0a2 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
-                                    }
-                                });
-                            }
-                        });
-                        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
-                                                }
-                                            });
-                                        });
-                                    }
-                                });
-                            }
+                $.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.zoneCount();
+                });
             }
         },
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/ui/scripts/ui/widgets/listView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js
index e61f43c..fed6194 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');
                         }
                     }


[3/4] git commit: updated refs/heads/4.9 to 6548839

Posted by ra...@apache.org.
CLOUDSTACK-9783: Improve metrics view performance

This improves the metrics view feature by improving the rendering performance
of metrics view tables, by reimplementing the logic at the backend and data
served via APIs. In large environments, the older implementation would
make several API calls that increases both network and database load.

List of APIs introduced for improving the performance:

    listClustersMetrics
    listHostsMetrics
    listInfrastructure
    listStoragePoolsMetrics
    listVMsMetrics
    listVolumesMetrics
    listZonesMetrics

Signed-off-by: Rohit Yadav <ro...@shapeblue.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/40225350
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/40225350
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/40225350

Branch: refs/heads/4.9
Commit: 402253504e9520104caf9fbc1317042f2fd89474
Parents: b95bf8f
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Thu Feb 16 13:45:15 2017 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Tue Feb 28 13:45:03 2017 +0530

----------------------------------------------------------------------
 .travis.yml                                     |   1 +
 .../command/admin/cluster/ListClustersCmd.java  |  12 +-
 .../api/command/admin/host/ListHostsCmd.java    |  20 +-
 .../cloudstack/api/response/HostResponse.java   | 159 +++++
 .../cloudstack/api/response/NicResponse.java    |  84 ++-
 .../api/response/StoragePoolResponse.java       |   8 +
 .../cloudstack/api/response/UserVmResponse.java |  24 +
 .../cloudstack/api/response/VolumeResponse.java | 149 ++++-
 .../cloudstack/api/response/ZoneResponse.java   |  88 +++
 client/pom.xml                                  |   5 +
 .../schema/src/com/cloud/dc/dao/ClusterDao.java |   8 +-
 .../src/com/cloud/dc/dao/ClusterDaoImpl.java    |  28 +-
 .../schema/src/com/cloud/dc/dao/HostPodDao.java |   2 +-
 .../src/com/cloud/dc/dao/HostPodDaoImpl.java    |   6 +-
 plugins/metrics/pom.xml                         |  55 ++
 .../cloudstack/metrics/module.properties        |  18 +
 .../metrics/spring-metrics-context.xml          |  27 +
 .../cloudstack/api/ListClustersMetricsCmd.java  |  51 ++
 .../cloudstack/api/ListHostsMetricsCmd.java     |  54 ++
 .../cloudstack/api/ListInfrastructureCmd.java   |  52 ++
 .../api/ListStoragePoolsMetricsCmd.java         |  52 ++
 .../cloudstack/api/ListVMsMetricsCmd.java       |  51 ++
 .../cloudstack/api/ListVolumesMetricsCmd.java   |  51 ++
 .../cloudstack/api/ListZonesMetricsCmd.java     |  52 ++
 .../cloudstack/metrics/MetricsService.java      |  46 ++
 .../cloudstack/metrics/MetricsServiceImpl.java  | 563 +++++++++++++++++
 .../response/ClusterMetricsResponse.java        | 211 +++++++
 .../response/HostMetricsResponse.java           | 204 ++++++
 .../response/InfrastructureResponse.java        | 101 +++
 .../response/StoragePoolMetricsResponse.java    | 105 ++++
 .../cloudstack/response/VmMetricsResponse.java  | 108 ++++
 .../response/VolumeMetricsResponse.java         |  41 ++
 .../response/ZoneMetricsResponse.java           | 206 ++++++
 plugins/pom.xml                                 |   1 +
 .../com/cloud/api/query/dao/HostJoinDao.java    |   2 +
 .../cloud/api/query/dao/HostJoinDaoImpl.java    |  15 +
 .../deploy/DeploymentPlanningManagerImpl.java   |   2 +-
 test/integration/smoke/test_metrics_api.py      | 210 +++++++
 tools/apidoc/gen_toc.py                         |   4 +-
 ui/scripts/metrics.js                           | 626 +++----------------
 ui/scripts/system.js                            | 331 +---------
 ui/scripts/ui/widgets/listView.js               |   9 +-
 42 files changed, 2922 insertions(+), 920 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index da81633..b8fbf0a 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java
----------------------------------------------------------------------
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 432ca92..74ad764 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<ClusterResponse> getClusterResponses() {
         Pair<List<? extends Cluster>, Integer> result = _mgr.searchForClusters(this);
-        ListResponse<ClusterResponse> response = new ListResponse<ClusterResponse>();
         List<ClusterResponse> clusterResponses = new ArrayList<ClusterResponse>();
         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<ClusterResponse> clusterResponses = getClusterResponses();
+        ListResponse<ClusterResponse> response = new ListResponse<ClusterResponse>();
+        response.setResponses(clusterResponses, clusterResponses.size());
         response.setResponseName(getCommandName());
         this.setResponseObject(response);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java
----------------------------------------------------------------------
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 424fc05..3391fdc 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<HostResponse> response = null;
+    protected ListResponse<HostResponse> getHostResponses() {
+        ListResponse<HostResponse> response = new ListResponse<>();
         if (getVirtualMachineId() == null) {
             response = _queryService.searchForServers(this);
         } else {
             Pair<List<? extends Host>, Integer> result;
             Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>> hostsForMigration =
-                _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal());
+                    _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal());
             result = hostsForMigration.first();
             List<? extends Host> hostsWithCapacity = hostsForMigration.second();
-
-            response = new ListResponse<HostResponse>();
             List<HostResponse> hostResponses = new ArrayList<HostResponse>();
             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<HostResponse> response = getHostResponses();
         response.setResponseName(getCommandName());
         this.setResponseObject(response);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/HostResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java
index ab9c8c3..90fe800 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<GpuResponse> 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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/NicResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NicResponse.java b/api/src/org/apache/cloudstack/api/response/NicResponse.java
index 7335836..7689123 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<NicSecondaryIpResponse> getSecondaryIps() {
+        return secondaryIps;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public String getVmId() {
+        return vmId;
+    }
+
+    public String getNsxLogicalSwitch() {
+        return nsxLogicalSwitch;
+    }
+
+    public String getNsxLogicalSwitchPort() {
+        return nsxLogicalSwitchPort;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
index 3571866..b7f7d0b 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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
index b681d4f..2ff1eaa 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<Long> getTagIds() {
+        return tagIds;
+    }
+
+    public void setTagIds(Set<Long> 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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
index a934563..e25adf6 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<ResourceTagResponse> 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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/api/src/org/apache/cloudstack/api/response/ZoneResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java
index 4266077..61bab02 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<CapacityResponse> getCapacitites() {
+        return capacitites;
+    }
+
+    public boolean isLocalStorageEnabled() {
+        return localStorageEnabled;
+    }
+
+    public Set<ResourceTagResponse> getTags() {
+        return tags;
+    }
+
+    public Map<String, String> getResourceDetails() {
+        return resourceDetails;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index d5ddd65..1f246ff 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -103,6 +103,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-plugin-metrics</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
       <artifactId>cloud-plugin-network-nvp</artifactId>
       <version>${project.version}</version>
     </dependency>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
index 06bc5a3..de8d604 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<ClusterVO, Long> {
     List<ClusterVO> listByPodId(long podId);
 
@@ -44,7 +44,7 @@ public interface ClusterDao extends GenericDao<ClusterVO, Long> {
 
     List<ClusterVO> listClustersByDcId(long zoneId);
 
-    List<Long> listAllCusters(long zoneId);
+    List<Long> listAllClusters(Long zoneId);
 
     boolean getSupportsResigning(long clusterId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
index 0c5bd6f..b1fce61 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<ClusterVO, Long> implements ClusterDao {
@@ -259,9 +257,11 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
     }
 
     @Override
-    public List<Long> listAllCusters(long zoneId) {
+    public List<Long> listAllClusters(Long zoneId) {
         SearchCriteria<Long> sc = ClusterIdSearch.create();
-        sc.setParameters("dataCenterId", zoneId);
+        if (zoneId != null) {
+            sc.setParameters("dataCenterId", zoneId);
+        }
         return customSearch(sc, null);
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/engine/schema/src/com/cloud/dc/dao/HostPodDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDao.java b/engine/schema/src/com/cloud/dc/dao/HostPodDao.java
index 39c8a49..1a000d8 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<HostPodVO, Long> {
 
     public List<Long> listDisabledPods(long zoneId);
 
-    public List<Long> listAllPods(long zoneId);
+    public List<Long> listAllPods(Long zoneId);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/HostPodDaoImpl.java
index 8d689e3..1c83b3a 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<HostPodVO, Long> implements H
     }
 
     @Override
-    public List<Long> listAllPods(long zoneId) {
+    public List<Long> listAllPods(Long zoneId) {
         SearchCriteria<Long> sc = PodIdSearch.create();
-        sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
+        if (zoneId != null) {
+            sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, zoneId);
+        }
         return customSearch(sc, null);
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/metrics/pom.xml b/plugins/metrics/pom.xml
new file mode 100644
index 0000000..946b235
--- /dev/null
+++ b/plugins/metrics/pom.xml
@@ -0,0 +1,55 @@
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+  http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-plugin-metrics</artifactId>
+  <name>Apache CloudStack Plugin - Metrics</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-plugins</artifactId>
+    <version>4.9.3.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <argLine>-Xmx1024m</argLine>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/resources/META-INF/cloudstack/metrics/module.properties
----------------------------------------------------------------------
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 0000000..149b83a
--- /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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/resources/META-INF/cloudstack/metrics/spring-metrics-context.xml
----------------------------------------------------------------------
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 0000000..6584641
--- /dev/null
+++ b/plugins/metrics/resources/META-INF/cloudstack/metrics/spring-metrics-context.xml
@@ -0,0 +1,27 @@
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd"
+>
+
+    <bean id="metricsService" class="org.apache.cloudstack.metrics.MetricsServiceImpl" >
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListClustersMetricsCmd.java
----------------------------------------------------------------------
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 0000000..ef259e1
--- /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<ClusterMetricsResponse> metricsResponses = metricsService.listClusterMetrics(getClusterResponses());
+        ListResponse<ClusterMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListHostsMetricsCmd.java
----------------------------------------------------------------------
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 0000000..9010063
--- /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<HostMetricsResponse> metricsResponses = metricsService.listHostMetrics(getHostResponses().getResponses());
+        ListResponse<HostMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListInfrastructureCmd.java
----------------------------------------------------------------------
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 0000000..4ea24c3
--- /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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListStoragePoolsMetricsCmd.java
----------------------------------------------------------------------
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 0000000..4206568
--- /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<StoragePoolMetricsResponse> metricsResponses = metricsService.listStoragePoolMetrics(_queryService.searchForStoragePools(this).getResponses());
+        ListResponse<StoragePoolMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListVMsMetricsCmd.java
----------------------------------------------------------------------
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 0000000..2321f51
--- /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<VmMetricsResponse> metricsResponses = metricsService.listVmMetrics(_queryService.searchForUserVMs(this).getResponses());
+        ListResponse<VmMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListVolumesMetricsCmd.java
----------------------------------------------------------------------
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 0000000..54ac922
--- /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<VolumeMetricsResponse> metricsResponses = metricsService.listVolumeMetrics(_queryService.searchForVolumes(this).getResponses());
+        ListResponse<VolumeMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/api/ListZonesMetricsCmd.java
----------------------------------------------------------------------
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 0000000..1a51a5f
--- /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<ZoneMetricsResponse> metricsResponses = metricsService.listZoneMetrics(_queryService.listDataCenters(this).getResponses());
+        ListResponse<ZoneMetricsResponse> response = new ListResponse<>();
+        response.setResponses(metricsResponses, metricsResponses.size());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsService.java
----------------------------------------------------------------------
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 0000000..deb1da8
--- /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<VolumeMetricsResponse> listVolumeMetrics(List<VolumeResponse> volumeResponses);
+    List<VmMetricsResponse> listVmMetrics(List<UserVmResponse> vmResponses);
+    List<StoragePoolMetricsResponse> listStoragePoolMetrics(List<StoragePoolResponse> poolResponses);
+    List<HostMetricsResponse> listHostMetrics(List<HostResponse> poolResponses);
+    List<ClusterMetricsResponse> listClusterMetrics(List<ClusterResponse> poolResponses);
+    List<ZoneMetricsResponse> listZoneMetrics(List<ZoneResponse> poolResponses);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/metrics/MetricsServiceImpl.java
----------------------------------------------------------------------
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 0000000..5cab7bc
--- /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<VolumeMetricsResponse> listVolumeMetrics(List<VolumeResponse> volumeResponses) {
+        final List<VolumeMetricsResponse> 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<VmMetricsResponse> listVmMetrics(List<UserVmResponse> vmResponses) {
+        final List<VmMetricsResponse> 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<StoragePoolMetricsResponse> listStoragePoolMetrics(List<StoragePoolResponse> poolResponses) {
+        final List<StoragePoolMetricsResponse> 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<HostMetricsResponse> listHostMetrics(List<HostResponse> hostResponses) {
+        final List<HostMetricsResponse> 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<CapacityDaoImpl.SummedCapacity> capacities = capacityDao.findCapacityBy(capacityType, zoneId, null, clusterId);
+        if (capacities == null || capacities.size() < 1) {
+            return null;
+        }
+        return capacities.get(0);
+    }
+
+    @Override
+    public List<ClusterMetricsResponse> listClusterMetrics(List<ClusterResponse> clusterResponses) {
+        final List<ClusterMetricsResponse> 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<ZoneMetricsResponse> listZoneMetrics(List<ZoneResponse> zoneResponses) {
+        final List<ZoneMetricsResponse> 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<Class<?>> getCommands() {
+        List<Class<?>> cmdList = new ArrayList<Class<?>>();
+        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;
+        }
+    }
+
+}


[4/4] git commit: updated refs/heads/4.9 to 6548839

Posted by ra...@apache.org.
Merge pull request #1944 from shapeblue/4.9-metrics-enhancement

CLOUDSTACK-9783: Improve metrics view performanceThis improves the metrics view feature by improving the rendering performance
of metrics view tables, by re-implementing the logic at the backend and data
served via APIs. In large environments, the older implementation would
make several API calls that increases both network and database load.

List of APIs introduced for improving the performance that re-implement the frontend logic at backend:

    listClustersMetrics
    listHostsMetrics
    listInfrastructure
    listStoragePoolsMetrics
    listVMsMetrics
    listVolumesMetrics
    listZonesMetrics

Pinging for review - @abhinandanprateek @DaanHoogland @borisstoyanov @karuturi @rashmidixit

Marvin test results:

=== TestName: test_list_clusters_metrics | Status : SUCCESS ===

=== TestName: test_list_hosts_metrics | Status : SUCCESS ===

=== TestName: test_list_infrastructure_metrics | Status : SUCCESS ===

=== TestName: test_list_pstorage_metrics | Status : SUCCESS ===

=== TestName: test_list_vms_metrics | Status : SUCCESS ===

=== TestName: test_list_volumes_metrics | Status : SUCCESS ===

=== TestName: test_list_zones_metrics | Status : SUCCESS ===

* pr/1944:
  CLOUDSTACK-9783: Improve metrics view performance

Signed-off-by: Rajani Karuturi <ra...@accelerite.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/65488394
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/65488394
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/65488394

Branch: refs/heads/4.9
Commit: 6548839417013f58d9ed05a6550c74a057039134
Parents: 9bf4281 4022535
Author: Rajani Karuturi <ra...@accelerite.com>
Authored: Thu Apr 6 12:04:29 2017 +0530
Committer: Rajani Karuturi <ra...@accelerite.com>
Committed: Thu Apr 6 12:04:29 2017 +0530

----------------------------------------------------------------------
 .travis.yml                                     |   1 +
 .../command/admin/cluster/ListClustersCmd.java  |  12 +-
 .../api/command/admin/host/ListHostsCmd.java    |  20 +-
 .../cloudstack/api/response/HostResponse.java   | 159 +++++
 .../cloudstack/api/response/NicResponse.java    |  84 ++-
 .../api/response/StoragePoolResponse.java       |   8 +
 .../cloudstack/api/response/UserVmResponse.java |  24 +
 .../cloudstack/api/response/VolumeResponse.java | 149 ++++-
 .../cloudstack/api/response/ZoneResponse.java   |  88 +++
 client/pom.xml                                  |   5 +
 .../schema/src/com/cloud/dc/dao/ClusterDao.java |   8 +-
 .../src/com/cloud/dc/dao/ClusterDaoImpl.java    |  28 +-
 .../schema/src/com/cloud/dc/dao/HostPodDao.java |   2 +-
 .../src/com/cloud/dc/dao/HostPodDaoImpl.java    |   6 +-
 plugins/metrics/pom.xml                         |  55 ++
 .../cloudstack/metrics/module.properties        |  18 +
 .../metrics/spring-metrics-context.xml          |  27 +
 .../cloudstack/api/ListClustersMetricsCmd.java  |  51 ++
 .../cloudstack/api/ListHostsMetricsCmd.java     |  54 ++
 .../cloudstack/api/ListInfrastructureCmd.java   |  52 ++
 .../api/ListStoragePoolsMetricsCmd.java         |  52 ++
 .../cloudstack/api/ListVMsMetricsCmd.java       |  51 ++
 .../cloudstack/api/ListVolumesMetricsCmd.java   |  51 ++
 .../cloudstack/api/ListZonesMetricsCmd.java     |  52 ++
 .../cloudstack/metrics/MetricsService.java      |  46 ++
 .../cloudstack/metrics/MetricsServiceImpl.java  | 563 +++++++++++++++++
 .../response/ClusterMetricsResponse.java        | 211 +++++++
 .../response/HostMetricsResponse.java           | 204 ++++++
 .../response/InfrastructureResponse.java        | 101 +++
 .../response/StoragePoolMetricsResponse.java    | 105 ++++
 .../cloudstack/response/VmMetricsResponse.java  | 108 ++++
 .../response/VolumeMetricsResponse.java         |  41 ++
 .../response/ZoneMetricsResponse.java           | 206 ++++++
 plugins/pom.xml                                 |   1 +
 .../com/cloud/api/query/dao/HostJoinDao.java    |   2 +
 .../cloud/api/query/dao/HostJoinDaoImpl.java    |  15 +
 .../deploy/DeploymentPlanningManagerImpl.java   |   2 +-
 test/integration/smoke/test_metrics_api.py      | 210 +++++++
 tools/apidoc/gen_toc.py                         |   4 +-
 ui/scripts/metrics.js                           | 626 +++----------------
 ui/scripts/system.js                            | 331 +---------
 ui/scripts/ui/widgets/listView.js               |   9 +-
 42 files changed, 2922 insertions(+), 920 deletions(-)
----------------------------------------------------------------------



[2/4] git commit: updated refs/heads/4.9 to 6548839

Posted by ra...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/ClusterMetricsResponse.java
----------------------------------------------------------------------
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 0000000..dde1ab7
--- /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;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/HostMetricsResponse.java
----------------------------------------------------------------------
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 0000000..cdc9d16
--- /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);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/InfrastructureResponse.java
----------------------------------------------------------------------
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 0000000..a4db345
--- /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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/StoragePoolMetricsResponse.java
----------------------------------------------------------------------
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 0000000..f20f797
--- /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);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/VmMetricsResponse.java
----------------------------------------------------------------------
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 0000000..a4057ae
--- /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<NicResponse> 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;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/VolumeMetricsResponse.java
----------------------------------------------------------------------
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 0000000..ef8515f
--- /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));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/metrics/src/org/apache/cloudstack/response/ZoneMetricsResponse.java
----------------------------------------------------------------------
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 0000000..7156017
--- /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;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 40cee26..72a7bc1 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -69,6 +69,7 @@
     <module>hypervisors/ucs</module>
     <module>hypervisors/hyperv</module>
     <module>hypervisors/ovm3</module>
+    <module>metrics</module>
     <module>network-elements/elastic-loadbalancer</module>
     <module>network-elements/ovs</module>
     <module>network-elements/juniper-contrail</module>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/server/src/com/cloud/api/query/dao/HostJoinDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/HostJoinDao.java b/server/src/com/cloud/api/query/dao/HostJoinDao.java
index f0ac183..e7dc5d5 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<HostJoinVO, Long> {
 
     List<HostJoinVO> searchByIds(Long... ids);
 
+    List<HostJoinVO> findByClusterId(Long clusterId, Host.Type type);
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
index 6c15a8b..58a0366 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<HostJoinVO, Long> implements
 
     private final SearchBuilder<HostJoinVO> hostIdSearch;
 
+    private final SearchBuilder<HostJoinVO> ClusterSearch;
+
     protected HostJoinDaoImpl() {
 
         hostSearch = createSearchBuilder();
@@ -75,6 +77,11 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> 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<HostJoinVO, Long> implements
         return uvList;
     }
 
+    @Override
+    public List<HostJoinVO> findByClusterId(Long clusterId, Host.Type type) {
+        SearchCriteria<HostJoinVO> sc = ClusterSearch.create();
+        sc.setParameters("clusterId", clusterId);
+        sc.setParameters("type", type);
+        return listBy(sc);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index ef0ad19..80c417e 100644
--- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -588,7 +588,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
         List<Long> allDedicatedPods = _dedicatedDao.listAllPods();
         allPodsInDc.retainAll(allDedicatedPods);
 
-        List<Long> allClustersInDc = _clusterDao.listAllCusters(dc.getId());
+        List<Long> allClustersInDc = _clusterDao.listAllClusters(dc.getId());
         List<Long> allDedicatedClusters = _dedicatedDao.listAllClusters();
         allClustersInDc.retainAll(allDedicatedClusters);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/test/integration/smoke/test_metrics_api.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_metrics_api.py b/test/integration/smoke/test_metrics_api.py
new file mode 100644
index 0000000..27c4a1b
--- /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'))

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/40225350/tools/apidoc/gen_toc.py
----------------------------------------------------------------------
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index e6ef674..0fd9775 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',
     }