You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2015/11/20 07:17:40 UTC
[1/7] git commit: updated refs/heads/4.5 to 2f250e2
Repository: cloudstack
Updated Branches:
refs/heads/4.5 efe93d748 -> 2f250e269
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/ui-custom/metricsView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/metricsView.js b/ui/scripts/ui-custom/metricsView.js
new file mode 100644
index 0000000..ef5dbba
--- /dev/null
+++ b/ui/scripts/ui-custom/metricsView.js
@@ -0,0 +1,140 @@
+// 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.
+(function($, cloudStack) {
+
+ cloudStack.uiCustom.metricsView = function(args) {
+ return function() {
+ var metricsListView = cloudStack.sections.metrics.listView;
+ var metricsLabel = _l('label.metrics');
+
+ if (args.resource == 'zones') {
+ metricsListView = cloudStack.sections.metrics.zones.listView;
+ metricsLabel = _l('label.zones') + ' ' + metricsLabel;
+ } else if (args.resource == 'clusters') {
+ metricsListView = cloudStack.sections.metrics.clusters.listView;
+ metricsLabel = _l('label.clusters') + ' ' + metricsLabel;
+ } else if (args.resource == 'hosts') {
+ metricsListView = cloudStack.sections.metrics.hosts.listView;
+ metricsLabel = _l('label.hosts') + ' ' + metricsLabel;
+ } else if (args.resource == 'storagepool') {
+ metricsListView = cloudStack.sections.metrics.storagepool.listView;
+ metricsLabel = _l('label.primary.storage') + ' ' + metricsLabel;
+ } else if (args.resource == 'vms') {
+ metricsListView = cloudStack.sections.metrics.instances.listView;
+ metricsLabel = _l('label.instances') + ' ' + metricsLabel;
+ } else if (args.resource == 'volumes') {
+ metricsListView = cloudStack.sections.metrics.volumes.listView;
+ metricsLabel = _l('label.volumes') + ' ' + metricsLabel;
+ }
+
+ // list view refresh button
+ metricsListView.actions = {
+ refreshMetrics: {
+ label: 'label.refresh',
+ isHeader: true,
+ addRow: true,
+ action: {
+ custom: function (args) {
+ return function() {
+ };
+ }
+ }
+ }
+ };
+
+ metricsListView.hideSearchBar = true;
+ metricsListView.needsRefresh = true;
+ metricsListView.noSplit = true;
+ metricsListView.horizontalOverflow = true;
+ metricsListView.groupableColumns = true;
+
+ if (args.resource == 'volumes') {
+ metricsListView.groupableColumns = false;
+ }
+
+ var metricsContext = cloudStack.context;
+ if (metricsContext.metricsFilterData) {
+ delete metricsContext.metricsFilterData;
+ }
+ if (args.filterBy) {
+ metricsContext.metricsFilterData = {
+ key: args.filterBy,
+ value: args.id
+ };
+ }
+
+ var $browser = $('#browser .container');
+ return $browser.cloudBrowser('addPanel', {
+ title: metricsLabel,
+ maximizeIfSelected: true,
+ complete: function($newPanel) {
+ $newPanel.listView({
+ $browser: $browser,
+ context: metricsContext,
+ listView: metricsListView
+ });
+ // Make metrics tables horizontally scrollable
+ $newPanel.find('.list-view').css({'overflow-x': 'visible'});
+ // Refresh metrics when refresh button is clicked
+ $newPanel.find('.refreshMetrics').click(function() {
+ var sortedTh = $newPanel.find('table thead tr:last th.sorted');
+ var thIndex = sortedTh.index();
+ var thClassName = null;
+ var wasSorted = false;
+ var sortClassName = 'asc';
+ if (sortedTh && sortedTh.hasClass('sorted')) {
+ wasSorted = true;
+ var classes = sortedTh.attr('class').split(/\s+/);
+ thClassName = classes[0];
+ if (classes.indexOf('desc') > -1) {
+ sortClassName = 'desc';
+ }
+ }
+ $browser.cloudBrowser('removeLastPanel', {});
+ var refreshedPanel = cloudStack.uiCustom.metricsView(args)();
+ if (wasSorted && thClassName) {
+ refreshedPanel.find('th.' + thClassName).filter(function() {
+ return $(this).index() == thIndex;
+ }).addClass('sorted').addClass(sortClassName);
+ }
+ });
+
+ var filterMetricView = metricsListView.browseBy;
+ if (filterMetricView) {
+ $newPanel.bind('click', function(event) {
+ event.stopPropagation();
+ var $target = $(event.target);
+ var id = $target.closest('tr').data('list-view-item-id');
+ var jsonObj = $target.closest('tr').data('jsonObj');
+ if (filterMetricView.filterKey && jsonObj) {
+ if (jsonObj.hasOwnProperty(filterMetricView.filterKey)) {
+ id = jsonObj[filterMetricView.filterKey];
+ } else {
+ return; // return if provided key is missing
+ }
+ }
+ if (id && ($target.hasClass('first') || $target.parent().hasClass('first')) && ($target.is('td') || $target.parent().is('td'))) {
+ filterMetricView.id = id;
+ cloudStack.uiCustom.metricsView(filterMetricView)();
+ }
+ });
+ }
+ }
+ });
+ };
+ };
+})(jQuery, cloudStack);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/ui/widgets/cloudBrowser.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/cloudBrowser.js b/ui/scripts/ui/widgets/cloudBrowser.js
index 007025b..b7a5c38 100644
--- a/ui/scripts/ui/widgets/cloudBrowser.js
+++ b/ui/scripts/ui/widgets/cloudBrowser.js
@@ -321,6 +321,14 @@
return $panel;
},
+ removeLastPanel: function(args) {
+ $('div.panel:last').stop(); // Prevent destroyed panels from animating
+ this.element.find('div.panel:last').remove();
+ this.element.find('div.panel:last').removeClass('reduced');
+ $('#breadcrumbs').find('ul li:last').remove();
+ $('#breadcrumbs').find('ul div.end').remove();
+ },
+
/**
* Clear all panels
*/
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/ui/widgets/dataTable.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/dataTable.js b/ui/scripts/ui/widgets/dataTable.js
index 4c02531..22ddda6 100644
--- a/ui/scripts/ui/widgets/dataTable.js
+++ b/ui/scripts/ui/widgets/dataTable.js
@@ -141,49 +141,95 @@
* @param columnIndex Index of column (starting at 0) to sort by
*/
var sortTable = function(columnIndex) {
- return false;
var direction = 'asc';
- if ($table.find('thead th').hasClass('sorted ' + direction)) {
+ if ($table.find('thead tr:last th').hasClass('sorted ' + direction)) {
direction = 'desc';
}
- $table.find('thead th').removeClass('sorted desc asc');
- $($table.find('thead th')[columnIndex]).addClass('sorted').addClass(direction);
+ $table.find('thead tr:last th').removeClass('sorted desc asc');
+ $($table.find('thead tr:last th')[columnIndex]).addClass('sorted').addClass(direction);
var $elems = $table.find('tbody td').filter(function() {
return $(this).index() == columnIndex;
});
+ if ($elems.length < 2) {
+ return;
+ }
+
+ var stringComparator = function(a,b) {
+ return a.html().localeCompare(b.html());
+ };
+ var numericComparator = function(a,b) {
+ return parseFloat(a.children().html()) < parseFloat(b.children().html()) ? 1 : -1;
+ };
+ var stateComparator = function(a,b) {
+ return a.attr('title').localeCompare(b.attr('title'));
+ };
+ var isNumeric = function(obj) {
+ return !$.isArray(obj) && !isNaN(parseFloat(obj)) && isFinite(parseFloat(obj));
+ }
+
+ var comparator = stringComparator;
+ var hasAllRowsSameValue = true;
+ var firstElem = $($elems[0]).html();
var sortData = [];
+ var numericDataCount = 0;
$elems.each(function() {
- sortData.push($(this).html());
- sortData.sort();
-
- if (direction == 'asc') {
- sortData.reverse();
+ var text = $(this).html();
+ if (hasAllRowsSameValue) {
+ if (firstElem !== text) {
+ hasAllRowsSameValue = false;
+ }
+ }
+ if (isNumeric(text) || !text) {
+ numericDataCount++;
}
+ sortData.push($(this));
});
+ if ($($elems[0]).hasClass('state')) {
+ comparator = stateComparator;
+ } else {
+ if (hasAllRowsSameValue) {
+ return;
+ }
+ if (columnIndex != 0 && numericDataCount > ($elems.length / 4)) {
+ comparator = numericComparator;
+ }
+ }
+
+ sortData.sort(comparator);
+
+ if (direction == 'asc') {
+ sortData.reverse();
+ }
+
+ var elements = [];
$(sortData).each(function() {
- var sortKey = this;
- var $targetCell = $elems.filter(function() {
- return $(this).html() == sortKey;
- });
- var $targetContainer = $targetCell.parent();
+ elements.push($(this).parent().clone(true));
+ });
- $targetContainer.remove().appendTo($table.find('tbody'));
+ var $tbody = $table.find('tbody');
+ $tbody.empty();
+ $(elements).each(function() {
+ $(this).appendTo($tbody);
});
computeEvenOddRows();
};
var resizeHeaders = function() {
- var $thead = $table.closest('div.data-table').find('thead');
+ var $thead = $table.hasClass('no-split') ? $table.find('thead') : $table.closest('div.data-table').find('thead');
var $tbody = $table.find('tbody');
var $ths = $thead.find('th');
var $tds = $tbody.find('tr:first td');
+ if ($table.hasClass('no-split')) {
+ $tbody.width($thead.width());
+ }
+
if ($ths.size() > $tds.size()) {
$ths.width(
$table.width() / $ths.size()
@@ -194,6 +240,10 @@
$ths.each(function() {
var $th = $(this);
+ if ($th.hasClass('collapsible-column')) {
+ return true;
+ }
+
var $td = $tds.filter(function() {
return $(this).index() == $th.index();
});
@@ -238,9 +288,12 @@
$table.find('tbody').closest('table').addClass('body');
}
- $table.find('th:not(:has(input))').bind('mousemove mouseout', hoverResizableEvent);
- $table.find('th:not(:has(input))').bind('mousedown mousemove mouseup mouseout', resizeDragEvent);
- $table.find('th:not(:has(input))').bind('click', function(event) {
+ if (!$table.hasClass('horizontal-overflow')) {
+ $table.find('th:not(:has(input))').bind('mousemove mouseout', hoverResizableEvent);
+ $table.find('th:not(:has(input))').bind('mousedown mousemove mouseup mouseout', resizeDragEvent);
+ }
+
+ $table.find('thead tr:last th:not(:has(input)):not(.collapsible-column):not(.quick-view)').unbind('click').bind('click', function(event) {
if ($(this).hasClass('resizable')) {
return false;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/ui/widgets/listView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js
index 07b60d9..9b83940 100644
--- a/ui/scripts/ui/widgets/listView.js
+++ b/ui/scripts/ui/widgets/listView.js
@@ -765,10 +765,12 @@
var createHeader = function(preFilter, fields, $table, actions, options) {
if (!options) options = {};
- var $thead = $('<thead>').prependTo($table).append($('<tr>'));
+ var $tr = $('<tr>');
+ var $thead = $('<thead>').prependTo($table).append($tr);
var reorder = options.reorder;
var detailView = options.detailView;
var multiSelect = options.multiSelect;
+ var groupableColumns = options.groupableColumns;
var viewArgs = $table.closest('.list-view').data('view-args');
var uiCustom = viewArgs.uiCustom;
var hiddenFields = [];
@@ -776,8 +778,110 @@
if (preFilter != null)
hiddenFields = preFilter();
+ var addColumnToTr = function($tr, key, colspan, label, needsCollapsibleColumn) {
+ var trText = _l(label);
+ var $th = $('<th>').addClass(key).attr('colspan', colspan).appendTo($tr);
+ if ($th.index()) $th.addClass('reduced-hide');
+ $th.css({'border-right': '1px solid #C6C3C3', 'border-left': '1px solid #C6C3C3'});
+ if (needsCollapsibleColumn) {
+ var karetLeft = $('<span>').css({'margin-right': '10px'});
+ karetLeft.attr('title', trText);
+ karetLeft.appendTo($th);
+ $('<span>').html('«').css({'font-size': '15px', 'float': 'right'}).appendTo(karetLeft);
+ $('<span>').html(trText).appendTo(karetLeft);
+
+ $th.click(function(event) {
+ event.stopPropagation();
+ var $th = $(this);
+ var startIndex = 0;
+ $th.prevAll('th').each(function() {
+ startIndex += parseInt($(this).attr('colspan'));
+ });
+ var endIndex = startIndex + parseInt($th.attr('colspan'));
+ // Hide Column group
+ $th.hide();
+ $th.closest('table').find('tbody td').filter(function() {
+ return $(this).index() >= startIndex && $(this).index() < endIndex;
+ }).hide();
+ $th.closest('table').find('thead tr:last th').filter(function() {
+ return $(this).index() >= startIndex && $(this).index() < endIndex;
+ }).hide();
+ // Show collapsible column with blank cells
+ $th.next('th').show();
+ $th.closest('table').find('tbody td').filter(function() {
+ return $(this).index() == endIndex;
+ }).show();
+ $th.closest('table').find('thead tr:last th').filter(function() {
+ return $(this).index() == endIndex;
+ }).show();
+ // Refresh list view
+ $tr.closest('.list-view').find('.no-split').dataTable('refresh');
+ });
+
+ var karetRight = addColumnToTr($tr, 'collapsible-column', 1, '');
+ $('<span>').html(trText.substring(0,3)).appendTo(karetRight);
+ $('<span>').css({'font-size': '15px'}).html(' »').appendTo(karetRight);
+ karetRight.attr('title', trText);
+ karetRight.css({'border-right': '1px solid #C6C3C3', 'border-left': '1px solid #C6C3C3', 'min-width': '10px', 'width': '10px', 'max-width': '45px', 'padding': '2px'});
+ karetRight.hide();
+ karetRight.click(function(event) {
+ event.stopPropagation();
+ var prevTh = $(this).prev('th');
+ var startIndex = 0;
+ prevTh.prevAll('th').each(function() {
+ startIndex += parseInt($(this).attr('colspan'));
+ });
+ var endIndex = startIndex + parseInt(prevTh.attr('colspan'));
+
+ prevTh.show();
+ prevTh.closest('table').find('tbody td').filter(function() {
+ return $(this).index() >= startIndex && $(this).index() < endIndex;
+ }).show();
+ prevTh.closest('table').find('thead tr:last th').filter(function() {
+ return $(this).index() >= startIndex && $(this).index() < endIndex;
+ }).show();
+
+ prevTh.next('th').hide();
+ prevTh.closest('table').find('tbody td').filter(function() {
+ return $(this).index() == endIndex;
+ }).hide();
+ prevTh.closest('table').find('thead tr:last th').filter(function() {
+ return $(this).index() == endIndex;
+ }).hide();
+
+ $tr.closest('.list-view').find('.no-split').dataTable('refresh');
+ });
+ } else {
+ $th.html(trText);
+ }
+ return $th;
+ };
+
+ if (groupableColumns) {
+ $tr.addClass('groupable-header-columns').addClass('groupable-header');
+ $.each(fields, function(key) {
+ var field = this;
+ if (field.columns) {
+ var colspan = Object.keys(field.columns).length;
+ addColumnToTr($tr, key, colspan, field.label, true);
+ } else {
+ var label = '';
+ if (key == 'name') {
+ label = 'label.resources';
+ }
+ addColumnToTr($tr, key, 1, label);
+ }
+ return true;
+ });
+ if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
+ addColumnToTr($tr, 'quick-view', 1, '');
+ }
+ $tr = $('<tr>').appendTo($thead);
+ $tr.addClass('groupable-header');
+ }
+
if (multiSelect) {
- var $th = $('<th>').addClass('multiselect').appendTo($thead.find('tr'));
+ var $th = $('<th>').addClass('multiselect').appendTo($tr);
var content = $('<input>')
.attr('type', 'checkbox')
.addClass('multiSelectMasterCheckbox')
@@ -794,18 +898,24 @@
if ($.inArray(key, hiddenFields) != -1)
return true;
var field = this;
- var $th = $('<th>').addClass(key).appendTo($thead.find('tr'));
-
- if ($th.index()) $th.addClass('reduced-hide');
-
- $th.html(_l(field.label));
-
+ if (field.columns) {
+ $.each(field.columns, function(idx) {
+ var subfield = this;
+ addColumnToTr($tr, key, 1, subfield.label);
+ return true;
+ });
+ var blankCell = addColumnToTr($tr, 'collapsible-column', 1, '');
+ blankCell.css({'min-width': '10px', 'width': '10px'});
+ blankCell.hide();
+ } else {
+ addColumnToTr($tr, key, 1, field.label);
+ }
return true;
});
// Re-order row buttons
if (reorder) {
- $thead.find('tr').append(
+ $tr.append(
$('<th>').html(_l('label.order')).addClass('reorder-actions reduced-hide')
);
}
@@ -826,7 +936,7 @@
);
if (actions && !options.noActionCol && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) {
- $thead.find('tr').append(
+ $tr.append(
$('<th></th>')
.html(_l('label.actions'))
.addClass('actions reduced-hide')
@@ -835,7 +945,7 @@
// Quick view
if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
- $thead.find('tr').append(
+ $tr.append(
$('<th></th>')
.html(_l('label.quickview'))
.addClass('quick-view reduced-hide')
@@ -1033,6 +1143,7 @@
var listViewArgs = $listView.data('view-args');
var uiCustom = listViewArgs.uiCustom;
var subselect = uiCustom ? listViewArgs.listView.subselect : null;
+ var hasCollapsibleColumn = false;
if (!(data && data.length)) {
$listView.data('end-of-table', true);
@@ -1088,8 +1199,25 @@
);
}
- // Add field data
+ var reducedFields = {};
+ var idx = 0;
$.each(fields, function(key) {
+ var field = this;
+ if (field.columns) {
+ $.each(field.columns, function(innerKey) {
+ reducedFields[innerKey] = this;
+ });
+ reducedFields['blank-cell-' + idx] = {blankCell: true};
+ idx += 1;
+ hasCollapsibleColumn = true;
+ } else {
+ reducedFields[key] = this;
+ }
+ return true;
+ });
+
+ // Add field data
+ $.each(reducedFields, function(key) {
if ($.inArray(key, hiddenFields) != -1)
return true;
var field = this;
@@ -1103,6 +1231,11 @@
$td.addClass('truncated');
}
+ if (field.blankCell) {
+ $td.css({'min-width': '10px', 'width': '10px'});
+ $td.hide();
+ }
+
if (field.indicator) {
$td.addClass('state').addClass(field.indicator[content]);
@@ -1110,6 +1243,19 @@
//$tr.find('td:first').addClass('item-state-' + field.indicator[content]);
}
+ 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) {
+ $td.addClass('alert-disable-threshold');
+ } else if (value >= notificationThreshold) {
+ $td.addClass('alert-notification-threshold');
+ }
+ }
+ }
+
if (field.id == true) id = field.id;
if ($td.index()) $td.addClass('reduced-hide');
if (field.action) {
@@ -1136,9 +1282,12 @@
$ul.appendTo($td);
} else {
- $td.append(
- $('<span>').html(_s(content))
- );
+ var span = $('<span>').html(_s(content));
+ if (field.compact) {
+ span.addClass('compact');
+ span.html('');
+ }
+ $td.append(span);
}
}
@@ -1376,8 +1525,8 @@
.appendTo($tr);
$quickView.mouseover(
// Show quick view
-
function() {
+ var $quickView = $(this);
var $quickViewTooltip = $('<div>').addClass('quick-view-tooltip hovered-elem');
var $tr = $quickView.closest('tr');
var $listView = $tr.closest('.list-view');
@@ -1461,7 +1610,7 @@
});
$quickViewTooltip.css({
position: 'absolute',
- left: $tr.offset().left + $tr.width() - $quickViewTooltip.width(),
+ left: $quickView.offset().left + $quickView.outerWidth() - $quickViewTooltip.width() - 2*(parseInt($quickView.css('border-left-width')) + parseInt($quickView.css('border-right-width'))),
top: $quickView.offset().top,
zIndex: $tr.closest('.panel').zIndex() + 1
});
@@ -1476,6 +1625,14 @@
}
});
+ // Toggle collapsible column to fix alignment of hidden/shown cells
+ if (hasCollapsibleColumn) {
+ $tbody.closest('table').find('tr:first th.collapsible-column:visible').prev('th').click();
+ }
+
+ // Re-sort table if a column was previously sorted
+ $listView.find('thead tr:last th.sorted').click().click();
+
return rows;
};
@@ -1794,8 +1951,19 @@
reorder: reorder,
detailView: listViewData.detailView,
'multiSelect': multiSelect,
- noActionCol: listViewData.noActionCol
+ noActionCol: listViewData.noActionCol,
+ groupableColumns: listViewData.groupableColumns
});
+
+ if (listViewData.noSplit) {
+ $table.addClass('no-split');
+ }
+
+ if (listViewData.horizontalOverflow) {
+ $table.addClass('horizontal-overflow');
+ $table.parent().css({'overflow-x': 'auto'});
+ }
+
createFilters($toolbar, listViewData.filters);
if (listViewData.hideSearchBar != true) {
[7/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
Merge pull request #1091 from shapeblue/metrics-4.5
[4.5] Metrics viewFrom #1038, for 4.5 branch
* pr/1091:
CLOUDSTACK-9020: Metrics UI fixes
CLOUDSTACK-9020: Increase UI container width by 200px
CLOUDSTACK-9020: add ipaddress in instances view
CLOUDSTACK-9020: add instances count in host view, ip address in instances view
CLOUDSTACK-9020: Metrics views for CloudStack UI
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/2f250e26
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2f250e26
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2f250e26
Branch: refs/heads/4.5
Commit: 2f250e269b51a9c72c51e26f650d278582db5257
Parents: efe93d7 ebee0f0
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Fri Nov 20 11:47:13 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Nov 20 11:47:13 2015 +0530
----------------------------------------------------------------------
.../config/ApiServiceConfiguration.java | 4 +-
.../classes/resources/messages.properties | 35 +
ui/css/cloudstack3.css | 175 ++-
ui/dictionary.jsp | 35 +
ui/images/logo-login-oss.png | Bin 22165 -> 10864 bytes
ui/images/logo.png | Bin 21781 -> 9257 bytes
ui/images/sprites.png | Bin 194105 -> 198421 bytes
ui/index.jsp | 2 +
ui/scripts/cloudStack.js | 20 +
ui/scripts/instances.js | 23 +-
ui/scripts/metrics.js | 1121 ++++++++++++++++++
ui/scripts/storage.js | 14 +
ui/scripts/system.js | 70 +-
ui/scripts/ui-custom/metricsView.js | 140 +++
ui/scripts/ui/widgets/cloudBrowser.js | 8 +
ui/scripts/ui/widgets/dataTable.js | 96 +-
ui/scripts/ui/widgets/listView.js | 204 +++-
17 files changed, 1853 insertions(+), 94 deletions(-)
----------------------------------------------------------------------
[3/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
CLOUDSTACK-9020: add instances count in host view, ip address in instances view
Add minor features based on community discussions
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit b4d1fed849aa7873af870b7e583ac91dd1ca4cc6)
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/14940a3c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/14940a3c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/14940a3c
Branch: refs/heads/4.5
Commit: 14940a3c9aa142cc4ba7acafc86aa5b6968702aa
Parents: d34da5a
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Sat Nov 7 16:49:14 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Sat Nov 7 16:54:01 2015 +0530
----------------------------------------------------------------------
ui/scripts/metrics.js | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/14940a3c/ui/scripts/metrics.js
----------------------------------------------------------------------
diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js
index 4fce7a0..7704469 100644
--- a/ui/scripts/metrics.js
+++ b/ui/scripts/metrics.js
@@ -550,6 +550,9 @@
},
compact: true
},
+ instances: {
+ label: 'label.instances'
+ },
cpuused: {
label: 'label.metrics.cpu.usage',
collapsible: true,
@@ -702,6 +705,26 @@
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;
+ $.each(vms, function(idx, vm) {
+ items[idx].instances++;
+ if (vm.state == 'Running') {
+ items[idx].instancesUp++;
+ }
+ });
+ }
+ },
+ async: false
+ });
+ items[idx].instances = items[idx].instancesUp + ' / ' + items[idx].instances;
});
}
args.response.success({
@@ -747,6 +770,12 @@
},
compact: true
},
+ ipaddress: {
+ label: 'label.ip.address'
+ },
+ zonename: {
+ label: 'label.zone'
+ },
cpuused: {
label: 'label.metrics.cpu.usage',
collapsible: true,
@@ -823,6 +852,9 @@
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'},
[5/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
CLOUDSTACK-9020: Increase UI container width by 200px
Based on suggestion from Lucian (Nux), this patch increases the UI's container
width by 200px as most modern resolutions on desktop/laptops/workstations are
at least 1400px wide. By increasing the width and adjusting css properties
throughout the UI, we get more space to show information. This also gets
rid of horizontal scrollbar in case of metrics views. This also, fixes the UI
logos to include our mascot 'cloudmonkey'.
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit f7b64726d9ad4ac53c19fb47378068433cf86ae3)
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/0d737884
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/0d737884
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/0d737884
Branch: refs/heads/4.5
Commit: 0d73788464b69ac70dea15cd588143e78b222bea
Parents: 1391f47
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Sat Nov 7 16:51:09 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Sat Nov 7 16:54:31 2015 +0530
----------------------------------------------------------------------
ui/css/cloudstack3.css | 91 +++++++++++++++++++-------------------
ui/images/logo-login-oss.png | Bin 22165 -> 10864 bytes
ui/images/logo.png | Bin 21781 -> 9257 bytes
3 files changed, 46 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0d737884/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index 3a4e963..e928409 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -46,7 +46,7 @@ div.toolbar,
/*+}*/
body {
- min-width: 1024px;
+ min-width: 1224px;
font-family: sans-serif;
overflow: auto;
background: #EDE8E8;
@@ -61,7 +61,7 @@ body.install-wizard {
}
#main-area {
- width: 1024px;
+ width: 1224px;
height: 729px;
margin: auto;
border: 1px solid #D4D4D4;
@@ -96,8 +96,8 @@ a:hover {
/*Table*/
table {
- width: 740px;
- max-width: 777px;
+ width: 940px;
+ max-width: 977px;
margin: 15px 15px 12px 12px;
font-size: 13px;
text-align: left;
@@ -480,8 +480,8 @@ body.login {
}
.login .logo {
- width: 250px;
- height: 31px;
+ width: 290px;
+ height: 40px;
float: left;
margin: 72px 0 0 209px;
background: url(../images/logo-login.png) no-repeat 0 0;
@@ -1297,7 +1297,7 @@ div.panel div.list-view {
}
.detail-view div.list-view {
- width: 730px;
+ width: 930px;
border: 1px solid #DAD4D4;
margin: 41px auto auto !important;
height: 536px !important;
@@ -1305,12 +1305,12 @@ div.panel div.list-view {
}
div.panel div.list-view div.data-table table {
- width: 755px;
+ width: 955px;
margin-top: 44px;
}
.detail-view div.list-view div.data-table table {
- width: 703px !important;
+ width: 903px !important;
}
.detail-view div.list-view div.data-table table td {
@@ -1321,7 +1321,7 @@ div.panel div.list-view div.fixed-header {
position: absolute;
top: 29px;
left: 12px;
- width: 760px;
+ width: 960px;
height: 47px;
display: table;
background-color: #F7F7F7;
@@ -1330,9 +1330,9 @@ div.panel div.list-view div.fixed-header {
}
.detail-view div.list-view div.fixed-header {
- width: 703px !important;
+ width: 903px !important;
top: 49px !important;
- left: 32px !important;
+ left: 29px !important;
background: #FFFFFF;
}
@@ -1354,7 +1354,7 @@ div.panel div.list-view div.fixed-header table {
position: relative;
left: 0px;
top: 18px;
- width: 755px;
+ width: 955px;
/*+box-shadow:0px 4px 10px #DFE1E3;*/
-moz-box-shadow: 0px 4px 10px #DFE1E3;
-webkit-box-shadow: 0px 4px 10px #DFE1E3;
@@ -1890,7 +1890,7 @@ span.compact {
}
.detail-group table {
- width: 96%;
+ width: 98%;
font-size: 12px;
border-bottom: 1px solid #DFDFDF;
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7f7f7', endColorstr='#eaeaea',GradientType=0 );
@@ -2435,7 +2435,7 @@ div.detail-group.actions td {
}
#header.nologo div.logo {
- width: 1024px;
+ width: 1224px;
height: 47px;
margin: auto;
background: url(../images/logo.png) no-repeat 0 center;
@@ -2446,7 +2446,7 @@ div.detail-group.actions td {
}
#header div.controls {
- width: 1026px;
+ width: 1226px;
height: 48px;
position: relative;
margin: 27px auto 0;
@@ -2554,7 +2554,7 @@ div.detail-group.actions td {
margin: 0;
position: absolute;
top: -47px;
- left: 890px;
+ left: 1090px;
cursor: default !important;
display: inline-block;
float: left;
@@ -2944,9 +2944,9 @@ div.detail-group.actions td {
/*Browser*/
#browser {
- width: 794px;
+ width: 994px;
height: 100%;
- max-width: 794px;
+ max-width: 994px;
position: relative;
float: left;
overflow: hidden;
@@ -3068,7 +3068,7 @@ div.detail-group.actions td {
}
.detail-view .ui-tabs-panel div.toolbar {
- width: 768px;
+ width: 968px;
background: transparent;
border: none;
margin-top: 8px;
@@ -3234,7 +3234,7 @@ div.toolbar div.button.main-action span.icon {
div.toolbar div.button.refresh {
float: right;
- margin: 0 15px 0 0;
+ margin: 0 20px 0 0;
}
div.toolbar div.button.refresh span {
@@ -4357,7 +4357,7 @@ textarea {
}
.dashboard.admin .dashboard-container.sub {
- width: 368px;
+ width: 468px;
}
.dashboard.admin .dashboard-container.sub .button.view-all,
@@ -4415,7 +4415,7 @@ textarea {
/**** Head*/
.dashboard.admin .dashboard-container.head {
- width: 766px;
+ width: 966px;
height: 331px;
margin: 9px 0 0;
float: left;
@@ -4475,7 +4475,7 @@ textarea {
/**** Charts / stats*/
.dashboard.admin .zone-stats {
- width: 774px;
+ width: 974px;
height: 316px;
overflow: auto;
overflow-x: hidden;
@@ -4486,7 +4486,7 @@ textarea {
}
.dashboard.admin .zone-stats ul {
- width: 796px;
+ width: 996px;
/*+placement:shift -2px 11px;*/
position: relative;
left: -2px;
@@ -4494,7 +4494,7 @@ textarea {
}
.dashboard.admin .zone-stats ul li {
- width: 388px;
+ width: 488px;
font-size: 14px;
height: 79px;
float: left;
@@ -4514,7 +4514,7 @@ textarea {
}
.dashboard.admin .zone-stats ul li .label {
- width: 111px;
+ width: 161px;
float: left;
font-weight: 100;
border-bottom: 1px solid #E2E2E2;
@@ -4685,7 +4685,7 @@ textarea {
}
.dashboard.admin .dashboard-container.sub.alerts ul {
- width: 368px;
+ width: 468px;
height: 234px;
overflow: auto;
overflow-x: hidden;
@@ -5145,7 +5145,7 @@ textarea {
}
.system-chart.dashboard.admin .dashboard-container {
- width: 740px;
+ width: 930px;
border: none;
}
@@ -5166,7 +5166,7 @@ textarea {
}
.system-chart.dashboard.admin .dashboard-container .stats .chart {
- width: 136px;
+ width: 300px;
}
/** Compute*/
@@ -5183,7 +5183,7 @@ textarea {
}
.system-chart.compute ul.resources li.zone {
- left: 96px;
+ left: 196px;
}
.system-chart.compute ul.resources li.zone .label {
@@ -5195,32 +5195,32 @@ textarea {
}
.system-chart.compute ul.resources li.pods {
- left: 199px;
+ left: 299px;
top: 112px;
}
.system-chart.compute ul.resources li.clusters {
- left: 296px;
+ left: 396px;
top: 189px;
}
.system-chart.compute ul.resources li.hosts {
- left: 407px;
+ left: 507px;
top: 265px;
}
.system-chart.compute ul.resources li.primaryStorage {
- left: 407px;
+ left: 507px;
top: 375px;
}
.system-chart.compute ul.resources li.secondaryStorage {
- left: 199px;
+ left: 299px;
top: 497px;
}
.system-chart.compute ul.resources li.ucs {
- left: 199px;
+ left: 299px;
top: 406px;
}
@@ -8135,6 +8135,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
.detail-view .multi-edit select {
width: 93%;
font-size: 10px;
+ min-width: 80px;
}
.multi-edit input {
@@ -9073,7 +9074,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
.network-chart li.firewall {
/*+placement:shift 282px 188px;*/
position: relative;
- left: 282px;
+ left: 356px;
top: 188px;
position: absolute;
}
@@ -9081,7 +9082,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
.network-chart li.loadBalancing {
/*+placement:shift 167px 342px;*/
position: relative;
- left: 167px;
+ left: 237px;
top: 342px;
position: absolute;
}
@@ -9089,7 +9090,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
.network-chart li.portForwarding {
/*+placement:shift 401px 342px;*/
position: relative;
- left: 401px;
+ left: 480px;
top: 342px;
position: absolute;
}
@@ -9166,7 +9167,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
/*System Dashboard*/
.system-dashboard {
height: 258px;
- width: 762px;
+ width: 962px;
display: block;
/*+border-radius:3px;*/
-moz-border-radius: 3px;
@@ -9264,7 +9265,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
position: relative;
left: 18px;
top: 110px;
- width: 78%;
+ width: 83%;
position: absolute;
text-align: center;
padding: 8px 0;
@@ -9279,7 +9280,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
.system-dashboard .status_box li {
height: 178px;
- width: 178px;
+ width: 228px;
padding: 0;
margin: 0 0 0 8px;
/*+border-radius:3px;*/
@@ -9303,7 +9304,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
padding: 65px 80px 5px;
/*+placement:shift 31px 19px;*/
position: relative;
- left: 31px;
+ left: 51px;
top: 19px;
position: absolute;
/*+opacity:56%;*/
@@ -9340,7 +9341,7 @@ div.container div.panel div#details-tab-addloadBalancer.detail-group div.loadBal
/*+placement:shift 13px 5px;*/
position: relative;
left: 13px;
- top: 5px;
+ top: 13px;
font-weight: 100;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0d737884/ui/images/logo-login-oss.png
----------------------------------------------------------------------
diff --git a/ui/images/logo-login-oss.png b/ui/images/logo-login-oss.png
index e0f3767..92fc81c 100644
Binary files a/ui/images/logo-login-oss.png and b/ui/images/logo-login-oss.png differ
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0d737884/ui/images/logo.png
----------------------------------------------------------------------
diff --git a/ui/images/logo.png b/ui/images/logo.png
index f36a9cb..2e3aae9 100644
Binary files a/ui/images/logo.png and b/ui/images/logo.png differ
[4/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
CLOUDSTACK-9020: add ipaddress in instances view
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit edc74aebbffc3f8fb4853de3cf6740eee83c78fd)
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/1391f476
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1391f476
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1391f476
Branch: refs/heads/4.5
Commit: 1391f476f1db211392b7adf23a58358f10d0aa4a
Parents: 14940a3
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Sat Nov 7 16:50:08 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Sat Nov 7 16:54:13 2015 +0530
----------------------------------------------------------------------
ui/scripts/instances.js | 8 ++++++++
1 file changed, 8 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1391f476/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index 8c7e31f..68bf098 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -164,6 +164,9 @@
label: 'label.display.name',
truncate: true
},
+ ipaddress: {
+ label: 'label.ip.address'
+ },
zonename: {
label: 'label.zone.name'
},
@@ -371,6 +374,11 @@
data: data,
success: function(json) {
var items = json.listvirtualmachinesresponse.virtualmachine;
+ $.each(items, function(idx, vm) {
+ if (vm.nic && vm.nic.length > 0 && vm.nic[0].ipaddress) {
+ items[idx].ipaddress = vm.nic[0].ipaddress;
+ }
+ });
args.response.success({
data: items
});
[2/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
CLOUDSTACK-9020: Metrics views for CloudStack UI
Implements following:
- A metrics table widget that is:
- vertically and horizontally scrollable with pagination/infinite scrolling
- sortable columns (client side)
- groupable/collapsible columns
- alternate row coloring
- refresh button to refresh views
- threshold table cell coloring
- panel/breadcrumb navigation
- quick view action column
- translatable labels
- Sortable column for all CloudStack tables (client side)
- Configurable UI pagesize for list API calls, 'default.ui.page.size'
- Metrics views: Zones, Clusters, Hosts, Instances, Storage pools, Volumes
- Resource filtering/navigation: Zones->Clusters->Hosts->Instances->Volumes, Storage Pool->Volumes
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/d34da5aa
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/d34da5aa
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/d34da5aa
Branch: refs/heads/4.5
Commit: d34da5aa8f10c0d47c837f99b2f456a91c77c2ab
Parents: efe93d7
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Tue Nov 3 15:27:46 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Fri Nov 6 11:06:02 2015 +0530
----------------------------------------------------------------------
.../config/ApiServiceConfiguration.java | 4 +-
.../classes/resources/messages.properties | 35 +
ui/css/cloudstack3.css | 84 +-
ui/dictionary.jsp | 35 +
ui/images/sprites.png | Bin 194105 -> 198421 bytes
ui/index.jsp | 2 +
ui/scripts/cloudStack.js | 20 +
ui/scripts/instances.js | 18 +-
ui/scripts/metrics.js | 1087 ++++++++++++++++++
ui/scripts/storage.js | 17 +
ui/scripts/system.js | 82 +-
ui/scripts/ui-custom/metricsView.js | 140 +++
ui/scripts/ui/widgets/cloudBrowser.js | 8 +
ui/scripts/ui/widgets/dataTable.js | 91 +-
ui/scripts/ui/widgets/listView.js | 204 +++-
15 files changed, 1778 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java b/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java
index 94c0a55..701af62 100644
--- a/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java
+++ b/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java
@@ -26,6 +26,8 @@ public class ApiServiceConfiguration implements Configurable {
public static final ConfigKey<String> ManagementHostIPAdr = new ConfigKey<String>("Advanced", String.class, "host", "localhost", "The ip address of management server", true);
public static final ConfigKey<String> ApiServletPath = new ConfigKey<String>("Advanced", String.class, "endpointe.url", "http://localhost:8080/client/api",
"API end point. Can be used by CS components/services deployed remotely, for sending CS API requests", true);
+ public static final ConfigKey<Long> DefaultUIPageSize = new ConfigKey<Long>("Advanced", Long.class, "default.ui.page.size", "20",
+ "The default pagesize to be used by UI and other clients when making list* API calls", true, ConfigKey.Scope.Global);
@Override
public String getConfigComponentName() {
@@ -34,7 +36,7 @@ public class ApiServiceConfiguration implements Configurable {
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {ManagementHostIPAdr, ApiServletPath};
+ return new ConfigKey<?>[] {ManagementHostIPAdr, ApiServletPath, DefaultUIPageSize};
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/client/WEB-INF/classes/resources/messages.properties
----------------------------------------------------------------------
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index f5e0588..54276e4 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -831,6 +831,41 @@ label.menu.templates=Templates
label.menu.virtual.appliances=Virtual Appliances
label.menu.virtual.resources=Virtual Resources
label.menu.volumes=Volumes
+label.metrics=Metrics
+label.metrics.allocated=Allocated
+label.metrics.clusters=Clusters
+label.metrics.cpu.allocated=CPU Allocation
+label.metrics.cpu.max.dev=Deviation
+label.metrics.cpu.total=Total
+label.metrics.cpu.usage=CPU Usage
+label.metrics.cpu.used.avg=Used
+label.metrics.disk=Disk
+label.metrics.disk.iops.total=IOPS
+label.metrics.disk.read=Read
+label.metrics.disk.size=Size
+label.metrics.disk.storagetype=Type
+label.metrics.disk.usage=Disk Usage
+label.metrics.disk.used=Used
+label.metrics.disk.total=Total
+label.metrics.disk.allocated=Allocated
+label.metrics.disk.unallocated=Unallocated
+label.metrics.disk.write=Write
+label.metrics.hosts=Hosts
+label.metrics.memory.allocated=Mem Allocation
+label.metrics.memory.max.dev=Deviation
+label.metrics.memory.total=Total
+label.metrics.memory.usage=Mem Usage
+label.metrics.memory.used.avg=Used
+label.metrics.name=Name
+label.metrics.network.usage=Network Usage
+label.metrics.network.read=Read
+label.metrics.network.write=Write
+label.metrics.num.cpu.cores=Cores
+label.metrics.property=Property
+label.metrics.scope=Scope
+label.metrics.state=State
+label.metrics.storagepool=Storage Pool
+label.metrics.vm.name=VM Name
label.migrate.instance.to.host=Migrate instance to another host
label.migrate.instance.to.ps=Migrate instance to another primary storage
label.migrate.instance.to=Migrate instance to
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index c239e67..3a4e963 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -146,7 +146,7 @@ table thead th.sorted.asc {
table tbody td,
table th {
- padding: 10px 5px 8px;
+ padding: 10px 5px 6px;
border-right: 1px solid #BFBFBF;
color: #282828;
clear: none;
@@ -1393,7 +1393,7 @@ div.list-view td.state span {
-webkit-text-shadow: 0px 1px 1px #FFFFFF;
-o-text-shadow: 0px 1px 1px #FFFFFF;
text-shadow: 0px 1px 1px #FFFFFF;
- background: url(../images/sprites.png) 1px -536px;
+ background: url(../images/sprites.png) 1px -526px;
}
div.list-view td.state.on span {
@@ -1407,7 +1407,69 @@ div.list-view td.state.off span {
background-image: url(../images/sprites.png);
background-repeat: no-repeat;
color: #B90606;
- background-position: 1px -496px;
+ background-position: 1px -492px;
+}
+
+div.list-view td.state.warning span {
+ background-image: url(../images/sprites.png);
+ background-repeat: no-repeat;
+ color: #B90606;
+ background-position: 1px -558px;
+}
+
+div.list-view td.state.transition span {
+ background-image: url(../images/sprites.png);
+ background-repeat: no-repeat;
+ color: #B90606;
+ background-position: 1px -432px;
+}
+
+.horizontal-overflow tbody td, .horizontal-overflow thead th {
+ min-width: 40px;
+ padding: 10px 10px 5px 0px;
+}
+
+.horizontal-overflow th.quick-view {
+ padding-left: 5px;
+}
+
+.groupable-header {
+ background: url(../images/bg-table-head.png);
+ border-left: 1px solid #C6C3C3;
+ border-right: 1px solid #C6C3C3;
+}
+
+.groupable-header-columns th {
+ border: none;
+}
+
+table.horizontal-overflow td.state {
+ width: 55px;
+ min-width: 55px;
+ max-width: 55px;
+}
+
+table.no-split td.first {
+ min-width: 150px;
+}
+
+.groupable-header-border {
+ border-left: 1px solid #C6C3C3;
+ border-right: 1px solid #C6C3C3;
+}
+
+td.alert-notification-threshold {
+ color: #E87900;
+ background-color: rgba(255, 231, 175, 0.75);
+}
+
+td.alert-disable-threshold {
+ color: #F50000;
+ background-color: rgba(255, 190, 190, 0.75);
+}
+
+span.compact {
+ height: 16px;
}
/** Quick view tooltip*/
@@ -12420,6 +12482,22 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
background-position: 0px -707px;
}
+.viewMetrics .icon {
+ background-position: -40px -32px;
+}
+
+.viewMetrics:hover .icon {
+ background-position: -40px -32px;
+}
+
+.refreshMetrics .icon {
+ background-position: 0px -62px;
+}
+
+.refreshMetrics:hover .icon {
+ background-position: 0px -62px;
+}
+
.attach .icon,
.attachISO .icon,
.attachDisk .icon,
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/dictionary.jsp
----------------------------------------------------------------------
diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp
index 414dab8..e0a41c1 100644
--- a/ui/dictionary.jsp
+++ b/ui/dictionary.jsp
@@ -832,6 +832,41 @@ dictionary = {
'label.menu.virtual.appliances': '<fmt:message key="label.menu.virtual.appliances" />',
'label.menu.virtual.resources': '<fmt:message key="label.menu.virtual.resources" />',
'label.menu.volumes': '<fmt:message key="label.menu.volumes" />',
+'label.metrics': '<fmt:message key="label.metrics" />',
+'label.metrics.allocated': '<fmt:message key="label.metrics.allocated" />',
+'label.metrics.clusters': '<fmt:message key="label.metrics.clusters" />',
+'label.metrics.cpu.allocated': '<fmt:message key="label.metrics.cpu.allocated" />',
+'label.metrics.cpu.max.dev': '<fmt:message key="label.metrics.cpu.max.dev" />',
+'label.metrics.cpu.total': '<fmt:message key="label.metrics.cpu.total" />',
+'label.metrics.cpu.usage': '<fmt:message key="label.metrics.cpu.usage" />',
+'label.metrics.cpu.used.avg': '<fmt:message key="label.metrics.cpu.used.avg" />',
+'label.metrics.disk': '<fmt:message key="label.metrics.disk" />',
+'label.metrics.disk.iops.total': '<fmt:message key="label.metrics.disk.iops.total" />',
+'label.metrics.disk.read': '<fmt:message key="label.metrics.disk.read" />',
+'label.metrics.disk.size': '<fmt:message key="label.metrics.disk.size" />',
+'label.metrics.disk.storagetype': '<fmt:message key="label.metrics.disk.storagetype" />',
+'label.metrics.disk.usage': '<fmt:message key="label.metrics.disk.usage" />',
+'label.metrics.disk.used': '<fmt:message key="label.metrics.disk.used" />',
+'label.metrics.disk.total': '<fmt:message key="label.metrics.disk.total" />',
+'label.metrics.disk.allocated': '<fmt:message key="label.metrics.disk.allocated" />',
+'label.metrics.disk.unallocated': '<fmt:message key="label.metrics.disk.unallocated" />',
+'label.metrics.disk.write': '<fmt:message key="label.metrics.disk.write" />',
+'label.metrics.hosts': '<fmt:message key="label.metrics.hosts" />',
+'label.metrics.memory.allocated': '<fmt:message key="label.metrics.memory.allocated" />',
+'label.metrics.memory.max.dev': '<fmt:message key="label.metrics.memory.max.dev" />',
+'label.metrics.memory.total': '<fmt:message key="label.metrics.memory.total" />',
+'label.metrics.memory.usage': '<fmt:message key="label.metrics.memory.usage" />',
+'label.metrics.memory.used.avg': '<fmt:message key="label.metrics.memory.used.avg" />',
+'label.metrics.name': '<fmt:message key="label.metrics.name" />',
+'label.metrics.network.read': '<fmt:message key="label.metrics.network.read" />',
+'label.metrics.network.usage': '<fmt:message key="label.metrics.network.usage" />',
+'label.metrics.network.write': '<fmt:message key="label.metrics.network.write" />',
+'label.metrics.num.cpu.cores': '<fmt:message key="label.metrics.num.cpu.cores" />',
+'label.metrics.property': '<fmt:message key="label.metrics.property" />',
+'label.metrics.scope': '<fmt:message key="label.metrics.scope" />',
+'label.metrics.state': '<fmt:message key="label.metrics.state" />',
+'label.metrics.storagepool': '<fmt:message key="label.metrics.storagepool" />',
+'label.metrics.vm.name': '<fmt:message key="label.metrics.vm.name" />',
'label.migrate.instance.to': '<fmt:message key="label.migrate.instance.to" />',
'label.migrate.instance.to.host': '<fmt:message key="label.migrate.instance.to.host" />',
'label.migrate.instance.to.ps': '<fmt:message key="label.migrate.instance.to.ps" />',
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/images/sprites.png
----------------------------------------------------------------------
diff --git a/ui/images/sprites.png b/ui/images/sprites.png
index 1a6eaa5..0ddafaf 100755
Binary files a/ui/images/sprites.png and b/ui/images/sprites.png differ
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/index.jsp
----------------------------------------------------------------------
diff --git a/ui/index.jsp b/ui/index.jsp
index 60f3cc3..2541c2a 100644
--- a/ui/index.jsp
+++ b/ui/index.jsp
@@ -1763,6 +1763,7 @@
<script type="text/javascript" src="scripts/ui-custom/granularSettings.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/zoneChart.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/dashboard.js?t=<%=now%>"></script>
+ <script type="text/javascript" src="scripts/ui-custom/metricsView.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/installWizard.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/installWizard.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/projects.js?t=<%=now%>"></script>
@@ -1799,6 +1800,7 @@
<script type="text/javascript" src="scripts/vm_snapshots.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/projectSelect.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/saml.js?t=<%=now%>"></script>
+ <script type="text/javascript" src="scripts/metrics.js?t=<%=now%>"></script>
<!-- Plugin/module API -->
<script type="text/javascript" src="scripts/ui-custom/pluginListing.js?t=<%=now%>"></script>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/cloudStack.js
----------------------------------------------------------------------
diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js
index 8b27452..1dcb994 100644
--- a/ui/scripts/cloudStack.js
+++ b/ui/scripts/cloudStack.js
@@ -164,6 +164,26 @@
}
});
+ // Update global pagesize for list APIs in UI
+ $.ajax({
+ type: 'GET',
+ url: createURL('listConfigurations'),
+ data: {name: 'default.ui.page.size'},
+ dataType: 'json',
+ async: false,
+ success: function(data, textStatus, xhr) {
+ if (data && data.listconfigurationsresponse && data.listconfigurationsresponse.configuration) {
+ var config = data.listconfigurationsresponse.configuration[0];
+ if (config && config.name == 'default.ui.page.size') {
+ pageSize = parseInt(config.value);
+ }
+ }
+ },
+ error: function(xhr) { // ignore any errors, fallback to the default
+ },
+ });
+
+
// Populate IDP list
$.ajax({
type: 'GET',
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index b8d1299..8c7e31f 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -288,7 +288,23 @@
poll: pollAsyncJobResult
}
},
- snapshot: vmSnapshotAction({ listView: true })
+ snapshot: vmSnapshotAction({ listView: true }),
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'vms'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
+ },
},
dataProvider: function(args) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/metrics.js
----------------------------------------------------------------------
diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js
new file mode 100644
index 0000000..4fce7a0
--- /dev/null
+++ b/ui/scripts/metrics.js
@@ -0,0 +1,1087 @@
+// 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.
+(function(cloudStack) {
+ cloudStack.sections.metrics = {
+ title: 'label.metrics',
+ listView: {
+ id: 'metrics',
+ fields: {
+ name: {
+ label: 'metrics'
+ }
+ },
+ }
+ };
+
+
+ // Zones Metrics
+ cloudStack.sections.metrics.zones = {
+ title: 'label.metrics',
+ listView: {
+ id: 'physicalResources',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Enabled': 'on',
+ 'Disabled': 'off'
+ },
+ compact: true
+ },
+ clusters : {
+ label: 'label.metrics.clusters'
+ },
+ cpuused: {
+ label: 'label.metrics.cpu.usage',
+ collapsible: true,
+ columns: {
+ cpuusedavg: {
+ label: 'label.metrics.cpu.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ },
+ cpumaxdev: {
+ label: 'label.metrics.cpu.max.dev'
+ }
+ }
+ },
+ cpuallocated: {
+ label: 'label.metrics.cpu.allocated',
+ collapsible: true,
+ columns: {
+ cpuallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ },
+ cputotal: {
+ label: 'label.metrics.cpu.total'
+ }
+ }
+ },
+ memused: {
+ label: 'label.metrics.memory.usage',
+ collapsible: true,
+ columns: {
+ memusedavg: {
+ label: 'label.metrics.memory.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ },
+ memmaxdev: {
+ label: 'label.metrics.memory.max.dev'
+ }
+ }
+ },
+ memallocated: {
+ label: 'label.metrics.memory.allocated',
+ collapsible: true,
+ columns: {
+ memallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ },
+ memtotal: {
+ label: 'label.metrics.memory.total'
+ }
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ $.ajax({
+ url: createURL('listZones'),
+ 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},
+ 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++;
+ }
+ $.ajax({
+ url: createURL('listHosts'),
+ data: {clusterid: cluster.id, type: 'routing'},
+ 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
+ });
+ }
+ });
+ },
+ browseBy: {
+ filterBy: 'zoneid',
+ resource: 'clusters'
+ },
+ detailView: cloudStack.sections.system.physicalResourceSection.sections.physicalResources.listView.zones.detailView
+ }
+ };
+
+
+ // Clusters Metrics
+ cloudStack.sections.metrics.clusters = {
+ title: 'label.metrics',
+ listView: {
+ id: 'clusters',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Enabled': 'on',
+ 'Unmanaged': 'warning',
+ 'Disabled': 'off'
+ },
+ compact: true
+ },
+ hosts: {
+ label: 'label.metrics.hosts'
+ },
+ cpuused: {
+ label: 'label.metrics.cpu.usage',
+ collapsible: true,
+ columns: {
+ cpuusedavg: {
+ label: 'label.metrics.cpu.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ },
+ cpumaxdev: {
+ label: 'label.metrics.cpu.max.dev'
+ }
+ }
+ },
+ cpuallocated: {
+ label: 'label.metrics.cpu.allocated',
+ collapsible: true,
+ columns: {
+ cpuallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ },
+ cputotal: {
+ label: 'label.metrics.cpu.total'
+ }
+ }
+ },
+ memused: {
+ label: 'label.metrics.memory.usage',
+ collapsible: true,
+ columns: {
+ memusedavg: {
+ label: 'label.metrics.memory.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ },
+ memmaxdev: {
+ label: 'label.metrics.memory.max.dev'
+ }
+ }
+ },
+ memallocated: {
+ label: 'label.metrics.memory.allocated',
+ collapsible: true,
+ columns: {
+ memallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ },
+ memtotal: {
+ label: 'label.metrics.memory.total'
+ }
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ if (args.context.metricsFilterData && args.context.metricsFilterData.key && args.context.metricsFilterData.value) {
+ data[args.context.metricsFilterData.key] = args.context.metricsFilterData.value;
+ }
+ $.ajax({
+ url: createURL('listClusters'),
+ 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'},
+ 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
+ });
+ }
+ });
+ },
+ browseBy: {
+ filterBy: 'clusterid',
+ resource: 'hosts'
+ },
+ detailView: cloudStack.sections.system.subsections.clusters.listView.detailView
+ }
+ };
+
+
+ // Hosts Metrics
+ cloudStack.sections.metrics.hosts = {
+ title: 'label.metrics',
+ listView: {
+ id: 'hosts',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Up': 'on',
+ 'Down': 'off',
+ 'Disconnected': 'off',
+ 'Removed': 'off',
+ 'Error': 'off',
+ 'Connecting': 'transition',
+ 'Rebalancing': 'transition',
+ 'Alert': 'warning',
+ },
+ compact: true
+ },
+ cpuused: {
+ label: 'label.metrics.cpu.usage',
+ collapsible: true,
+ columns: {
+ cores: {
+ label: 'label.metrics.num.cpu.cores',
+ },
+ cputotal: {
+ label: 'label.metrics.cpu.total'
+ },
+ cpuusedavg: {
+ label: 'label.metrics.cpu.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ },
+ cpuallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'cpunotificationthreshold',
+ disable: 'cpudisablethreshold'
+ }
+ }
+ }
+ },
+ memused: {
+ label: 'label.metrics.memory.usage',
+ collapsible: true,
+ columns: {
+ memtotal: {
+ label: 'label.metrics.memory.total'
+ },
+ memusedavg: {
+ label: 'label.metrics.memory.used.avg',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ },
+ memallocated: {
+ label: 'label.metrics.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'memnotificationthreshold',
+ disable: 'memdisablethreshold'
+ }
+ }
+ }
+ },
+ network: {
+ label: 'label.metrics.network.usage',
+ collapsible: true,
+ columns: {
+ networkread: {
+ label: 'label.metrics.network.read'
+ },
+ networkwrite: {
+ label: 'label.metrics.network.write'
+ }
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = {};
+ data.type = 'routing';
+ listViewDataProvider(args, data);
+ if (args.context.metricsFilterData && args.context.metricsFilterData.key && args.context.metricsFilterData.value) {
+ data[args.context.metricsFilterData.key] = args.context.metricsFilterData.value;
+ }
+ $.ajax({
+ url: createURL('listHosts'),
+ data: data,
+ success: function(json) {
+ var items = json.listhostsresponse.host;
+ if (items) {
+ $.each(items, function(idx, host) {
+ 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 = '';
+ }
+
+ // Threshold color coding
+ items[idx].cpunotificationthreshold = 0.75 * parseFloat(items[idx].cputotal);
+ items[idx].cpudisablethreshold = 0.95 * parseFloat(items[idx].cputotal);
+ items[idx].memnotificationthreshold = 0.75 * parseFloat(items[idx].memtotal);
+ items[idx].memdisablethreshold = 0.95 * 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);
+ break;
+ case 'cluster.cpu.allocated.capacity.notificationthreshold':
+ items[idx].cpunotificationthreshold = parseFloat(config.value) * parseFloat(items[idx].cputotal);
+ break;
+ case 'cluster.memory.allocated.capacity.disablethreshold':
+ items[idx].memdisablethreshold = parseFloat(config.value) * parseFloat(items[idx].memtotal);
+ break;
+ case 'cluster.memory.allocated.capacity.notificationthreshold':
+ items[idx].memnotificationthreshold = parseFloat(config.value) * parseFloat(items[idx].memtotal);
+ break;
+ }
+ });
+ }
+ },
+ async: false
+ });
+
+ 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 = cluster.cpuovercommitratio;
+ memOverCommit = cluster.memoryovercommitratio;
+ }
+ },
+ async: false
+ });
+
+ items[idx].cputotal = items[idx].cputotal + ' Ghz (x' + cpuOverCommit + ')';
+ items[idx].memtotal = items[idx].memtotal + ' (x' + memOverCommit + ')';
+ });
+ }
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ browseBy: {
+ filterBy: 'hostid',
+ resource: 'vms'
+ },
+ detailView: cloudStack.sections.system.subsections.hosts.listView.detailView
+ }
+ };
+
+
+ // VMs Metrics
+ cloudStack.sections.metrics.instances = {
+ title: 'label.metrics',
+ listView: {
+ id: 'instances',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Running': 'on',
+ 'Stopped': 'off',
+ 'Error': 'off',
+ 'Destroyed': 'off',
+ 'Expunging': 'off',
+ 'Stopping': 'transition',
+ 'Starting': 'transition',
+ 'Migrating': 'transition',
+ 'Shutdowned': 'warning',
+ },
+ compact: true
+ },
+ cpuused: {
+ label: 'label.metrics.cpu.usage',
+ collapsible: true,
+ columns: {
+ cores: {
+ label: 'label.metrics.num.cpu.cores',
+ },
+ cputotal: {
+ label: 'label.metrics.cpu.total'
+ },
+ cpuused: {
+ label: 'label.metrics.cpu.used.avg',
+ }
+ }
+ },
+ memused: {
+ label: 'label.metrics.memory.usage',
+ collapsible: true,
+ columns: {
+ memallocated: {
+ label: 'label.metrics.allocated'
+ }
+ }
+ },
+ network: {
+ label: 'label.metrics.network.usage',
+ collapsible: true,
+ columns: {
+ networkread: {
+ label: 'label.metrics.network.read'
+ },
+ networkwrite: {
+ label: 'label.metrics.network.write'
+ }
+ }
+ },
+ disk: {
+ label: 'label.metrics.disk.usage',
+ collapsible: true,
+ columns: {
+ diskread: {
+ label: 'label.metrics.disk.read'
+ },
+ diskwrite: {
+ label: 'label.metrics.disk.write'
+ },
+ diskiopstotal: {
+ label: 'label.metrics.disk.iops.total'
+ }
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ if (args.context.metricsFilterData && args.context.metricsFilterData.key && args.context.metricsFilterData.value) {
+ data[args.context.metricsFilterData.key] = args.context.metricsFilterData.value;
+ }
+ $.ajax({
+ url: createURL('listVirtualMachines'),
+ 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);
+
+ 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
+ });
+ }
+ });
+ },
+ browseBy: {
+ filterBy: 'virtualmachineid',
+ resource: 'volumes'
+ },
+ detailView: cloudStack.sections.instances.listView.detailView
+ }
+ };
+
+
+ // Volumes Metrics
+ cloudStack.sections.metrics.volumes = {
+ title: 'label.metrics',
+ listView: {
+ id: 'volumes',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Allocated': 'transition',
+ 'Creating': 'transition',
+ 'Ready': 'on',
+ 'Destroy': 'off',
+ 'Expunging': 'off',
+ 'Migrating': 'warning',
+ 'UploadOp': 'transition',
+ 'Snapshotting': 'warning',
+ },
+ compact: true
+ },
+ vmname: {
+ label: 'label.metrics.vm.name'
+ },
+ disksize: {
+ label: 'label.metrics.disk.size'
+ },
+ storagetype: {
+ label: 'label.metrics.disk.storagetype'
+ },
+ storagepool: {
+ label: 'label.metrics.storagepool'
+ },
+ },
+ dataProvider: function(args) {
+ var data = {listAll: true};
+ listViewDataProvider(args, data);
+ if (args.context.metricsFilterData && args.context.metricsFilterData.key && args.context.metricsFilterData.value) {
+ data[args.context.metricsFilterData.key] = args.context.metricsFilterData.value;
+ }
+ $.ajax({
+ url: createURL('listVolumes'),
+ 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
+ });
+ }
+ });
+ },
+ detailView: cloudStack.sections.storage.sections.volumes.listView.detailView
+ }
+ };
+
+
+ // Storage Pool Metrics
+ cloudStack.sections.metrics.storagepool = {
+ title: 'label.metrics',
+ listView: {
+ id: 'primarystorages',
+ fields: {
+ name: {
+ label: 'label.metrics.name'
+ },
+ property: {
+ label: 'label.metrics.property',
+ collapsible: true,
+ columns: {
+ state: {
+ label: 'label.metrics.state',
+ converter: function (str) {
+ // For localization
+ return str;
+ },
+ indicator: {
+ 'Up': 'on',
+ 'Down': 'off',
+ 'Removed': 'off',
+ 'ErrorInMaintenance': 'off',
+ 'PrepareForMaintenance': 'transition',
+ 'CancelMaintenance': 'warning',
+ 'Maintenance': 'warning',
+ },
+ compact: true
+ },
+ scope: {
+ label: 'label.metrics.scope'
+ },
+ type: {
+ label: 'label.metrics.disk.storagetype'
+ },
+ }
+ },
+ disk: {
+ label: 'label.metrics.disk',
+ collapsible: true,
+ columns: {
+ disksizeused: {
+ label: 'label.metrics.disk.used',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'storagenotificationthreshold',
+ disable: 'storagedisablethreshold'
+ }
+ },
+ disksizetotal: {
+ label: 'label.metrics.disk.total'
+ },
+ disksizeallocated: {
+ label: 'label.metrics.disk.allocated',
+ thresholdcolor: true,
+ thresholds: {
+ notification: 'storageallocatednotificationthreshold',
+ disable: 'storageallocateddisablethreshold'
+ }
+ },
+ disksizeunallocated: {
+ label: 'label.metrics.disk.unallocated'
+ }
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ if (args.context.metricsFilterData && args.context.metricsFilterData.key && args.context.metricsFilterData.value) {
+ data[args.context.metricsFilterData.key] = args.context.metricsFilterData.value;
+ }
+ $.ajax({
+ url: createURL('listStoragePools'),
+ 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) * 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) * 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
+ });
+ }
+ });
+ },
+ browseBy: {
+ filterBy: 'storageid',
+ resource: 'volumes'
+ },
+ detailView: cloudStack.sections.system.subsections['primary-storage'].listView.detailView
+ }
+ };
+
+})(cloudStack);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/storage.js
----------------------------------------------------------------------
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index d56835c..ee913f5 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -253,6 +253,23 @@
}
},
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'volumes'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
+ },
+
uploadVolume: {
isHeader: true,
label: 'label.upload.volume',
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/d34da5aa/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 7169a95..8d097f4 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -7622,7 +7622,7 @@
}
}
},
- show: cloudStack.uiCustom.physicalResources({
+ physicalResourceSection: {
sections: {
physicalResources: {
type: 'select',
@@ -7705,7 +7705,23 @@
});
}
}
- }
+ },
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'zones'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
+ },
},
detailView: {
@@ -9390,7 +9406,7 @@
}
}
}
- }),
+ },
subsections: {
virtualRouters: {
sectionSelect: {
@@ -14371,6 +14387,22 @@
}
});
}
+ },
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'clusters'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
}
},
@@ -15073,11 +15105,12 @@
}
if (! args.context.instances) {
- array1.push("&zoneid=" + args.context.zones[0].id);
+ if ("zones" in args.context)
+ array1.push("&zoneid=" + args.context.zones[0].id);
if ("pods" in args.context)
- array1.push("&podid=" + args.context.pods[0].id);
+ array1.push("&podid=" + args.context.pods[0].id);
if ("clusters" in args.context)
- array1.push("&clusterid=" + args.context.clusters[0].id);
+ array1.push("&clusterid=" + args.context.clusters[0].id);
} else {
//Instances menu > Instance detailView > View Hosts
array1.push("&id=" + args.context.instances[0].hostid);
@@ -15608,6 +15641,22 @@
return 'label.add.host';
}
}
+ },
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'hosts'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
}
},
detailView: {
@@ -17414,6 +17463,22 @@
return 'label.add.primary.storage';
}
}
+ },
+ viewMetrics: {
+ label: 'label.metrics',
+ isHeader: true,
+ addRow: false,
+ preFilter: function(args) {
+ return isAdmin();
+ },
+ action: {
+ custom: cloudStack.uiCustom.metricsView({resource: 'storagepool'})
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.metrics';
+ }
+ }
}
},
@@ -19649,7 +19714,10 @@
});
}
}
-
+
+ // Inject cloudStack infra page
+ cloudStack.sections.system.show = cloudStack.uiCustom.physicalResources(cloudStack.sections.system.physicalResourceSection);
+
function addExternalLoadBalancer(args, physicalNetworkObj, apiCmd, apiCmdRes, apiCmdObj) {
var array1 =[];
array1.push("&physicalnetworkid=" + physicalNetworkObj.id);
[6/7] git commit: updated refs/heads/4.5 to 2f250e2
Posted by bh...@apache.org.
CLOUDSTACK-9020: Metrics UI fixes
- Allow all users to see resource metrics
- Fix instance count issue on host metrics view
- Fix sorting issue
Signed-off-by: Rohit Yadav <ro...@shapeblue.com>
(cherry picked from commit 53084c4c8a87ccbdb1a7017e0a4cc66dbc386220)
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/ebee0f0c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ebee0f0c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ebee0f0c
Branch: refs/heads/4.5
Commit: ebee0f0c9de98d3fd0aaa6357dc87b753d557656
Parents: 0d73788
Author: Rohit Yadav <ro...@shapeblue.com>
Authored: Sat Nov 7 18:06:05 2015 +0530
Committer: Rohit Yadav <ro...@shapeblue.com>
Committed: Sun Nov 8 20:57:13 2015 +0530
----------------------------------------------------------------------
ui/scripts/instances.js | 3 ---
ui/scripts/metrics.js | 16 +++++++++-------
ui/scripts/storage.js | 3 ---
ui/scripts/system.js | 12 ------------
ui/scripts/ui/widgets/dataTable.js | 11 ++++++++---
5 files changed, 17 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebee0f0c/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index 68bf098..094957a 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -296,9 +296,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'vms'})
},
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebee0f0c/ui/scripts/metrics.js
----------------------------------------------------------------------
diff --git a/ui/scripts/metrics.js b/ui/scripts/metrics.js
index 7704469..609022a 100644
--- a/ui/scripts/metrics.js
+++ b/ui/scripts/metrics.js
@@ -159,7 +159,7 @@
items[idx].clusters += parseInt(json.listclustersresponse.count);
$.each(json.listclustersresponse.cluster, function(i, cluster) {
if (cluster.allocationstate == 'Enabled' && cluster.managedstate == 'Managed') {
- items[idx].clustersUp++;
+ items[idx].clustersUp += 1;
}
$.ajax({
url: createURL('listHosts'),
@@ -714,12 +714,14 @@
success: function(json) {
if (json && json.listvirtualmachinesresponse && json.listvirtualmachinesresponse.virtualmachine) {
var vms = json.listvirtualmachinesresponse.virtualmachine;
- $.each(vms, function(idx, vm) {
- items[idx].instances++;
- if (vm.state == 'Running') {
- items[idx].instancesUp++;
- }
- });
+ if (vms) {
+ $.each(vms, function(_, vm) {
+ items[idx].instances += 1;
+ if (vm.state == 'Running') {
+ items[idx].instancesUp += 1;
+ }
+ });
+ }
}
},
async: false
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebee0f0c/ui/scripts/storage.js
----------------------------------------------------------------------
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index ee913f5..78826a3 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -257,9 +257,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'volumes'})
},
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebee0f0c/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 8d097f4..3aafd8d 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -7710,9 +7710,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'zones'})
},
@@ -14392,9 +14389,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'clusters'})
},
@@ -15646,9 +15640,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'hosts'})
},
@@ -17468,9 +17459,6 @@
label: 'label.metrics',
isHeader: true,
addRow: false,
- preFilter: function(args) {
- return isAdmin();
- },
action: {
custom: cloudStack.uiCustom.metricsView({resource: 'storagepool'})
},
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebee0f0c/ui/scripts/ui/widgets/dataTable.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/dataTable.js b/ui/scripts/ui/widgets/dataTable.js
index 22ddda6..4574052 100644
--- a/ui/scripts/ui/widgets/dataTable.js
+++ b/ui/scripts/ui/widgets/dataTable.js
@@ -177,14 +177,19 @@
var sortData = [];
var numericDataCount = 0;
$elems.each(function() {
- var text = $(this).html();
+ var text = $(this);
if (hasAllRowsSameValue) {
- if (firstElem !== text) {
+ if (firstElem !== text.html()) {
hasAllRowsSameValue = false;
}
}
+ if (text.children()) {
+ text = text.children().html();
+ } else {
+ text = text.html();
+ }
if (isNumeric(text) || !text) {
- numericDataCount++;
+ numericDataCount += 1;
}
sortData.push($(this));
});