[PATCH 0/3] Host tab functionality split into Dashboard and Updates

From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com> Host tab functionality split into Dashboard and Updates Splitting host tab functionality into two tabs 1. Dashboard a. restart, shutdown buttons b. statistics c. debug reports 2. Updates a. Repositories b. Software updates Ginger Base screen shot change to reflect new ui New UI screen shot shows 1. New UI page 2. Feature tab split Issue 728 : processor info displays blank for system z UI changes to accommodate the basic system info 1. memory shows online, offline memory info 2. cpu shows online, offline cpu info On s390x deidcated, shared cpu info shown 3. On s390x hypervisor, LPAR details shown Note : Stage 1, debug reports is not moved to Administration tab. Have to experiment on having single tab hosting multiple plugin features. Till that time individual tab host single plugin features. Chandra Shekhar Reddy Potula (3): Host tab functionality split into Dashboard and Updates Ginger Base screen shot change to reflect new ui Issue 728 : processor info displays blank for system z .../gingerbase/docs/gingerbase-host-tab.png | Bin 79669 -> 105906 bytes src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 +- .../gingerbase/ui/css/src/modules/_host.scss | 9 +- .../ui/js/src/gingerbase.host-dashboard.js | 614 ++++++++++++++ .../gingerbase/ui/js/src/gingerbase.host-update.js | 405 +++++++++ .../gingerbase/ui/js/src/gingerbase.host.js | 928 --------------------- .../gingerbase/ui/pages/host-dashboard.html.tmpl | 143 ++++ .../gingerbase/ui/pages/host-update.html.tmpl | 90 ++ src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 156 ---- 9 files changed, 1265 insertions(+), 1090 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js delete mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl delete mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl -- 2.4.0

From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com> Splitting host tab functionality into two tabs 1. Dashboard a. restart, shutdown buttons b. statistics c. debug reports 2. Updates a. Repositories b. Software updates --- src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 +- .../ui/js/src/gingerbase.host-dashboard.js | 593 +++++++++++++ .../gingerbase/ui/js/src/gingerbase.host-update.js | 405 +++++++++ .../gingerbase/ui/js/src/gingerbase.host.js | 928 --------------------- .../gingerbase/ui/pages/host-dashboard.html.tmpl | 135 +++ .../gingerbase/ui/pages/host-update.html.tmpl | 90 ++ src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 156 ---- 7 files changed, 1231 insertions(+), 1086 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js delete mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl delete mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl diff --git a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml index 3d3f51e..f6f16d4 100644 --- a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml +++ b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml @@ -4,7 +4,13 @@ <tab> <access role="admin" mode="admin"/> <access role="user" mode="none"/> - <title>Host</title> - <path>plugins/gingerbase/host.html</path> + <title>Dashboard</title> + <path>plugins/gingerbase/host-dashboard.html</path> + </tab> + <tab> + <access role="admin" mode="admin"/> + <access role="user" mode="none"/> + <title>Updates</title> + <path>plugins/gingerbase/host-update.html</path> </tab> </tabs-ext> diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js new file mode 100644 index 0000000..047ba5b --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js @@ -0,0 +1,593 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_dashboard = function() { + "use strict"; + var reportGridID = 'available-reports-grid'; + var reportGrid = null; + var enableReportButtons = function(toEnable) { + var buttonID = '#{grid}-{btn}-button'; + $.each(['rename', 'remove', 'download'], function(i, n) { + $(wok.substitute(buttonID, { + grid: reportGridID, + btn: n + })).prop('disabled', !toEnable); + }); + }; + var initReportGrid = function(reports) { + reportGrid = new wok.widget.List({ + container: 'debug-report-section', + id: reportGridID, + title: i18n['GGBDR6002M'], + toolbarButtons: [{ + id: reportGridID + '-generate-button', + class: 'fa fa-plus-circle', + label: i18n['GGBDR6006M'], + onClick: function(event) { + wok.window.open('plugins/gingerbase/report-add.html'); + } + }, { + id: reportGridID + '-rename-button', + class: 'fa fa-pencil', + label: i18n['GGBDR6008M'], + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.selectedReport = report['name']; + wok.window.open('plugins/gingerbase/report-rename.html'); + } + }, { + id: reportGridID + '-download-button', + label: i18n['GGBDR6010M'], + class: 'fa fa-download', + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.downloadReport({ + file: report['uri'] + }); + } + }, { + id: reportGridID + '-remove-button', + class: 'fa fa-minus-circle', + label: i18n['GGBDR6009M'], + critical: true, + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + var settings = { + title: i18n['GGBAPI6004M'], + content: i18n['GGBDR6001M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteReport({ + name: report['name'] + }, function(result) { + listDebugReports(); + }, function(error) { + wok.message.error(error.responseJSON.reason); + }); + }); + } + }], + onRowSelected: function(row) { + var report = reportGrid.getSelected(); + // Only enable report buttons if the selected line is not a + // pending report + if (report['time'] === i18n['GGBDR6007M']) { + var gridElement = $('#' + reportGridID); + var row = $('tr:contains(' + report['name'] + ')', gridElement); + enableReportButtons(false); + row.attr('class', ''); + } else { + enableReportButtons(true); + } + }, + frozenFields: [], + fields: [{ + name: 'name', + label: i18n['GGBDR6003M'], + 'class': 'debug-report-name', + type: 'name' + }, { + name: 'time', + label: i18n['GGBDR6005M'], + 'class': 'debug-report-time', + type: 'description' + }], + data: reports + }); + }; + + var getPendingReports = function() { + var reports = []; + var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); + + gingerbase.getTasksByFilter(filter, function(tasks) { + for (var i = 0; i < tasks.length; i++) { + var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; + reports.push({ + 'name': reportName, + 'time': i18n['GGBDR6007M'] + }); + + if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + gingerbase.trackTask(tasks[i].id, function(result) { + wok.topic('gingerbase/debugReportAdded').publish(); + }, function(result) { + // Error message from Async Task status + if (result['message']) { + var errText = result['message']; + } + // Error message from standard gingerbase exception + else { + var errText = result['responseJSON']['reason']; + } + result && wok.message.error(errText); + wok.topic('gingerbase/debugReportAdded').publish(); + }, null); + } + }, null, true); + + return reports; + }; + + var listDebugReports = function() { + gingerbase.listReports(function(reports) { + var pendingReports = getPendingReports(); + var allReports = pendingReports.concat(reports); + $('#debug-report-section').removeClass('hidden'); +/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/ + + + // Row selection will be cleared so disable buttons here + enableReportButtons(false); + + if (reportGrid) { + reportGrid.setData(allReports); + } else { + initReportGrid(allReports); + } + + if (!allReports.length) { + $('#available-reports-grid-btn-group').removeClass('hidden'); + } else { + $('#available-reports-grid-btn-group').addClass('hidden'); + } + + // Set id-debug-img to pending reports + // It will display a loading icon + var gridElement = $('#' + reportGridID); + // "Generating..." + $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { + console.log(row); + $(row).parent().addClass('generating'); + $(row).parent().find('.dropdown-toggle').addClass('disabled'); + //$(row).attr('id', 'id-debug-img'); + }); + }, function(error) { + if (error['status'] === 403) { + $('#debug-report-section').addClass('hidden'); +/* + // Check Repositories and resize column + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#repositories-section').removeClass('col-md-4'); + $('#repositories-section').addClass('col-md-8'); + } else { + $('#content-sys-info').removeClass('col-md-4'); + $('#content-sys-info').addClass('col-md-12'); + } +*/ + return; + } + $('#debug-report-section').removeClass('hidden'); +/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/ + }); + }; + + var shutdownButtonID = '#host-button-shutdown'; + var restartButtonID = '#host-button-restart'; + var shutdownHost = function(params) { + var settings = { + content: i18n['GGBHOST6008M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + $(shutdownButtonID).prop('disabled', true); + $(restartButtonID).prop('disabled', true); + // Check if there is any VM is running. + // Based on the success will shutdown/reboot + gingerbase.shutdown(params, function(success) { + wok.message.success(i18n['GGBHOST6009M']) + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + return; + }, function(error) { + // Looks like VMs are running. + wok.message.error.code('GGBHOST6001E'); + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + }); + }, function() { + }); + }; + + var initPage = function() { + + $('#host-button-shutdown').on('click', function(event) { + event.preventDefault(); + shutdownHost(null); + }); + + $('#host-button-restart').on('click', function(event) { + event.preventDefault(); + shutdownHost({ + reboot: true + }); + }); + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if (gingerbase.capabilities['system_report_tool']) { + listDebugReports(); + wok.topic('gingerbase/debugReportAdded') + .subscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed') + .subscribe(listDebugReports); + } + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-dashboard-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + initTracker(); + }); + + var StatsMgr = function() { + var statsArray = { + cpu: { + u: { + type: 'percent', + legend: i18n['GGBHOST6002M'], + points: [] + } + }, + memory: { + u: { + type: 'value', + base: 2, + fixed: 2, + legend: i18n['GGBHOST6003M'], + points: [] + } + }, + diskIO: { + w: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6005M'], + 'class': 'disk-write', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6004M'], + points: [] + } + }, + networkIO: { + s: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6007M'], + 'class': 'network-sent', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6006M'], + points: [] + } + } + }; + var SIZE = 20; + var cursor = SIZE; + + var add = function(stats) { + for (var key in stats) { + var item = stats[key]; + for (var metrics in item) { + var value = item[metrics]['v']; + var max = item[metrics]['max']; + var unifiedMetrics = statsArray[key][metrics]; + var ps = unifiedMetrics['points']; + if (!Array.isArray(value)) { + ps.push(value); + if (ps.length > SIZE + 1) { + ps.shift(); + } + } else { + ps = ps.concat(value); + ps.splice(0, ps.length - SIZE - 1); + unifiedMetrics['points'] = ps; + } + if (max !== undefined) { + unifiedMetrics['max'] = max; + } else { + if (unifiedMetrics['type'] !== 'value') { + continue; + } + max = -Infinity; + $.each(ps, function(i, value) { + if (value > max) { + max = value; + } + }); + if (max === 0) { + ++max; + } + max *= 1.1; + unifiedMetrics['max'] = max; + } + } + } + cursor++; + }; + + var get = function(which) { + var stats = statsArray[which]; + var lines = []; + for (var k in stats) { + var obj = stats[k]; + var line = { + type: obj['type'], + base: obj['base'], + unit: obj['unit'], + fixed: obj['fixed'], + legend: obj['legend'] + }; + if (obj['max']) { + line['max'] = obj['max']; + } + if (obj['class']) { + line['class'] = obj['class']; + } + var ps = obj['points']; + var numStats = ps.length; + var unifiedPoints = []; + $.each(ps, function(i, value) { + unifiedPoints.push({ + x: cursor - numStats + i, + y: value + }); + }); + line['points'] = unifiedPoints; + lines.push(line); + } + return lines; + }; + + return { + add: add, + get: get + }; + }; + + var Tracker = function(charts) { + var charts = charts; + var timer = null; + var statsPool = new StatsMgr(); + var setCharts = function(newCharts) { + charts = newCharts; + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + }; + + var self = this; + + var UnifyStats = function(stats) { + var result = { + cpu: { + u: { + v: stats['cpu_utilization'] + } + }, + memory: { + u: {} + }, + diskIO: { + w: { + v: stats['disk_write_rate'] + }, + r: { + v: stats['disk_read_rate'] + } + }, + networkIO: { + s: { + v: stats['net_sent_rate'] + }, + r: { + v: stats['net_recv_rate'] + } + } + }; + if (Array.isArray(stats['memory'])) { + result.memory.u['v'] = []; + result.memory.u['max'] = -Infinity; + for (var i = 0; i < stats['memory'].length; i++) { + result.memory.u['v'].push(stats['memory'][i]['avail']); + result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); + } + } else { + result.memory.u['v'] = stats['memory']['avail'], + result.memory.u['max'] = stats['memory']['total'] + } + return (result); + }; + + + var statsCallback = function(stats) { + var unifiedStats = UnifyStats(stats); + statsPool.add(unifiedStats); + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + timer = setTimeout(function() { + continueTrack(); + }, 1000); + }; + + var track = function() { + gingerbase.getHostStatsHistory(statsCallback, + function() { + continueTrack(); + }); + }; + + var continueTrack = function() { + gingerbase.getHostStats(statsCallback, + function() { + continueTrack(); + }); + }; + + var destroy = function() { + timer && clearTimeout(timer); + timer = null; + }; + + return { + setCharts: setCharts, + start: track, + stop: destroy + }; + }; + + var initTracker = function() { + // TODO: Extend tabs with onUnload event to unregister timers. + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + var trackedCharts = { + cpu: new wok.widget.LineChart({ + id: 'chart-cpu', + node: 'container-chart-cpu', + type: 'percent' + }), + memory: new wok.widget.LineChart({ + id: 'chart-memory', + node: 'container-chart-memory', + type: 'value' + }), + diskIO: new wok.widget.LineChart({ + id: 'chart-disk-io', + node: 'container-chart-disk-io', + type: 'value' + }), + networkIO: new wok.widget.LineChart({ + id: 'chart-network-io', + node: 'container-chart-network-io', + type: 'value' + }) + }; + + if (gingerbase.hostTimer) { + gingerbase.hostTimer.setCharts(trackedCharts); + } else { + gingerbase.hostTimer = new Tracker(trackedCharts); + gingerbase.hostTimer.start(); + } + }; + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js new file mode 100644 index 0000000..ee89625 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js @@ -0,0 +1,405 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_update = function() { + "use strict"; + var repositoriesGrid = null; + var initRepositoriesGrid = function(repo_type) { + var gridFields = []; + if (repo_type === "yum") { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'config[display_repo_name]', + label: i18n['GGBREPO6005M'], + 'class': 'repository-name', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }]; + } else if (repo_type === "deb") { + gridFields = [{ + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl deb', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled deb', + type: 'status' + }, { + name: 'config[dist]', + label: "dist", + 'class': 'repository-gpgcheck deb' + }, { + name: 'config[comps]', + label: "comps", + 'class': 'repository-gpgcheck deb' + }]; + } else { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }, { + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl', + type: 'description' + }]; + } + repositoriesGrid = new wok.widget.List({ + container: 'repositories-section', + id: 'repositories-grid', + title: i18n['GGBREPO6003M'], + toolbarButtons: [{ + id: 'repositories-grid-add-button', + label: i18n['GGBREPO6012M'], + class: 'fa fa-plus-circle', + onClick: function(event) { + wok.window.open({ + url: 'plugins/gingerbase/repository-add.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-enable-button', + label: i18n['GGBREPO6016M'], + class: 'fa fa-play-circle-o', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var name = repository['repo_id']; + var enable = !repository['enabled']; + $(this).prop('disabled', true); + gingerbase.enableRepository(name, enable, function() { + wok.topic('gingerbase/repositoryUpdated').publish(); + }); + } + }, { + id: 'repositories-grid-edit-button', + label: i18n['GGBREPO6013M'], + class: 'fa fa-pencil', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + gingerbase.selectedRepository = repository['repo_id']; + wok.window.open({ + url: 'plugins/gingerbase/repository-edit.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-remove-button', + label: i18n['GGBREPO6014M'], + class: 'fa fa-minus-circle', + critical: true, + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + + var settings = { + title: i18n['GGBREPO6001M'], + content: i18n['GGBREPO6002M'], + confirm: i18n['GGBAPI6004M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteRepository( + repository['repo_id'], + function(result) { + wok.topic('gingerbase/repositoryDeleted').publish(result); + }, + function(error) {} + ); + }); + } + }], + onRowSelected: function(row) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var selectedRow = $('tr',repositoriesGrid.bodyContainer); + $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); + $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); + var enabled = repository['enabled']; + var actionHtml,actionText,actionIcon =''; + if(enabled){ + actionText= i18n['GGBREPO6017M']; + actionIcon = 'fa-pause'; + }else{ + actionText= i18n['GGBREPO6016M']; + actionIcon = 'fa-play-circle-o'; + } + actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); + $('#repositories-grid-enable-button',selectedRow) + .html(actionHtml) + .prop('disabled', false); + }, + frozenFields: [], + fields: gridFields, + data: listRepositories + }); + }; + + var listRepositories = function(gridCallback) { + gingerbase.listRepositories(function(repositories) { + if ($.isFunction(gridCallback)) { + gridCallback(repositories); + } else { + if (repositoriesGrid) { + repositoriesGrid.setData(repositories); + } else { + initRepositoriesGrid(); + repositoriesGrid.setData(repositories); + } + } + }, + function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + repositoriesGrid && + repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + + $('#repositories-grid-remove-button').prop('disabled', true); + $('#repositories-grid-edit-button').prop('disabled', true); + $('#repositories-grid-enable-button').prop('disabled', true); + }; + + var softwareUpdatesGridID = 'software-updates-grid'; + var softwareUpdatesGrid = null; + var progressAreaID = 'software-updates-progress-textarea'; + var reloadProgressArea = function(result) { + var progressArea = $('#' + progressAreaID)[0]; + $(progressArea).text(result['message']); + var scrollTop = $(progressArea).prop('scrollHeight'); + $(progressArea).prop('scrollTop', scrollTop); + }; + + var initSoftwareUpdatesGrid = function(softwareUpdates) { + softwareUpdatesGrid = new wok.widget.Grid({ + container: 'software-updates-grid-container', + id: softwareUpdatesGridID, + title: i18n['GGBUPD6001M'], + rowSelection: 'disabled', + toolbarButtons: [{ + id: softwareUpdatesGridID + '-update-button', + label: i18n['GGBUPD6006M'], + disabled: true, + onClick: function(event) { + var updateButton = $(this); + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); + + gingerbase.updateSoftware(function(result) { + reloadProgressArea(result); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + wok.message.error(message || i18n['GGBUPD6009M']); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + }, reloadProgressArea); + } + }], + frozenFields: [], + fields: [{ + name: 'package_name', + label: i18n['GGBUPD6002M'], + 'class': 'software-update-name' + }, { + name: 'version', + label: i18n['GGBUPD6003M'], + 'class': 'software-update-version' + }, { + name: 'arch', + label: i18n['GGBUPD6004M'], + 'class': 'software-update-arch' + }, { + name: 'repository', + label: i18n['GGBUPD6005M'], + 'class': 'software-update-repos' + }], + data: listSoftwareUpdates + }); + }; + + var startSoftwareUpdateProgress = function() { + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + + gingerbase.softwareUpdateProgress(function(result) { + reloadProgressArea(result); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + wok.message.warn(i18n['GGBUPD6010M']); + }, function(error) { + wok.message.error(i18n['GGBUPD6011M']); + }, reloadProgressArea); + }; + + var listSoftwareUpdates = function(gridCallback) { + gingerbase.listSoftwareUpdates(function(softwareUpdates) { + if ($.isFunction(gridCallback)) { + gridCallback(softwareUpdates); + } else { + if (softwareUpdatesGrid) { + softwareUpdatesGrid.setData(softwareUpdates); + } else { + initSoftwareUpdatesGrid(softwareUpdates); + } + } + + var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); + $(updateButton).prop('disabled', softwareUpdates.length === 0); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + // cannot get the list of packages because there is another + // package manager instance running, so follow that instance updates + if (message.indexOf("GGBPKGUPD0005E") !== -1) { + startSoftwareUpdateProgress(); + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + return; + } + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + softwareUpdatesGrid && + softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + }; + + var initPage = function() { + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); + $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); + wok.topic('gingerbase/repositoryAdded') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .subscribe(listRepositories); + } + + if (gingerbase.capabilities['update_tool']) { + $('#software-update-section').removeClass('hidden'); + initSoftwareUpdatesGrid(); + wok.topic('gingerbase/softwareUpdated') + .subscribe(listSoftwareUpdates); + } + + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-update-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + repositoriesGrid && repositoriesGrid.destroy(); + wok.topic('gingerbase/repositoryAdded') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .unsubscribe(listRepositories); + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + softwareUpdatesGrid && softwareUpdatesGrid.destroy(); + wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); + + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js deleted file mode 100644 index 4a237df..0000000 --- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Licensed 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. - */ -gingerbase.host = {}; - -gingerbase.host_main = function() { - "use strict"; - var repositoriesGrid = null; - var initRepositoriesGrid = function(repo_type) { - var gridFields = []; - if (repo_type === "yum") { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'config[display_repo_name]', - label: i18n['GGBREPO6005M'], - 'class': 'repository-name', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }]; - } else if (repo_type === "deb") { - gridFields = [{ - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl deb', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled deb', - type: 'status' - }, { - name: 'config[dist]', - label: "dist", - 'class': 'repository-gpgcheck deb' - }, { - name: 'config[comps]', - label: "comps", - 'class': 'repository-gpgcheck deb' - }]; - } else { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }, { - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl', - type: 'description' - }]; - } - repositoriesGrid = new wok.widget.List({ - container: 'repositories-section', - id: 'repositories-grid', - title: i18n['GGBREPO6003M'], - toolbarButtons: [{ - id: 'repositories-grid-add-button', - label: i18n['GGBREPO6012M'], - class: 'fa fa-plus-circle', - onClick: function(event) { - wok.window.open({ - url: 'plugins/gingerbase/repository-add.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-enable-button', - label: i18n['GGBREPO6016M'], - class: 'fa fa-play-circle-o', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var name = repository['repo_id']; - var enable = !repository['enabled']; - $(this).prop('disabled', true); - gingerbase.enableRepository(name, enable, function() { - wok.topic('gingerbase/repositoryUpdated').publish(); - }); - } - }, { - id: 'repositories-grid-edit-button', - label: i18n['GGBREPO6013M'], - class: 'fa fa-pencil', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - gingerbase.selectedRepository = repository['repo_id']; - wok.window.open({ - url: 'plugins/gingerbase/repository-edit.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-remove-button', - label: i18n['GGBREPO6014M'], - class: 'fa fa-minus-circle', - critical: true, - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - - var settings = { - title: i18n['GGBREPO6001M'], - content: i18n['GGBREPO6002M'], - confirm: i18n['GGBAPI6004M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteRepository( - repository['repo_id'], - function(result) { - wok.topic('gingerbase/repositoryDeleted').publish(result); - }, - function(error) {} - ); - }); - } - }], - onRowSelected: function(row) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var selectedRow = $('tr',repositoriesGrid.bodyContainer); - $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); - $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); - var enabled = repository['enabled']; - var actionHtml,actionText,actionIcon =''; - if(enabled){ - actionText= i18n['GGBREPO6017M']; - actionIcon = 'fa-pause'; - }else{ - actionText= i18n['GGBREPO6016M']; - actionIcon = 'fa-play-circle-o'; - } - actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); - $('#repositories-grid-enable-button',selectedRow) - .html(actionHtml) - .prop('disabled', false); - }, - frozenFields: [], - fields: gridFields, - data: listRepositories - }); - }; - - var listRepositories = function(gridCallback) { - gingerbase.listRepositories(function(repositories) { - if ($.isFunction(gridCallback)) { - gridCallback(repositories); - } else { - if (repositoriesGrid) { - repositoriesGrid.setData(repositories); - } else { - initRepositoriesGrid(); - repositoriesGrid.setData(repositories); - } - } - }, - function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - repositoriesGrid && - repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - - $('#repositories-grid-remove-button').prop('disabled', true); - $('#repositories-grid-edit-button').prop('disabled', true); - $('#repositories-grid-enable-button').prop('disabled', true); - }; - - var softwareUpdatesGridID = 'software-updates-grid'; - var softwareUpdatesGrid = null; - var progressAreaID = 'software-updates-progress-textarea'; - var reloadProgressArea = function(result) { - var progressArea = $('#' + progressAreaID)[0]; - $(progressArea).text(result['message']); - var scrollTop = $(progressArea).prop('scrollHeight'); - $(progressArea).prop('scrollTop', scrollTop); - }; - - var initSoftwareUpdatesGrid = function(softwareUpdates) { - softwareUpdatesGrid = new wok.widget.Grid({ - container: 'software-updates-grid-container', - id: softwareUpdatesGridID, - title: i18n['GGBUPD6001M'], - rowSelection: 'disabled', - toolbarButtons: [{ - id: softwareUpdatesGridID + '-update-button', - label: i18n['GGBUPD6006M'], - disabled: true, - onClick: function(event) { - var updateButton = $(this); - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); - - gingerbase.updateSoftware(function(result) { - reloadProgressArea(result); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - wok.message.error(message || i18n['GGBUPD6009M']); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - }, reloadProgressArea); - } - }], - frozenFields: [], - fields: [{ - name: 'package_name', - label: i18n['GGBUPD6002M'], - 'class': 'software-update-name' - }, { - name: 'version', - label: i18n['GGBUPD6003M'], - 'class': 'software-update-version' - }, { - name: 'arch', - label: i18n['GGBUPD6004M'], - 'class': 'software-update-arch' - }, { - name: 'repository', - label: i18n['GGBUPD6005M'], - 'class': 'software-update-repos' - }], - data: listSoftwareUpdates - }); - }; - - var startSoftwareUpdateProgress = function() { - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - - gingerbase.softwareUpdateProgress(function(result) { - reloadProgressArea(result); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - wok.message.warn(i18n['GGBUPD6010M']); - }, function(error) { - wok.message.error(i18n['GGBUPD6011M']); - }, reloadProgressArea); - }; - - var listSoftwareUpdates = function(gridCallback) { - gingerbase.listSoftwareUpdates(function(softwareUpdates) { - if ($.isFunction(gridCallback)) { - gridCallback(softwareUpdates); - } else { - if (softwareUpdatesGrid) { - softwareUpdatesGrid.setData(softwareUpdates); - } else { - initSoftwareUpdatesGrid(softwareUpdates); - } - } - - var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); - $(updateButton).prop('disabled', softwareUpdates.length === 0); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - // cannot get the list of packages because there is another - // package manager instance running, so follow that instance updates - if (message.indexOf("GGBPKGUPD0005E") !== -1) { - startSoftwareUpdateProgress(); - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - return; - } - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - softwareUpdatesGrid && - softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - }; - - var reportGridID = 'available-reports-grid'; - var reportGrid = null; - var enableReportButtons = function(toEnable) { - var buttonID = '#{grid}-{btn}-button'; - $.each(['rename', 'remove', 'download'], function(i, n) { - $(wok.substitute(buttonID, { - grid: reportGridID, - btn: n - })).prop('disabled', !toEnable); - }); - }; - var initReportGrid = function(reports) { - reportGrid = new wok.widget.List({ - container: 'debug-report-section', - id: reportGridID, - title: i18n['GGBDR6002M'], - toolbarButtons: [{ - id: reportGridID + '-generate-button', - class: 'fa fa-plus-circle', - label: i18n['GGBDR6006M'], - onClick: function(event) { - wok.window.open('plugins/gingerbase/report-add.html'); - } - }, { - id: reportGridID + '-rename-button', - class: 'fa fa-pencil', - label: i18n['GGBDR6008M'], - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.selectedReport = report['name']; - wok.window.open('plugins/gingerbase/report-rename.html'); - } - }, { - id: reportGridID + '-download-button', - label: i18n['GGBDR6010M'], - class: 'fa fa-download', - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.downloadReport({ - file: report['uri'] - }); - } - }, { - id: reportGridID + '-remove-button', - class: 'fa fa-minus-circle', - label: i18n['GGBDR6009M'], - critical: true, - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - var settings = { - title: i18n['GGBAPI6004M'], - content: i18n['GGBDR6001M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteReport({ - name: report['name'] - }, function(result) { - listDebugReports(); - }, function(error) { - wok.message.error(error.responseJSON.reason); - }); - }); - } - }], - onRowSelected: function(row) { - var report = reportGrid.getSelected(); - // Only enable report buttons if the selected line is not a - // pending report - if (report['time'] === i18n['GGBDR6007M']) { - var gridElement = $('#' + reportGridID); - var row = $('tr:contains(' + report['name'] + ')', gridElement); - enableReportButtons(false); - row.attr('class', ''); - } else { - enableReportButtons(true); - } - }, - frozenFields: [], - fields: [{ - name: 'name', - label: i18n['GGBDR6003M'], - 'class': 'debug-report-name', - type: 'name' - }, { - name: 'time', - label: i18n['GGBDR6005M'], - 'class': 'debug-report-time', - type: 'description' - }], - data: reports - }); - }; - - var getPendingReports = function() { - var reports = []; - var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); - - gingerbase.getTasksByFilter(filter, function(tasks) { - for (var i = 0; i < tasks.length; i++) { - var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; - reports.push({ - 'name': reportName, - 'time': i18n['GGBDR6007M'] - }); - - if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { - continue; - } - - gingerbase.trackTask(tasks[i].id, function(result) { - wok.topic('gingerbase/debugReportAdded').publish(); - }, function(result) { - // Error message from Async Task status - if (result['message']) { - var errText = result['message']; - } - // Error message from standard gingerbase exception - else { - var errText = result['responseJSON']['reason']; - } - result && wok.message.error(errText); - wok.topic('gingerbase/debugReportAdded').publish(); - }, null); - } - }, null, true); - - return reports; - }; - - var listDebugReports = function() { - gingerbase.listReports(function(reports) { - var pendingReports = getPendingReports(); - var allReports = pendingReports.concat(reports); - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - - - // Row selection will be cleared so disable buttons here - enableReportButtons(false); - - if (reportGrid) { - reportGrid.setData(allReports); - } else { - initReportGrid(allReports); - } - - if (!allReports.length) { - $('#available-reports-grid-btn-group').removeClass('hidden'); - } else { - $('#available-reports-grid-btn-group').addClass('hidden'); - } - - // Set id-debug-img to pending reports - // It will display a loading icon - var gridElement = $('#' + reportGridID); - // "Generating..." - $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { - console.log(row); - $(row).parent().addClass('generating'); - $(row).parent().find('.dropdown-toggle').addClass('disabled'); - //$(row).attr('id', 'id-debug-img'); - }); - }, function(error) { - if (error['status'] === 403) { - $('#debug-report-section').addClass('hidden'); - // Check Repositories and resize column - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#repositories-section').removeClass('col-md-4'); - $('#repositories-section').addClass('col-md-8'); - } else { - $('#content-sys-info').removeClass('col-md-4'); - $('#content-sys-info').addClass('col-md-12'); - } - return; - } - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - }); - }; - - var shutdownButtonID = '#host-button-shutdown'; - var restartButtonID = '#host-button-restart'; - var shutdownHost = function(params) { - var settings = { - content: i18n['GGBHOST6008M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - $(shutdownButtonID).prop('disabled', true); - $(restartButtonID).prop('disabled', true); - // Check if there is any VM is running. - // Based on the success will shutdown/reboot - gingerbase.shutdown(params, function(success) { - wok.message.success(i18n['GGBHOST6009M']) - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - return; - }, function(error) { - // Looks like VMs are running. - wok.message.error.code('GGBHOST6001E'); - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - }); - }, function() { - }); - }; - - var initPage = function() { - - $('#host-button-shutdown').on('click', function(event) { - event.preventDefault(); - shutdownHost(null); - }); - - $('#host-button-restart').on('click', function(event) { - event.preventDefault(); - shutdownHost({ - reboot: true - }); - }); - - var setupUI = function() { - if (gingerbase.capabilities === undefined) { - setTimeout(setupUI, 2000); - return; - } - - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); - $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); - wok.topic('gingerbase/repositoryAdded') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .subscribe(listRepositories); - } - - if (gingerbase.capabilities['update_tool']) { - $('#software-update-section').removeClass('hidden'); - initSoftwareUpdatesGrid(); - wok.topic('gingerbase/softwareUpdated') - .subscribe(listSoftwareUpdates); - } - - if (gingerbase.capabilities['system_report_tool']) { - listDebugReports(); - wok.topic('gingerbase/debugReportAdded') - .subscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed') - .subscribe(listDebugReports); - } - }; - setupUI(); - }; - - gingerbase.getHost(function(data) { - var htmlTmpl = $('#host-tmpl').html(); - data['logo'] = data['logo'] || ''; - data['memory'] = wok.formatMeasurement(data['memory'], { - fixed: 2 - }); - var templated = wok.substitute(htmlTmpl, data); - $('#host-content-container').html(templated); - - initPage(); - initTracker(); - }); - - var StatsMgr = function() { - var statsArray = { - cpu: { - u: { - type: 'percent', - legend: i18n['GGBHOST6002M'], - points: [] - } - }, - memory: { - u: { - type: 'value', - base: 2, - fixed: 2, - legend: i18n['GGBHOST6003M'], - points: [] - } - }, - diskIO: { - w: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6005M'], - 'class': 'disk-write', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6004M'], - points: [] - } - }, - networkIO: { - s: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6007M'], - 'class': 'network-sent', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6006M'], - points: [] - } - } - }; - var SIZE = 20; - var cursor = SIZE; - - var add = function(stats) { - for (var key in stats) { - var item = stats[key]; - for (var metrics in item) { - var value = item[metrics]['v']; - var max = item[metrics]['max']; - var unifiedMetrics = statsArray[key][metrics]; - var ps = unifiedMetrics['points']; - if (!Array.isArray(value)) { - ps.push(value); - if (ps.length > SIZE + 1) { - ps.shift(); - } - } else { - ps = ps.concat(value); - ps.splice(0, ps.length - SIZE - 1); - unifiedMetrics['points'] = ps; - } - if (max !== undefined) { - unifiedMetrics['max'] = max; - } else { - if (unifiedMetrics['type'] !== 'value') { - continue; - } - max = -Infinity; - $.each(ps, function(i, value) { - if (value > max) { - max = value; - } - }); - if (max === 0) { - ++max; - } - max *= 1.1; - unifiedMetrics['max'] = max; - } - } - } - cursor++; - }; - - var get = function(which) { - var stats = statsArray[which]; - var lines = []; - for (var k in stats) { - var obj = stats[k]; - var line = { - type: obj['type'], - base: obj['base'], - unit: obj['unit'], - fixed: obj['fixed'], - legend: obj['legend'] - }; - if (obj['max']) { - line['max'] = obj['max']; - } - if (obj['class']) { - line['class'] = obj['class']; - } - var ps = obj['points']; - var numStats = ps.length; - var unifiedPoints = []; - $.each(ps, function(i, value) { - unifiedPoints.push({ - x: cursor - numStats + i, - y: value - }); - }); - line['points'] = unifiedPoints; - lines.push(line); - } - return lines; - }; - - return { - add: add, - get: get - }; - }; - - var Tracker = function(charts) { - var charts = charts; - var timer = null; - var statsPool = new StatsMgr(); - var setCharts = function(newCharts) { - charts = newCharts; - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - }; - - var self = this; - - var UnifyStats = function(stats) { - var result = { - cpu: { - u: { - v: stats['cpu_utilization'] - } - }, - memory: { - u: {} - }, - diskIO: { - w: { - v: stats['disk_write_rate'] - }, - r: { - v: stats['disk_read_rate'] - } - }, - networkIO: { - s: { - v: stats['net_sent_rate'] - }, - r: { - v: stats['net_recv_rate'] - } - } - }; - if (Array.isArray(stats['memory'])) { - result.memory.u['v'] = []; - result.memory.u['max'] = -Infinity; - for (var i = 0; i < stats['memory'].length; i++) { - result.memory.u['v'].push(stats['memory'][i]['avail']); - result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); - } - } else { - result.memory.u['v'] = stats['memory']['avail'], - result.memory.u['max'] = stats['memory']['total'] - } - return (result); - }; - - - var statsCallback = function(stats) { - var unifiedStats = UnifyStats(stats); - statsPool.add(unifiedStats); - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - timer = setTimeout(function() { - continueTrack(); - }, 1000); - }; - - var track = function() { - gingerbase.getHostStatsHistory(statsCallback, - function() { - continueTrack(); - }); - }; - - var continueTrack = function() { - gingerbase.getHostStats(statsCallback, - function() { - continueTrack(); - }); - }; - - var destroy = function() { - timer && clearTimeout(timer); - timer = null; - }; - - return { - setCharts: setCharts, - start: track, - stop: destroy - }; - }; - - var initTracker = function() { - // TODO: Extend tabs with onUnload event to unregister timers. - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - var trackedCharts = { - cpu: new wok.widget.LineChart({ - id: 'chart-cpu', - node: 'container-chart-cpu', - type: 'percent' - }), - memory: new wok.widget.LineChart({ - id: 'chart-memory', - node: 'container-chart-memory', - type: 'value' - }), - diskIO: new wok.widget.LineChart({ - id: 'chart-disk-io', - node: 'container-chart-disk-io', - type: 'value' - }), - networkIO: new wok.widget.LineChart({ - id: 'chart-network-io', - node: 'container-chart-network-io', - type: 'value' - }) - }; - - if (gingerbase.hostTimer) { - gingerbase.hostTimer.setCharts(trackedCharts); - } else { - gingerbase.hostTimer = new Tracker(trackedCharts); - gingerbase.hostTimer.start(); - } - }; - - $('#host-root-container').on('remove', function() { - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - repositoriesGrid && repositoriesGrid.destroy(); - wok.topic('gingerbase/repositoryAdded') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .unsubscribe(listRepositories); - - softwareUpdatesGrid && softwareUpdatesGrid.destroy(); - wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); - - reportGrid && reportGrid.destroy(); - wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); - }); -}; diff --git a/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl new file mode 100644 index 0000000..06b8088 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl @@ -0,0 +1,135 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + <ul class="nav navbar-nav navbar-right tools"> + <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> + <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> + <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> + </ul> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-dashboard-tmpl" type="gingerbase/template"> +<div class="host-dashboard"> + <div class="container"> + <div id="alert-container"></div> + <div id="content-sys-statistics" class="row"> + <div class="col-md-3"> + <div id="cpu-dashboard"> + <h3 class="section-label">$_("CPU")</h3> + <div class="section-value"> + <div id="container-chart-cpu" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="memory-dashboard"> + <h3 class="section-label">$_("Memory")</h3> + <div class="section-value"> + <div id="container-chart-memory" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="disk-dashboard"> + <h3 class="section-label">$_("Disk I/O")</h3> + <div class="section-value"> + <div id="container-chart-disk-io" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="network-dashboard"> + <h3 class="section-label">$_("Network I/O")</h3> + <div class="section-value"> + <div id="container-chart-network-io" class="inline-block"></div> + </div> + </div> + </div> + </div> + </div> +</div> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="content-sys-info" class="panel panel-default col-md-6"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Basic Information")</h3> + </div> + <div class="panel-body"> + <dl class="basic-information-list"> + <dt>{os_distro}</dt> + <dd>$_("OS Distro")</dd> + <dt>{os_version}</dt> + <dd>$_("OS Version")</dd> + <dt>{os_codename}</dt> + <dd>$_("OS Code Name")</dd> + <dt>{cpu_model}</dt> + <dd>$_("Processor")</dd> + <dt>{cpus}</dt> + <dd>$_("CPU(s)")</dd> + <dt>{memory}</dt> + <dd>$_("Memory")</dd> + </dl> + </div> + </div> + <div id="debug-report-section" class="col-md-6 hidden"></div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_dashboard(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl new file mode 100644 index 0000000..20790ed --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl @@ -0,0 +1,90 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-update-tmpl" type="gingerbase/template"> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="repositories-section" class="col-md-12 hidden"></div> + </div> + <div class="row"> + <div id="software-update-section" class="panel panel-default col-md-12 hidden"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Software Updates")</h3> + </div> + <div id="content-software-update" class="panel panel-default"> + <div id="software-updates-grid-container"></div> + <div id="software-updates-progress-container" class="hidden"> + <div class="software-updates-main"> + <h3> + <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> + <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> + </a> + </h3> + <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> + </div> + </div> + </div> + </div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_update(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl deleted file mode 100644 index d17f184..0000000 --- a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl +++ /dev/null @@ -1,156 +0,0 @@ -#* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Code derived from Project Kimchi - * - * Licensed 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. - *# - -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<html> -<head> -<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> -<script src="plugins/gingerbase/js/gingerbase.min.js"></script> -</head> -<body> -<div id="host-root-container"> -<nav class="navbar navbar-default toolbar"> - <div class="container"> - <!-- Brand and toggle get grouped for better mobile display --> - <div class="navbar-header"> - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - - <!-- Collect the nav links, forms, and other content for toggling --> - <div class="collapse navbar-collapse" id="toolbar"> - <ul class="nav navbar-nav navbar-right tools"> - <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> - <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> - <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> - </ul> - </div> - </div> -</nav> - <div id="host-content-container" class="empty-when-logged-off"></div> -</div> - -<script id="host-tmpl" type="gingerbase/template"> -<div class="host-dashboard"> - <div class="container"> - <div id="alert-container"></div> - <div id="content-sys-statistics" class="row"> - <div class="col-md-3"> - <div id="cpu-dashboard"> - <h3 class="section-label">$_("CPU")</h3> - <div class="section-value"> - <div id="container-chart-cpu" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="memory-dashboard"> - <h3 class="section-label">$_("Memory")</h3> - <div class="section-value"> - <div id="container-chart-memory" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="disk-dashboard"> - <h3 class="section-label">$_("Disk I/O")</h3> - <div class="section-value"> - <div id="container-chart-disk-io" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="network-dashboard"> - <h3 class="section-label">$_("Network I/O")</h3> - <div class="section-value"> - <div id="container-chart-network-io" class="inline-block"></div> - </div> - </div> - </div> - </div> - </div> -</div> -<div class="host-panel"> - <div class="container"> - <div id="host-info-container" class="row"> - <div id="content-sys-info" class="panel panel-default col-md-12"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Basic Information")</h3> - </div> - <div class="panel-body"> - <dl class="basic-information-list"> - <dt>{os_distro}</dt> - <dd>$_("OS Distro")</dd> - <dt>{os_version}</dt> - <dd>$_("OS Version")</dd> - <dt>{os_codename}</dt> - <dd>$_("OS Code Name")</dd> - <dt>{cpu_model}</dt> - <dd>$_("Processor")</dd> - <dt>{cpus}</dt> - <dd>$_("CPU(s)")</dd> - <dt>{memory}</dt> - <dd>$_("Memory")</dd> - </dl> - </div> - </div> - <div id="repositories-section" class="col-md-8 hidden"></div> - <div id="debug-report-section" class="col-md-8 hidden"></div> - </div> - <div class="row"> - <div id="software-update-section" class="panel panel-default col-md-12 hidden"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Software Updates")</h3> - </div> - <div id="content-software-update" class="panel panel-default"> - <div id="software-updates-grid-container"></div> - <div id="software-updates-progress-container" class="hidden"> - <div class="software-updates-main"> - <h3> - <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> - <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> - </a> - </h3> - <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> - </div> - </div> - </div> - </div> - </div> - </div> -</div> -</script> -<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> -</div> -<script type="text/javascript"> - gingerbase.host_main(); -</script> -</body> -</html> -- 2.4.0

On 26/11/2015 10:53, chandra@linux.vnet.ibm.com wrote:
From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com>
Splitting host tab functionality into two tabs 1. Dashboard a. restart, shutdown buttons b. statistics c. debug reports 2. Updates a. Repositories b. Software updates --- src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 +- .../ui/js/src/gingerbase.host-dashboard.js | 593 +++++++++++++ .../gingerbase/ui/js/src/gingerbase.host-update.js | 405 +++++++++ .../gingerbase/ui/js/src/gingerbase.host.js | 928 --------------------- .../gingerbase/ui/pages/host-dashboard.html.tmpl | 135 +++ .../gingerbase/ui/pages/host-update.html.tmpl | 90 ++ src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 156 ---- 7 files changed, 1231 insertions(+), 1086 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js delete mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl delete mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl
diff --git a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml index 3d3f51e..f6f16d4 100644 --- a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml +++ b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml @@ -4,7 +4,13 @@ <tab> <access role="admin" mode="admin"/> <access role="user" mode="none"/> - <title>Host</title> - <path>plugins/gingerbase/host.html</path> + <title>Dashboard</title> + <path>plugins/gingerbase/host-dashboard.html</path> + </tab> + <tab> + <access role="admin" mode="admin"/> + <access role="user" mode="none"/> + <title>Updates</title> + <path>plugins/gingerbase/host-update.html</path> </tab> </tabs-ext> diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js new file mode 100644 index 0000000..047ba5b --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js @@ -0,0 +1,593 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_dashboard = function() { + "use strict"; + var reportGridID = 'available-reports-grid'; + var reportGrid = null; + var enableReportButtons = function(toEnable) { + var buttonID = '#{grid}-{btn}-button'; + $.each(['rename', 'remove', 'download'], function(i, n) { + $(wok.substitute(buttonID, { + grid: reportGridID, + btn: n + })).prop('disabled', !toEnable); + }); + }; + var initReportGrid = function(reports) { + reportGrid = new wok.widget.List({ + container: 'debug-report-section', + id: reportGridID, + title: i18n['GGBDR6002M'], + toolbarButtons: [{ + id: reportGridID + '-generate-button', + class: 'fa fa-plus-circle', + label: i18n['GGBDR6006M'], + onClick: function(event) { + wok.window.open('plugins/gingerbase/report-add.html'); + } + }, { + id: reportGridID + '-rename-button', + class: 'fa fa-pencil', + label: i18n['GGBDR6008M'], + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.selectedReport = report['name']; + wok.window.open('plugins/gingerbase/report-rename.html'); + } + }, { + id: reportGridID + '-download-button', + label: i18n['GGBDR6010M'], + class: 'fa fa-download', + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.downloadReport({ + file: report['uri'] + }); + } + }, { + id: reportGridID + '-remove-button', + class: 'fa fa-minus-circle', + label: i18n['GGBDR6009M'], + critical: true, + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + var settings = { + title: i18n['GGBAPI6004M'], + content: i18n['GGBDR6001M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteReport({ + name: report['name'] + }, function(result) { + listDebugReports(); + }, function(error) { + wok.message.error(error.responseJSON.reason); + }); + }); + } + }], + onRowSelected: function(row) { + var report = reportGrid.getSelected(); + // Only enable report buttons if the selected line is not a + // pending report + if (report['time'] === i18n['GGBDR6007M']) { + var gridElement = $('#' + reportGridID); + var row = $('tr:contains(' + report['name'] + ')', gridElement); + enableReportButtons(false); + row.attr('class', ''); + } else { + enableReportButtons(true); + } + }, + frozenFields: [], + fields: [{ + name: 'name', + label: i18n['GGBDR6003M'], + 'class': 'debug-report-name', + type: 'name' + }, { + name: 'time', + label: i18n['GGBDR6005M'], + 'class': 'debug-report-time', + type: 'description' + }], + data: reports + }); + }; + + var getPendingReports = function() { + var reports = []; + var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); + + gingerbase.getTasksByFilter(filter, function(tasks) { + for (var i = 0; i < tasks.length; i++) { + var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; + reports.push({ + 'name': reportName, + 'time': i18n['GGBDR6007M'] + }); + + if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + gingerbase.trackTask(tasks[i].id, function(result) { + wok.topic('gingerbase/debugReportAdded').publish(); + }, function(result) { + // Error message from Async Task status + if (result['message']) { + var errText = result['message']; + } + // Error message from standard gingerbase exception + else { + var errText = result['responseJSON']['reason']; + } + result && wok.message.error(errText); + wok.topic('gingerbase/debugReportAdded').publish(); + }, null); + } + }, null, true); + + return reports; + }; + + var listDebugReports = function() { + gingerbase.listReports(function(reports) { + var pendingReports = getPendingReports(); + var allReports = pendingReports.concat(reports); + $('#debug-report-section').removeClass('hidden');
+/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/ +
Can the above block be removed as it is commeted?
+ + // Row selection will be cleared so disable buttons here + enableReportButtons(false); + + if (reportGrid) { + reportGrid.setData(allReports); + } else { + initReportGrid(allReports); + } + + if (!allReports.length) { + $('#available-reports-grid-btn-group').removeClass('hidden'); + } else { + $('#available-reports-grid-btn-group').addClass('hidden'); + } + + // Set id-debug-img to pending reports + // It will display a loading icon + var gridElement = $('#' + reportGridID); + // "Generating..." + $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { + console.log(row); + $(row).parent().addClass('generating'); + $(row).parent().find('.dropdown-toggle').addClass('disabled'); + //$(row).attr('id', 'id-debug-img'); + }); + }, function(error) { + if (error['status'] === 403) { + $('#debug-report-section').addClass('hidden');
+/* + // Check Repositories and resize column + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#repositories-section').removeClass('col-md-4'); + $('#repositories-section').addClass('col-md-8'); + } else { + $('#content-sys-info').removeClass('col-md-4'); + $('#content-sys-info').addClass('col-md-12'); + } +*/
Same here.
+ return; + } + $('#debug-report-section').removeClass('hidden');
+/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/
And here.
+ }); + }; + + var shutdownButtonID = '#host-button-shutdown'; + var restartButtonID = '#host-button-restart'; + var shutdownHost = function(params) { + var settings = { + content: i18n['GGBHOST6008M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + $(shutdownButtonID).prop('disabled', true); + $(restartButtonID).prop('disabled', true); + // Check if there is any VM is running. + // Based on the success will shutdown/reboot + gingerbase.shutdown(params, function(success) { + wok.message.success(i18n['GGBHOST6009M']) + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + return; + }, function(error) { + // Looks like VMs are running. + wok.message.error.code('GGBHOST6001E'); + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + }); + }, function() { + }); + }; + + var initPage = function() { + + $('#host-button-shutdown').on('click', function(event) { + event.preventDefault(); + shutdownHost(null); + }); + + $('#host-button-restart').on('click', function(event) { + event.preventDefault(); + shutdownHost({ + reboot: true + }); + }); + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if (gingerbase.capabilities['system_report_tool']) { + listDebugReports(); + wok.topic('gingerbase/debugReportAdded') + .subscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed') + .subscribe(listDebugReports); + } + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-dashboard-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + initTracker(); + }); + + var StatsMgr = function() { + var statsArray = { + cpu: { + u: { + type: 'percent', + legend: i18n['GGBHOST6002M'], + points: [] + } + }, + memory: { + u: { + type: 'value', + base: 2, + fixed: 2, + legend: i18n['GGBHOST6003M'], + points: [] + } + }, + diskIO: { + w: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6005M'], + 'class': 'disk-write', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6004M'], + points: [] + } + }, + networkIO: { + s: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6007M'], + 'class': 'network-sent', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6006M'], + points: [] + } + } + }; + var SIZE = 20; + var cursor = SIZE; + + var add = function(stats) { + for (var key in stats) { + var item = stats[key]; + for (var metrics in item) { + var value = item[metrics]['v']; + var max = item[metrics]['max']; + var unifiedMetrics = statsArray[key][metrics]; + var ps = unifiedMetrics['points']; + if (!Array.isArray(value)) { + ps.push(value); + if (ps.length > SIZE + 1) { + ps.shift(); + } + } else { + ps = ps.concat(value); + ps.splice(0, ps.length - SIZE - 1); + unifiedMetrics['points'] = ps; + } + if (max !== undefined) { + unifiedMetrics['max'] = max; + } else { + if (unifiedMetrics['type'] !== 'value') { + continue; + } + max = -Infinity; + $.each(ps, function(i, value) { + if (value > max) { + max = value; + } + }); + if (max === 0) { + ++max; + } + max *= 1.1; + unifiedMetrics['max'] = max; + } + } + } + cursor++; + }; + + var get = function(which) { + var stats = statsArray[which]; + var lines = []; + for (var k in stats) { + var obj = stats[k]; + var line = { + type: obj['type'], + base: obj['base'], + unit: obj['unit'], + fixed: obj['fixed'], + legend: obj['legend'] + }; + if (obj['max']) { + line['max'] = obj['max']; + } + if (obj['class']) { + line['class'] = obj['class']; + } + var ps = obj['points']; + var numStats = ps.length; + var unifiedPoints = []; + $.each(ps, function(i, value) { + unifiedPoints.push({ + x: cursor - numStats + i, + y: value + }); + }); + line['points'] = unifiedPoints; + lines.push(line); + } + return lines; + }; + + return { + add: add, + get: get + }; + }; + + var Tracker = function(charts) { + var charts = charts; + var timer = null; + var statsPool = new StatsMgr(); + var setCharts = function(newCharts) { + charts = newCharts; + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + }; + + var self = this; + + var UnifyStats = function(stats) { + var result = { + cpu: { + u: { + v: stats['cpu_utilization'] + } + }, + memory: { + u: {} + }, + diskIO: { + w: { + v: stats['disk_write_rate'] + }, + r: { + v: stats['disk_read_rate'] + } + }, + networkIO: { + s: { + v: stats['net_sent_rate'] + }, + r: { + v: stats['net_recv_rate'] + } + } + }; + if (Array.isArray(stats['memory'])) { + result.memory.u['v'] = []; + result.memory.u['max'] = -Infinity; + for (var i = 0; i < stats['memory'].length; i++) { + result.memory.u['v'].push(stats['memory'][i]['avail']); + result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); + } + } else { + result.memory.u['v'] = stats['memory']['avail'], + result.memory.u['max'] = stats['memory']['total'] + } + return (result); + }; + + + var statsCallback = function(stats) { + var unifiedStats = UnifyStats(stats); + statsPool.add(unifiedStats); + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + timer = setTimeout(function() { + continueTrack(); + }, 1000); + }; + + var track = function() { + gingerbase.getHostStatsHistory(statsCallback, + function() { + continueTrack(); + }); + }; + + var continueTrack = function() { + gingerbase.getHostStats(statsCallback, + function() { + continueTrack(); + }); + }; + + var destroy = function() { + timer && clearTimeout(timer); + timer = null; + }; + + return { + setCharts: setCharts, + start: track, + stop: destroy + }; + }; + + var initTracker = function() { + // TODO: Extend tabs with onUnload event to unregister timers. + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + var trackedCharts = { + cpu: new wok.widget.LineChart({ + id: 'chart-cpu', + node: 'container-chart-cpu', + type: 'percent' + }), + memory: new wok.widget.LineChart({ + id: 'chart-memory', + node: 'container-chart-memory', + type: 'value' + }), + diskIO: new wok.widget.LineChart({ + id: 'chart-disk-io', + node: 'container-chart-disk-io', + type: 'value' + }), + networkIO: new wok.widget.LineChart({ + id: 'chart-network-io', + node: 'container-chart-network-io', + type: 'value' + }) + }; + + if (gingerbase.hostTimer) { + gingerbase.hostTimer.setCharts(trackedCharts); + } else { + gingerbase.hostTimer = new Tracker(trackedCharts); + gingerbase.hostTimer.start(); + } + }; + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js new file mode 100644 index 0000000..ee89625 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js @@ -0,0 +1,405 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_update = function() { + "use strict"; + var repositoriesGrid = null; + var initRepositoriesGrid = function(repo_type) { + var gridFields = []; + if (repo_type === "yum") { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'config[display_repo_name]', + label: i18n['GGBREPO6005M'], + 'class': 'repository-name', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }]; + } else if (repo_type === "deb") { + gridFields = [{ + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl deb', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled deb', + type: 'status' + }, { + name: 'config[dist]', + label: "dist", + 'class': 'repository-gpgcheck deb' + }, { + name: 'config[comps]', + label: "comps", + 'class': 'repository-gpgcheck deb' + }]; + } else { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }, { + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl', + type: 'description' + }]; + } + repositoriesGrid = new wok.widget.List({ + container: 'repositories-section', + id: 'repositories-grid', + title: i18n['GGBREPO6003M'], + toolbarButtons: [{ + id: 'repositories-grid-add-button', + label: i18n['GGBREPO6012M'], + class: 'fa fa-plus-circle', + onClick: function(event) { + wok.window.open({ + url: 'plugins/gingerbase/repository-add.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-enable-button', + label: i18n['GGBREPO6016M'], + class: 'fa fa-play-circle-o', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var name = repository['repo_id']; + var enable = !repository['enabled']; + $(this).prop('disabled', true); + gingerbase.enableRepository(name, enable, function() { + wok.topic('gingerbase/repositoryUpdated').publish(); + }); + } + }, { + id: 'repositories-grid-edit-button', + label: i18n['GGBREPO6013M'], + class: 'fa fa-pencil', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + gingerbase.selectedRepository = repository['repo_id']; + wok.window.open({ + url: 'plugins/gingerbase/repository-edit.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-remove-button', + label: i18n['GGBREPO6014M'], + class: 'fa fa-minus-circle', + critical: true, + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + + var settings = { + title: i18n['GGBREPO6001M'], + content: i18n['GGBREPO6002M'], + confirm: i18n['GGBAPI6004M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteRepository( + repository['repo_id'], + function(result) { + wok.topic('gingerbase/repositoryDeleted').publish(result); + }, + function(error) {} + ); + }); + } + }], + onRowSelected: function(row) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var selectedRow = $('tr',repositoriesGrid.bodyContainer); + $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); + $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); + var enabled = repository['enabled']; + var actionHtml,actionText,actionIcon =''; + if(enabled){ + actionText= i18n['GGBREPO6017M']; + actionIcon = 'fa-pause'; + }else{ + actionText= i18n['GGBREPO6016M']; + actionIcon = 'fa-play-circle-o'; + } + actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); + $('#repositories-grid-enable-button',selectedRow) + .html(actionHtml) + .prop('disabled', false); + }, + frozenFields: [], + fields: gridFields, + data: listRepositories + }); + }; + + var listRepositories = function(gridCallback) { + gingerbase.listRepositories(function(repositories) { + if ($.isFunction(gridCallback)) { + gridCallback(repositories); + } else { + if (repositoriesGrid) { + repositoriesGrid.setData(repositories); + } else { + initRepositoriesGrid(); + repositoriesGrid.setData(repositories); + } + } + }, + function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + repositoriesGrid && + repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + + $('#repositories-grid-remove-button').prop('disabled', true); + $('#repositories-grid-edit-button').prop('disabled', true); + $('#repositories-grid-enable-button').prop('disabled', true); + }; + + var softwareUpdatesGridID = 'software-updates-grid'; + var softwareUpdatesGrid = null; + var progressAreaID = 'software-updates-progress-textarea'; + var reloadProgressArea = function(result) { + var progressArea = $('#' + progressAreaID)[0]; + $(progressArea).text(result['message']); + var scrollTop = $(progressArea).prop('scrollHeight'); + $(progressArea).prop('scrollTop', scrollTop); + }; + + var initSoftwareUpdatesGrid = function(softwareUpdates) { + softwareUpdatesGrid = new wok.widget.Grid({ + container: 'software-updates-grid-container', + id: softwareUpdatesGridID, + title: i18n['GGBUPD6001M'], + rowSelection: 'disabled', + toolbarButtons: [{ + id: softwareUpdatesGridID + '-update-button', + label: i18n['GGBUPD6006M'], + disabled: true, + onClick: function(event) { + var updateButton = $(this); + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); + + gingerbase.updateSoftware(function(result) { + reloadProgressArea(result); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + wok.message.error(message || i18n['GGBUPD6009M']); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + }, reloadProgressArea); + } + }], + frozenFields: [], + fields: [{ + name: 'package_name', + label: i18n['GGBUPD6002M'], + 'class': 'software-update-name' + }, { + name: 'version', + label: i18n['GGBUPD6003M'], + 'class': 'software-update-version' + }, { + name: 'arch', + label: i18n['GGBUPD6004M'], + 'class': 'software-update-arch' + }, { + name: 'repository', + label: i18n['GGBUPD6005M'], + 'class': 'software-update-repos' + }], + data: listSoftwareUpdates + }); + }; + + var startSoftwareUpdateProgress = function() { + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + + gingerbase.softwareUpdateProgress(function(result) { + reloadProgressArea(result); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + wok.message.warn(i18n['GGBUPD6010M']); + }, function(error) { + wok.message.error(i18n['GGBUPD6011M']); + }, reloadProgressArea); + }; + + var listSoftwareUpdates = function(gridCallback) { + gingerbase.listSoftwareUpdates(function(softwareUpdates) { + if ($.isFunction(gridCallback)) { + gridCallback(softwareUpdates); + } else { + if (softwareUpdatesGrid) { + softwareUpdatesGrid.setData(softwareUpdates); + } else { + initSoftwareUpdatesGrid(softwareUpdates); + } + } + + var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); + $(updateButton).prop('disabled', softwareUpdates.length === 0); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + // cannot get the list of packages because there is another + // package manager instance running, so follow that instance updates + if (message.indexOf("GGBPKGUPD0005E") !== -1) { + startSoftwareUpdateProgress(); + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + return; + } + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + softwareUpdatesGrid && + softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + }; + + var initPage = function() { + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); + $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); + wok.topic('gingerbase/repositoryAdded') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .subscribe(listRepositories); + } + + if (gingerbase.capabilities['update_tool']) { + $('#software-update-section').removeClass('hidden'); + initSoftwareUpdatesGrid(); + wok.topic('gingerbase/softwareUpdated') + .subscribe(listSoftwareUpdates); + } + + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-update-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + repositoriesGrid && repositoriesGrid.destroy(); + wok.topic('gingerbase/repositoryAdded') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .unsubscribe(listRepositories); + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + softwareUpdatesGrid && softwareUpdatesGrid.destroy(); + wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); + + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js deleted file mode 100644 index 4a237df..0000000 --- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Licensed 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. - */ -gingerbase.host = {}; - -gingerbase.host_main = function() { - "use strict"; - var repositoriesGrid = null; - var initRepositoriesGrid = function(repo_type) { - var gridFields = []; - if (repo_type === "yum") { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'config[display_repo_name]', - label: i18n['GGBREPO6005M'], - 'class': 'repository-name', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }]; - } else if (repo_type === "deb") { - gridFields = [{ - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl deb', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled deb', - type: 'status' - }, { - name: 'config[dist]', - label: "dist", - 'class': 'repository-gpgcheck deb' - }, { - name: 'config[comps]', - label: "comps", - 'class': 'repository-gpgcheck deb' - }]; - } else { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }, { - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl', - type: 'description' - }]; - } - repositoriesGrid = new wok.widget.List({ - container: 'repositories-section', - id: 'repositories-grid', - title: i18n['GGBREPO6003M'], - toolbarButtons: [{ - id: 'repositories-grid-add-button', - label: i18n['GGBREPO6012M'], - class: 'fa fa-plus-circle', - onClick: function(event) { - wok.window.open({ - url: 'plugins/gingerbase/repository-add.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-enable-button', - label: i18n['GGBREPO6016M'], - class: 'fa fa-play-circle-o', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var name = repository['repo_id']; - var enable = !repository['enabled']; - $(this).prop('disabled', true); - gingerbase.enableRepository(name, enable, function() { - wok.topic('gingerbase/repositoryUpdated').publish(); - }); - } - }, { - id: 'repositories-grid-edit-button', - label: i18n['GGBREPO6013M'], - class: 'fa fa-pencil', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - gingerbase.selectedRepository = repository['repo_id']; - wok.window.open({ - url: 'plugins/gingerbase/repository-edit.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-remove-button', - label: i18n['GGBREPO6014M'], - class: 'fa fa-minus-circle', - critical: true, - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - - var settings = { - title: i18n['GGBREPO6001M'], - content: i18n['GGBREPO6002M'], - confirm: i18n['GGBAPI6004M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteRepository( - repository['repo_id'], - function(result) { - wok.topic('gingerbase/repositoryDeleted').publish(result); - }, - function(error) {} - ); - }); - } - }], - onRowSelected: function(row) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var selectedRow = $('tr',repositoriesGrid.bodyContainer); - $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); - $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); - var enabled = repository['enabled']; - var actionHtml,actionText,actionIcon =''; - if(enabled){ - actionText= i18n['GGBREPO6017M']; - actionIcon = 'fa-pause'; - }else{ - actionText= i18n['GGBREPO6016M']; - actionIcon = 'fa-play-circle-o'; - } - actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); - $('#repositories-grid-enable-button',selectedRow) - .html(actionHtml) - .prop('disabled', false); - }, - frozenFields: [], - fields: gridFields, - data: listRepositories - }); - }; - - var listRepositories = function(gridCallback) { - gingerbase.listRepositories(function(repositories) { - if ($.isFunction(gridCallback)) { - gridCallback(repositories); - } else { - if (repositoriesGrid) { - repositoriesGrid.setData(repositories); - } else { - initRepositoriesGrid(); - repositoriesGrid.setData(repositories); - } - } - }, - function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - repositoriesGrid && - repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - - $('#repositories-grid-remove-button').prop('disabled', true); - $('#repositories-grid-edit-button').prop('disabled', true); - $('#repositories-grid-enable-button').prop('disabled', true); - }; - - var softwareUpdatesGridID = 'software-updates-grid'; - var softwareUpdatesGrid = null; - var progressAreaID = 'software-updates-progress-textarea'; - var reloadProgressArea = function(result) { - var progressArea = $('#' + progressAreaID)[0]; - $(progressArea).text(result['message']); - var scrollTop = $(progressArea).prop('scrollHeight'); - $(progressArea).prop('scrollTop', scrollTop); - }; - - var initSoftwareUpdatesGrid = function(softwareUpdates) { - softwareUpdatesGrid = new wok.widget.Grid({ - container: 'software-updates-grid-container', - id: softwareUpdatesGridID, - title: i18n['GGBUPD6001M'], - rowSelection: 'disabled', - toolbarButtons: [{ - id: softwareUpdatesGridID + '-update-button', - label: i18n['GGBUPD6006M'], - disabled: true, - onClick: function(event) { - var updateButton = $(this); - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); - - gingerbase.updateSoftware(function(result) { - reloadProgressArea(result); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - wok.message.error(message || i18n['GGBUPD6009M']); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - }, reloadProgressArea); - } - }], - frozenFields: [], - fields: [{ - name: 'package_name', - label: i18n['GGBUPD6002M'], - 'class': 'software-update-name' - }, { - name: 'version', - label: i18n['GGBUPD6003M'], - 'class': 'software-update-version' - }, { - name: 'arch', - label: i18n['GGBUPD6004M'], - 'class': 'software-update-arch' - }, { - name: 'repository', - label: i18n['GGBUPD6005M'], - 'class': 'software-update-repos' - }], - data: listSoftwareUpdates - }); - }; - - var startSoftwareUpdateProgress = function() { - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - - gingerbase.softwareUpdateProgress(function(result) { - reloadProgressArea(result); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - wok.message.warn(i18n['GGBUPD6010M']); - }, function(error) { - wok.message.error(i18n['GGBUPD6011M']); - }, reloadProgressArea); - }; - - var listSoftwareUpdates = function(gridCallback) { - gingerbase.listSoftwareUpdates(function(softwareUpdates) { - if ($.isFunction(gridCallback)) { - gridCallback(softwareUpdates); - } else { - if (softwareUpdatesGrid) { - softwareUpdatesGrid.setData(softwareUpdates); - } else { - initSoftwareUpdatesGrid(softwareUpdates); - } - } - - var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); - $(updateButton).prop('disabled', softwareUpdates.length === 0); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - // cannot get the list of packages because there is another - // package manager instance running, so follow that instance updates - if (message.indexOf("GGBPKGUPD0005E") !== -1) { - startSoftwareUpdateProgress(); - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - return; - } - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - softwareUpdatesGrid && - softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - }; - - var reportGridID = 'available-reports-grid'; - var reportGrid = null; - var enableReportButtons = function(toEnable) { - var buttonID = '#{grid}-{btn}-button'; - $.each(['rename', 'remove', 'download'], function(i, n) { - $(wok.substitute(buttonID, { - grid: reportGridID, - btn: n - })).prop('disabled', !toEnable); - }); - }; - var initReportGrid = function(reports) { - reportGrid = new wok.widget.List({ - container: 'debug-report-section', - id: reportGridID, - title: i18n['GGBDR6002M'], - toolbarButtons: [{ - id: reportGridID + '-generate-button', - class: 'fa fa-plus-circle', - label: i18n['GGBDR6006M'], - onClick: function(event) { - wok.window.open('plugins/gingerbase/report-add.html'); - } - }, { - id: reportGridID + '-rename-button', - class: 'fa fa-pencil', - label: i18n['GGBDR6008M'], - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.selectedReport = report['name']; - wok.window.open('plugins/gingerbase/report-rename.html'); - } - }, { - id: reportGridID + '-download-button', - label: i18n['GGBDR6010M'], - class: 'fa fa-download', - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.downloadReport({ - file: report['uri'] - }); - } - }, { - id: reportGridID + '-remove-button', - class: 'fa fa-minus-circle', - label: i18n['GGBDR6009M'], - critical: true, - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - var settings = { - title: i18n['GGBAPI6004M'], - content: i18n['GGBDR6001M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteReport({ - name: report['name'] - }, function(result) { - listDebugReports(); - }, function(error) { - wok.message.error(error.responseJSON.reason); - }); - }); - } - }], - onRowSelected: function(row) { - var report = reportGrid.getSelected(); - // Only enable report buttons if the selected line is not a - // pending report - if (report['time'] === i18n['GGBDR6007M']) { - var gridElement = $('#' + reportGridID); - var row = $('tr:contains(' + report['name'] + ')', gridElement); - enableReportButtons(false); - row.attr('class', ''); - } else { - enableReportButtons(true); - } - }, - frozenFields: [], - fields: [{ - name: 'name', - label: i18n['GGBDR6003M'], - 'class': 'debug-report-name', - type: 'name' - }, { - name: 'time', - label: i18n['GGBDR6005M'], - 'class': 'debug-report-time', - type: 'description' - }], - data: reports - }); - }; - - var getPendingReports = function() { - var reports = []; - var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); - - gingerbase.getTasksByFilter(filter, function(tasks) { - for (var i = 0; i < tasks.length; i++) { - var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; - reports.push({ - 'name': reportName, - 'time': i18n['GGBDR6007M'] - }); - - if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { - continue; - } - - gingerbase.trackTask(tasks[i].id, function(result) { - wok.topic('gingerbase/debugReportAdded').publish(); - }, function(result) { - // Error message from Async Task status - if (result['message']) { - var errText = result['message']; - } - // Error message from standard gingerbase exception - else { - var errText = result['responseJSON']['reason']; - } - result && wok.message.error(errText); - wok.topic('gingerbase/debugReportAdded').publish(); - }, null); - } - }, null, true); - - return reports; - }; - - var listDebugReports = function() { - gingerbase.listReports(function(reports) { - var pendingReports = getPendingReports(); - var allReports = pendingReports.concat(reports); - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - - - // Row selection will be cleared so disable buttons here - enableReportButtons(false); - - if (reportGrid) { - reportGrid.setData(allReports); - } else { - initReportGrid(allReports); - } - - if (!allReports.length) { - $('#available-reports-grid-btn-group').removeClass('hidden'); - } else { - $('#available-reports-grid-btn-group').addClass('hidden'); - } - - // Set id-debug-img to pending reports - // It will display a loading icon - var gridElement = $('#' + reportGridID); - // "Generating..." - $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { - console.log(row); - $(row).parent().addClass('generating'); - $(row).parent().find('.dropdown-toggle').addClass('disabled'); - //$(row).attr('id', 'id-debug-img'); - }); - }, function(error) { - if (error['status'] === 403) { - $('#debug-report-section').addClass('hidden'); - // Check Repositories and resize column - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#repositories-section').removeClass('col-md-4'); - $('#repositories-section').addClass('col-md-8'); - } else { - $('#content-sys-info').removeClass('col-md-4'); - $('#content-sys-info').addClass('col-md-12'); - } - return; - } - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - }); - }; - - var shutdownButtonID = '#host-button-shutdown'; - var restartButtonID = '#host-button-restart'; - var shutdownHost = function(params) { - var settings = { - content: i18n['GGBHOST6008M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - $(shutdownButtonID).prop('disabled', true); - $(restartButtonID).prop('disabled', true); - // Check if there is any VM is running. - // Based on the success will shutdown/reboot - gingerbase.shutdown(params, function(success) { - wok.message.success(i18n['GGBHOST6009M']) - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - return; - }, function(error) { - // Looks like VMs are running. - wok.message.error.code('GGBHOST6001E'); - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - }); - }, function() { - }); - }; - - var initPage = function() { - - $('#host-button-shutdown').on('click', function(event) { - event.preventDefault(); - shutdownHost(null); - }); - - $('#host-button-restart').on('click', function(event) { - event.preventDefault(); - shutdownHost({ - reboot: true - }); - }); - - var setupUI = function() { - if (gingerbase.capabilities === undefined) { - setTimeout(setupUI, 2000); - return; - } - - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); - $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); - wok.topic('gingerbase/repositoryAdded') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .subscribe(listRepositories); - } - - if (gingerbase.capabilities['update_tool']) { - $('#software-update-section').removeClass('hidden'); - initSoftwareUpdatesGrid(); - wok.topic('gingerbase/softwareUpdated') - .subscribe(listSoftwareUpdates); - } - - if (gingerbase.capabilities['system_report_tool']) { - listDebugReports(); - wok.topic('gingerbase/debugReportAdded') - .subscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed') - .subscribe(listDebugReports); - } - }; - setupUI(); - }; - - gingerbase.getHost(function(data) { - var htmlTmpl = $('#host-tmpl').html(); - data['logo'] = data['logo'] || ''; - data['memory'] = wok.formatMeasurement(data['memory'], { - fixed: 2 - }); - var templated = wok.substitute(htmlTmpl, data); - $('#host-content-container').html(templated); - - initPage(); - initTracker(); - }); - - var StatsMgr = function() { - var statsArray = { - cpu: { - u: { - type: 'percent', - legend: i18n['GGBHOST6002M'], - points: [] - } - }, - memory: { - u: { - type: 'value', - base: 2, - fixed: 2, - legend: i18n['GGBHOST6003M'], - points: [] - } - }, - diskIO: { - w: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6005M'], - 'class': 'disk-write', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6004M'], - points: [] - } - }, - networkIO: { - s: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6007M'], - 'class': 'network-sent', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6006M'], - points: [] - } - } - }; - var SIZE = 20; - var cursor = SIZE; - - var add = function(stats) { - for (var key in stats) { - var item = stats[key]; - for (var metrics in item) { - var value = item[metrics]['v']; - var max = item[metrics]['max']; - var unifiedMetrics = statsArray[key][metrics]; - var ps = unifiedMetrics['points']; - if (!Array.isArray(value)) { - ps.push(value); - if (ps.length > SIZE + 1) { - ps.shift(); - } - } else { - ps = ps.concat(value); - ps.splice(0, ps.length - SIZE - 1); - unifiedMetrics['points'] = ps; - } - if (max !== undefined) { - unifiedMetrics['max'] = max; - } else { - if (unifiedMetrics['type'] !== 'value') { - continue; - } - max = -Infinity; - $.each(ps, function(i, value) { - if (value > max) { - max = value; - } - }); - if (max === 0) { - ++max; - } - max *= 1.1; - unifiedMetrics['max'] = max; - } - } - } - cursor++; - }; - - var get = function(which) { - var stats = statsArray[which]; - var lines = []; - for (var k in stats) { - var obj = stats[k]; - var line = { - type: obj['type'], - base: obj['base'], - unit: obj['unit'], - fixed: obj['fixed'], - legend: obj['legend'] - }; - if (obj['max']) { - line['max'] = obj['max']; - } - if (obj['class']) { - line['class'] = obj['class']; - } - var ps = obj['points']; - var numStats = ps.length; - var unifiedPoints = []; - $.each(ps, function(i, value) { - unifiedPoints.push({ - x: cursor - numStats + i, - y: value - }); - }); - line['points'] = unifiedPoints; - lines.push(line); - } - return lines; - }; - - return { - add: add, - get: get - }; - }; - - var Tracker = function(charts) { - var charts = charts; - var timer = null; - var statsPool = new StatsMgr(); - var setCharts = function(newCharts) { - charts = newCharts; - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - }; - - var self = this; - - var UnifyStats = function(stats) { - var result = { - cpu: { - u: { - v: stats['cpu_utilization'] - } - }, - memory: { - u: {} - }, - diskIO: { - w: { - v: stats['disk_write_rate'] - }, - r: { - v: stats['disk_read_rate'] - } - }, - networkIO: { - s: { - v: stats['net_sent_rate'] - }, - r: { - v: stats['net_recv_rate'] - } - } - }; - if (Array.isArray(stats['memory'])) { - result.memory.u['v'] = []; - result.memory.u['max'] = -Infinity; - for (var i = 0; i < stats['memory'].length; i++) { - result.memory.u['v'].push(stats['memory'][i]['avail']); - result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); - } - } else { - result.memory.u['v'] = stats['memory']['avail'], - result.memory.u['max'] = stats['memory']['total'] - } - return (result); - }; - - - var statsCallback = function(stats) { - var unifiedStats = UnifyStats(stats); - statsPool.add(unifiedStats); - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - timer = setTimeout(function() { - continueTrack(); - }, 1000); - }; - - var track = function() { - gingerbase.getHostStatsHistory(statsCallback, - function() { - continueTrack(); - }); - }; - - var continueTrack = function() { - gingerbase.getHostStats(statsCallback, - function() { - continueTrack(); - }); - }; - - var destroy = function() { - timer && clearTimeout(timer); - timer = null; - }; - - return { - setCharts: setCharts, - start: track, - stop: destroy - }; - }; - - var initTracker = function() { - // TODO: Extend tabs with onUnload event to unregister timers. - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - var trackedCharts = { - cpu: new wok.widget.LineChart({ - id: 'chart-cpu', - node: 'container-chart-cpu', - type: 'percent' - }), - memory: new wok.widget.LineChart({ - id: 'chart-memory', - node: 'container-chart-memory', - type: 'value' - }), - diskIO: new wok.widget.LineChart({ - id: 'chart-disk-io', - node: 'container-chart-disk-io', - type: 'value' - }), - networkIO: new wok.widget.LineChart({ - id: 'chart-network-io', - node: 'container-chart-network-io', - type: 'value' - }) - }; - - if (gingerbase.hostTimer) { - gingerbase.hostTimer.setCharts(trackedCharts); - } else { - gingerbase.hostTimer = new Tracker(trackedCharts); - gingerbase.hostTimer.start(); - } - }; - - $('#host-root-container').on('remove', function() { - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - repositoriesGrid && repositoriesGrid.destroy(); - wok.topic('gingerbase/repositoryAdded') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .unsubscribe(listRepositories); - - softwareUpdatesGrid && softwareUpdatesGrid.destroy(); - wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); - - reportGrid && reportGrid.destroy(); - wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); - }); -}; diff --git a/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl new file mode 100644 index 0000000..06b8088 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl @@ -0,0 +1,135 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + <ul class="nav navbar-nav navbar-right tools"> + <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> + <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> + <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> + </ul> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-dashboard-tmpl" type="gingerbase/template"> +<div class="host-dashboard"> + <div class="container"> + <div id="alert-container"></div> + <div id="content-sys-statistics" class="row"> + <div class="col-md-3"> + <div id="cpu-dashboard"> + <h3 class="section-label">$_("CPU")</h3> + <div class="section-value"> + <div id="container-chart-cpu" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="memory-dashboard"> + <h3 class="section-label">$_("Memory")</h3> + <div class="section-value"> + <div id="container-chart-memory" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="disk-dashboard"> + <h3 class="section-label">$_("Disk I/O")</h3> + <div class="section-value"> + <div id="container-chart-disk-io" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="network-dashboard"> + <h3 class="section-label">$_("Network I/O")</h3> + <div class="section-value"> + <div id="container-chart-network-io" class="inline-block"></div> + </div> + </div> + </div> + </div> + </div> +</div> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="content-sys-info" class="panel panel-default col-md-6"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Basic Information")</h3> + </div> + <div class="panel-body"> + <dl class="basic-information-list"> + <dt>{os_distro}</dt> + <dd>$_("OS Distro")</dd> + <dt>{os_version}</dt> + <dd>$_("OS Version")</dd> + <dt>{os_codename}</dt> + <dd>$_("OS Code Name")</dd> + <dt>{cpu_model}</dt> + <dd>$_("Processor")</dd> + <dt>{cpus}</dt> + <dd>$_("CPU(s)")</dd> + <dt>{memory}</dt> + <dd>$_("Memory")</dd> + </dl> + </div> + </div> + <div id="debug-report-section" class="col-md-6 hidden"></div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_dashboard(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl new file mode 100644 index 0000000..20790ed --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl @@ -0,0 +1,90 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-update-tmpl" type="gingerbase/template"> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="repositories-section" class="col-md-12 hidden"></div> + </div> + <div class="row"> + <div id="software-update-section" class="panel panel-default col-md-12 hidden"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Software Updates")</h3> + </div> + <div id="content-software-update" class="panel panel-default"> + <div id="software-updates-grid-container"></div> + <div id="software-updates-progress-container" class="hidden"> + <div class="software-updates-main"> + <h3> + <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> + <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> + </a> + </h3> + <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> + </div> + </div> + </div> + </div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_update(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl deleted file mode 100644 index d17f184..0000000 --- a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl +++ /dev/null @@ -1,156 +0,0 @@ -#* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Code derived from Project Kimchi - * - * Licensed 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. - *# - -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<html> -<head> -<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> -<script src="plugins/gingerbase/js/gingerbase.min.js"></script> -</head> -<body> -<div id="host-root-container"> -<nav class="navbar navbar-default toolbar"> - <div class="container"> - <!-- Brand and toggle get grouped for better mobile display --> - <div class="navbar-header"> - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - - <!-- Collect the nav links, forms, and other content for toggling --> - <div class="collapse navbar-collapse" id="toolbar"> - <ul class="nav navbar-nav navbar-right tools"> - <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> - <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> - <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> - </ul> - </div> - </div> -</nav> - <div id="host-content-container" class="empty-when-logged-off"></div> -</div> - -<script id="host-tmpl" type="gingerbase/template"> -<div class="host-dashboard"> - <div class="container"> - <div id="alert-container"></div> - <div id="content-sys-statistics" class="row"> - <div class="col-md-3"> - <div id="cpu-dashboard"> - <h3 class="section-label">$_("CPU")</h3> - <div class="section-value"> - <div id="container-chart-cpu" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="memory-dashboard"> - <h3 class="section-label">$_("Memory")</h3> - <div class="section-value"> - <div id="container-chart-memory" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="disk-dashboard"> - <h3 class="section-label">$_("Disk I/O")</h3> - <div class="section-value"> - <div id="container-chart-disk-io" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="network-dashboard"> - <h3 class="section-label">$_("Network I/O")</h3> - <div class="section-value"> - <div id="container-chart-network-io" class="inline-block"></div> - </div> - </div> - </div> - </div> - </div> -</div> -<div class="host-panel"> - <div class="container"> - <div id="host-info-container" class="row"> - <div id="content-sys-info" class="panel panel-default col-md-12"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Basic Information")</h3> - </div> - <div class="panel-body"> - <dl class="basic-information-list"> - <dt>{os_distro}</dt> - <dd>$_("OS Distro")</dd> - <dt>{os_version}</dt> - <dd>$_("OS Version")</dd> - <dt>{os_codename}</dt> - <dd>$_("OS Code Name")</dd> - <dt>{cpu_model}</dt> - <dd>$_("Processor")</dd> - <dt>{cpus}</dt> - <dd>$_("CPU(s)")</dd> - <dt>{memory}</dt> - <dd>$_("Memory")</dd> - </dl> - </div> - </div> - <div id="repositories-section" class="col-md-8 hidden"></div> - <div id="debug-report-section" class="col-md-8 hidden"></div> - </div> - <div class="row"> - <div id="software-update-section" class="panel panel-default col-md-12 hidden"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Software Updates")</h3> - </div> - <div id="content-software-update" class="panel panel-default"> - <div id="software-updates-grid-container"></div> - <div id="software-updates-progress-container" class="hidden"> - <div class="software-updates-main"> - <h3> - <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> - <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> - </a> - </h3> - <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> - </div> - </div> - </div> - </div> - </div> - </div> -</div> -</script> -<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> -</div> -<script type="text/javascript"> - gingerbase.host_main(); -</script> -</body> -</html>

I removed the commented blocks I commented below and everything continued to work fine. So I will remove them and apply all the patches. On 26/11/2015 16:24, Aline Manera wrote:
On 26/11/2015 10:53, chandra@linux.vnet.ibm.com wrote:
From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com>
Splitting host tab functionality into two tabs 1. Dashboard a. restart, shutdown buttons b. statistics c. debug reports 2. Updates a. Repositories b. Software updates --- src/wok/plugins/gingerbase/ui/config/tab-ext.xml | 10 +- .../ui/js/src/gingerbase.host-dashboard.js | 593 +++++++++++++ .../gingerbase/ui/js/src/gingerbase.host-update.js | 405 +++++++++ .../gingerbase/ui/js/src/gingerbase.host.js | 928 --------------------- .../gingerbase/ui/pages/host-dashboard.html.tmpl | 135 +++ .../gingerbase/ui/pages/host-update.html.tmpl | 90 ++ src/wok/plugins/gingerbase/ui/pages/host.html.tmpl | 156 ---- 7 files changed, 1231 insertions(+), 1086 deletions(-) create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js create mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js delete mode 100644 src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl create mode 100644 src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl delete mode 100644 src/wok/plugins/gingerbase/ui/pages/host.html.tmpl
diff --git a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml index 3d3f51e..f6f16d4 100644 --- a/src/wok/plugins/gingerbase/ui/config/tab-ext.xml +++ b/src/wok/plugins/gingerbase/ui/config/tab-ext.xml @@ -4,7 +4,13 @@ <tab> <access role="admin" mode="admin"/> <access role="user" mode="none"/> - <title>Host</title> - <path>plugins/gingerbase/host.html</path> + <title>Dashboard</title> + <path>plugins/gingerbase/host-dashboard.html</path> + </tab> + <tab> + <access role="admin" mode="admin"/> + <access role="user" mode="none"/> + <title>Updates</title> + <path>plugins/gingerbase/host-update.html</path> </tab> </tabs-ext> diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js new file mode 100644 index 0000000..047ba5b --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js @@ -0,0 +1,593 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_dashboard = function() { + "use strict"; + var reportGridID = 'available-reports-grid'; + var reportGrid = null; + var enableReportButtons = function(toEnable) { + var buttonID = '#{grid}-{btn}-button'; + $.each(['rename', 'remove', 'download'], function(i, n) { + $(wok.substitute(buttonID, { + grid: reportGridID, + btn: n + })).prop('disabled', !toEnable); + }); + }; + var initReportGrid = function(reports) { + reportGrid = new wok.widget.List({ + container: 'debug-report-section', + id: reportGridID, + title: i18n['GGBDR6002M'], + toolbarButtons: [{ + id: reportGridID + '-generate-button', + class: 'fa fa-plus-circle', + label: i18n['GGBDR6006M'], + onClick: function(event) { + wok.window.open('plugins/gingerbase/report-add.html'); + } + }, { + id: reportGridID + '-rename-button', + class: 'fa fa-pencil', + label: i18n['GGBDR6008M'], + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.selectedReport = report['name']; + wok.window.open('plugins/gingerbase/report-rename.html'); + } + }, { + id: reportGridID + '-download-button', + label: i18n['GGBDR6010M'], + class: 'fa fa-download', + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + gingerbase.downloadReport({ + file: report['uri'] + }); + } + }, { + id: reportGridID + '-remove-button', + class: 'fa fa-minus-circle', + label: i18n['GGBDR6009M'], + critical: true, + disabled: true, + onClick: function(event) { + var report = reportGrid.getSelected(); + if (!report) { + return; + } + + var settings = { + title: i18n['GGBAPI6004M'], + content: i18n['GGBDR6001M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteReport({ + name: report['name'] + }, function(result) { + listDebugReports(); + }, function(error) { + wok.message.error(error.responseJSON.reason); + }); + }); + } + }], + onRowSelected: function(row) { + var report = reportGrid.getSelected(); + // Only enable report buttons if the selected line is not a + // pending report + if (report['time'] === i18n['GGBDR6007M']) { + var gridElement = $('#' + reportGridID); + var row = $('tr:contains(' + report['name'] + ')', gridElement); + enableReportButtons(false); + row.attr('class', ''); + } else { + enableReportButtons(true); + } + }, + frozenFields: [], + fields: [{ + name: 'name', + label: i18n['GGBDR6003M'], + 'class': 'debug-report-name', + type: 'name' + }, { + name: 'time', + label: i18n['GGBDR6005M'], + 'class': 'debug-report-time', + type: 'description' + }], + data: reports + }); + }; + + var getPendingReports = function() { + var reports = []; + var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); + + gingerbase.getTasksByFilter(filter, function(tasks) { + for (var i = 0; i < tasks.length; i++) { + var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; + reports.push({ + 'name': reportName, + 'time': i18n['GGBDR6007M'] + }); + + if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + gingerbase.trackTask(tasks[i].id, function(result) { + wok.topic('gingerbase/debugReportAdded').publish(); + }, function(result) { + // Error message from Async Task status + if (result['message']) { + var errText = result['message']; + } + // Error message from standard gingerbase exception + else { + var errText = result['responseJSON']['reason']; + } + result && wok.message.error(errText); + wok.topic('gingerbase/debugReportAdded').publish(); + }, null); + } + }, null, true); + + return reports; + }; + + var listDebugReports = function() { + gingerbase.listReports(function(reports) { + var pendingReports = getPendingReports(); + var allReports = pendingReports.concat(reports); + $('#debug-report-section').removeClass('hidden');
+/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/ +
Can the above block be removed as it is commeted?
+ + // Row selection will be cleared so disable buttons here + enableReportButtons(false); + + if (reportGrid) { + reportGrid.setData(allReports); + } else { + initReportGrid(allReports); + } + + if (!allReports.length) { + $('#available-reports-grid-btn-group').removeClass('hidden'); + } else { + $('#available-reports-grid-btn-group').addClass('hidden'); + } + + // Set id-debug-img to pending reports + // It will display a loading icon + var gridElement = $('#' + reportGridID); + // "Generating..." + $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { + console.log(row); + $(row).parent().addClass('generating'); + $(row).parent().find('.dropdown-toggle').addClass('disabled'); + //$(row).attr('id', 'id-debug-img'); + }); + }, function(error) { + if (error['status'] === 403) { + $('#debug-report-section').addClass('hidden');
+/* + // Check Repositories and resize column + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#repositories-section').removeClass('col-md-4'); + $('#repositories-section').addClass('col-md-8'); + } else { + $('#content-sys-info').removeClass('col-md-4'); + $('#content-sys-info').addClass('col-md-12'); + } +*/
Same here.
+ return; + } + $('#debug-report-section').removeClass('hidden');
+/* + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + $('#debug-report-section, #repositories-section').removeClass('col-md-8'); + $('#debug-report-section, #repositories-section').addClass('col-md-4'); + } else { + $('#content-sys-info').removeClass('col-md-12'); + $('#content-sys-info').addClass('col-md-4'); + } +*/
And here.
+ }); + }; + + var shutdownButtonID = '#host-button-shutdown'; + var restartButtonID = '#host-button-restart'; + var shutdownHost = function(params) { + var settings = { + content: i18n['GGBHOST6008M'], + confirm: i18n['GGBAPI6002M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + $(shutdownButtonID).prop('disabled', true); + $(restartButtonID).prop('disabled', true); + // Check if there is any VM is running. + // Based on the success will shutdown/reboot + gingerbase.shutdown(params, function(success) { + wok.message.success(i18n['GGBHOST6009M']) + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + return; + }, function(error) { + // Looks like VMs are running. + wok.message.error.code('GGBHOST6001E'); + $(shutdownButtonID).prop('disabled', false); + $(restartButtonID).prop('disabled', false); + }); + }, function() { + }); + }; + + var initPage = function() { + + $('#host-button-shutdown').on('click', function(event) { + event.preventDefault(); + shutdownHost(null); + }); + + $('#host-button-restart').on('click', function(event) { + event.preventDefault(); + shutdownHost({ + reboot: true + }); + }); + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if (gingerbase.capabilities['system_report_tool']) { + listDebugReports(); + wok.topic('gingerbase/debugReportAdded') + .subscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed') + .subscribe(listDebugReports); + } + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-dashboard-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + initTracker(); + }); + + var StatsMgr = function() { + var statsArray = { + cpu: { + u: { + type: 'percent', + legend: i18n['GGBHOST6002M'], + points: [] + } + }, + memory: { + u: { + type: 'value', + base: 2, + fixed: 2, + legend: i18n['GGBHOST6003M'], + points: [] + } + }, + diskIO: { + w: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6005M'], + 'class': 'disk-write', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6004M'], + points: [] + } + }, + networkIO: { + s: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6007M'], + 'class': 'network-sent', + points: [] + }, + r: { + type: 'value', + base: 2, + fixed: 2, + unit: 'B/s', + legend: i18n['GGBHOST6006M'], + points: [] + } + } + }; + var SIZE = 20; + var cursor = SIZE; + + var add = function(stats) { + for (var key in stats) { + var item = stats[key]; + for (var metrics in item) { + var value = item[metrics]['v']; + var max = item[metrics]['max']; + var unifiedMetrics = statsArray[key][metrics]; + var ps = unifiedMetrics['points']; + if (!Array.isArray(value)) { + ps.push(value); + if (ps.length > SIZE + 1) { + ps.shift(); + } + } else { + ps = ps.concat(value); + ps.splice(0, ps.length - SIZE - 1); + unifiedMetrics['points'] = ps; + } + if (max !== undefined) { + unifiedMetrics['max'] = max; + } else { + if (unifiedMetrics['type'] !== 'value') { + continue; + } + max = -Infinity; + $.each(ps, function(i, value) { + if (value > max) { + max = value; + } + }); + if (max === 0) { + ++max; + } + max *= 1.1; + unifiedMetrics['max'] = max; + } + } + } + cursor++; + }; + + var get = function(which) { + var stats = statsArray[which]; + var lines = []; + for (var k in stats) { + var obj = stats[k]; + var line = { + type: obj['type'], + base: obj['base'], + unit: obj['unit'], + fixed: obj['fixed'], + legend: obj['legend'] + }; + if (obj['max']) { + line['max'] = obj['max']; + } + if (obj['class']) { + line['class'] = obj['class']; + } + var ps = obj['points']; + var numStats = ps.length; + var unifiedPoints = []; + $.each(ps, function(i, value) { + unifiedPoints.push({ + x: cursor - numStats + i, + y: value + }); + }); + line['points'] = unifiedPoints; + lines.push(line); + } + return lines; + }; + + return { + add: add, + get: get + }; + }; + + var Tracker = function(charts) { + var charts = charts; + var timer = null; + var statsPool = new StatsMgr(); + var setCharts = function(newCharts) { + charts = newCharts; + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + }; + + var self = this; + + var UnifyStats = function(stats) { + var result = { + cpu: { + u: { + v: stats['cpu_utilization'] + } + }, + memory: { + u: {} + }, + diskIO: { + w: { + v: stats['disk_write_rate'] + }, + r: { + v: stats['disk_read_rate'] + } + }, + networkIO: { + s: { + v: stats['net_sent_rate'] + }, + r: { + v: stats['net_recv_rate'] + } + } + }; + if (Array.isArray(stats['memory'])) { + result.memory.u['v'] = []; + result.memory.u['max'] = -Infinity; + for (var i = 0; i < stats['memory'].length; i++) { + result.memory.u['v'].push(stats['memory'][i]['avail']); + result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); + } + } else { + result.memory.u['v'] = stats['memory']['avail'], + result.memory.u['max'] = stats['memory']['total'] + } + return (result); + }; + + + var statsCallback = function(stats) { + var unifiedStats = UnifyStats(stats); + statsPool.add(unifiedStats); + for (var key in charts) { + var chart = charts[key]; + chart.updateUI(statsPool.get(key)); + } + timer = setTimeout(function() { + continueTrack(); + }, 1000); + }; + + var track = function() { + gingerbase.getHostStatsHistory(statsCallback, + function() { + continueTrack(); + }); + }; + + var continueTrack = function() { + gingerbase.getHostStats(statsCallback, + function() { + continueTrack(); + }); + }; + + var destroy = function() { + timer && clearTimeout(timer); + timer = null; + }; + + return { + setCharts: setCharts, + start: track, + stop: destroy + }; + }; + + var initTracker = function() { + // TODO: Extend tabs with onUnload event to unregister timers. + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + var trackedCharts = { + cpu: new wok.widget.LineChart({ + id: 'chart-cpu', + node: 'container-chart-cpu', + type: 'percent' + }), + memory: new wok.widget.LineChart({ + id: 'chart-memory', + node: 'container-chart-memory', + type: 'value' + }), + diskIO: new wok.widget.LineChart({ + id: 'chart-disk-io', + node: 'container-chart-disk-io', + type: 'value' + }), + networkIO: new wok.widget.LineChart({ + id: 'chart-network-io', + node: 'container-chart-network-io', + type: 'value' + }) + }; + + if (gingerbase.hostTimer) { + gingerbase.hostTimer.setCharts(trackedCharts); + } else { + gingerbase.hostTimer = new Tracker(trackedCharts); + gingerbase.hostTimer.start(); + } + }; + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js new file mode 100644 index 0000000..ee89625 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-update.js @@ -0,0 +1,405 @@ +/* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Licensed 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. + */ +gingerbase.host = {}; + +gingerbase.host_update = function() { + "use strict"; + var repositoriesGrid = null; + var initRepositoriesGrid = function(repo_type) { + var gridFields = []; + if (repo_type === "yum") { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'config[display_repo_name]', + label: i18n['GGBREPO6005M'], + 'class': 'repository-name', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }]; + } else if (repo_type === "deb") { + gridFields = [{ + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl deb', + type: 'description' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled deb', + type: 'status' + }, { + name: 'config[dist]', + label: "dist", + 'class': 'repository-gpgcheck deb' + }, { + name: 'config[comps]', + label: "comps", + 'class': 'repository-gpgcheck deb' + }]; + } else { + gridFields = [{ + name: 'repo_id', + label: i18n['GGBREPO6004M'], + 'class': 'repository-id', + type: 'name' + }, { + name: 'enabled', + label: i18n['GGBREPO6009M'], + 'class': 'repository-enabled', + type: 'status' + }, { + name: 'baseurl', + label: i18n['GGBREPO6006M'], + makeTitle: true, + 'class': 'repository-baseurl', + type: 'description' + }]; + } + repositoriesGrid = new wok.widget.List({ + container: 'repositories-section', + id: 'repositories-grid', + title: i18n['GGBREPO6003M'], + toolbarButtons: [{ + id: 'repositories-grid-add-button', + label: i18n['GGBREPO6012M'], + class: 'fa fa-plus-circle', + onClick: function(event) { + wok.window.open({ + url: 'plugins/gingerbase/repository-add.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-enable-button', + label: i18n['GGBREPO6016M'], + class: 'fa fa-play-circle-o', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var name = repository['repo_id']; + var enable = !repository['enabled']; + $(this).prop('disabled', true); + gingerbase.enableRepository(name, enable, function() { + wok.topic('gingerbase/repositoryUpdated').publish(); + }); + } + }, { + id: 'repositories-grid-edit-button', + label: i18n['GGBREPO6013M'], + class: 'fa fa-pencil', + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + gingerbase.selectedRepository = repository['repo_id']; + wok.window.open({ + url: 'plugins/gingerbase/repository-edit.html', + class: repo_type + }); + } + }, { + id: 'repositories-grid-remove-button', + label: i18n['GGBREPO6014M'], + class: 'fa fa-minus-circle', + critical: true, + disabled: true, + onClick: function(event) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + + var settings = { + title: i18n['GGBREPO6001M'], + content: i18n['GGBREPO6002M'], + confirm: i18n['GGBAPI6004M'], + cancel: i18n['GGBAPI6003M'] + }; + + wok.confirm(settings, function() { + gingerbase.deleteRepository( + repository['repo_id'], + function(result) { + wok.topic('gingerbase/repositoryDeleted').publish(result); + }, + function(error) {} + ); + }); + } + }], + onRowSelected: function(row) { + var repository = repositoriesGrid.getSelected(); + if (!repository) { + return; + } + var selectedRow = $('tr',repositoriesGrid.bodyContainer); + $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); + $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); + var enabled = repository['enabled']; + var actionHtml,actionText,actionIcon =''; + if(enabled){ + actionText= i18n['GGBREPO6017M']; + actionIcon = 'fa-pause'; + }else{ + actionText= i18n['GGBREPO6016M']; + actionIcon = 'fa-play-circle-o'; + } + actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); + $('#repositories-grid-enable-button',selectedRow) + .html(actionHtml) + .prop('disabled', false); + }, + frozenFields: [], + fields: gridFields, + data: listRepositories + }); + }; + + var listRepositories = function(gridCallback) { + gingerbase.listRepositories(function(repositories) { + if ($.isFunction(gridCallback)) { + gridCallback(repositories); + } else { + if (repositoriesGrid) { + repositoriesGrid.setData(repositories); + } else { + initRepositoriesGrid(); + repositoriesGrid.setData(repositories); + } + } + }, + function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + repositoriesGrid && + repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + + $('#repositories-grid-remove-button').prop('disabled', true); + $('#repositories-grid-edit-button').prop('disabled', true); + $('#repositories-grid-enable-button').prop('disabled', true); + }; + + var softwareUpdatesGridID = 'software-updates-grid'; + var softwareUpdatesGrid = null; + var progressAreaID = 'software-updates-progress-textarea'; + var reloadProgressArea = function(result) { + var progressArea = $('#' + progressAreaID)[0]; + $(progressArea).text(result['message']); + var scrollTop = $(progressArea).prop('scrollHeight'); + $(progressArea).prop('scrollTop', scrollTop); + }; + + var initSoftwareUpdatesGrid = function(softwareUpdates) { + softwareUpdatesGrid = new wok.widget.Grid({ + container: 'software-updates-grid-container', + id: softwareUpdatesGridID, + title: i18n['GGBUPD6001M'], + rowSelection: 'disabled', + toolbarButtons: [{ + id: softwareUpdatesGridID + '-update-button', + label: i18n['GGBUPD6006M'], + disabled: true, + onClick: function(event) { + var updateButton = $(this); + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); + + gingerbase.updateSoftware(function(result) { + reloadProgressArea(result); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + wok.message.error(message || i18n['GGBUPD6009M']); + $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); + }, reloadProgressArea); + } + }], + frozenFields: [], + fields: [{ + name: 'package_name', + label: i18n['GGBUPD6002M'], + 'class': 'software-update-name' + }, { + name: 'version', + label: i18n['GGBUPD6003M'], + 'class': 'software-update-version' + }, { + name: 'arch', + label: i18n['GGBUPD6004M'], + 'class': 'software-update-arch' + }, { + name: 'repository', + label: i18n['GGBUPD6005M'], + 'class': 'software-update-repos' + }], + data: listSoftwareUpdates + }); + }; + + var startSoftwareUpdateProgress = function() { + var progressArea = $('#' + progressAreaID)[0]; + $('#software-updates-progress-container').removeClass('hidden'); + $(progressArea).text(''); + !wok.isElementInViewport(progressArea) && + progressArea.scrollIntoView(); + + gingerbase.softwareUpdateProgress(function(result) { + reloadProgressArea(result); + wok.topic('gingerbase/softwareUpdated').publish({ + result: result + }); + wok.message.warn(i18n['GGBUPD6010M']); + }, function(error) { + wok.message.error(i18n['GGBUPD6011M']); + }, reloadProgressArea); + }; + + var listSoftwareUpdates = function(gridCallback) { + gingerbase.listSoftwareUpdates(function(softwareUpdates) { + if ($.isFunction(gridCallback)) { + gridCallback(softwareUpdates); + } else { + if (softwareUpdatesGrid) { + softwareUpdatesGrid.setData(softwareUpdates); + } else { + initSoftwareUpdatesGrid(softwareUpdates); + } + } + + var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); + $(updateButton).prop('disabled', softwareUpdates.length === 0); + }, function(error) { + var message = error && error['responseJSON'] && error['responseJSON']['reason']; + + // cannot get the list of packages because there is another + // package manager instance running, so follow that instance updates + if (message.indexOf("GGBPKGUPD0005E") !== -1) { + startSoftwareUpdateProgress(); + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + return; + } + + if ($.isFunction(gridCallback)) { + gridCallback([]); + } + softwareUpdatesGrid && + softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); + }); + }; + + var initPage = function() { + + var setupUI = function() { + if (gingerbase.capabilities === undefined) { + setTimeout(setupUI, 2000); + return; + } + + if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { + initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); + $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); + $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); + wok.topic('gingerbase/repositoryAdded') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .subscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .subscribe(listRepositories); + } + + if (gingerbase.capabilities['update_tool']) { + $('#software-update-section').removeClass('hidden'); + initSoftwareUpdatesGrid(); + wok.topic('gingerbase/softwareUpdated') + .subscribe(listSoftwareUpdates); + } + + }; + setupUI(); + }; + + gingerbase.getHost(function(data) { + var htmlTmpl = $('#host-update-tmpl').html(); + data['logo'] = data['logo'] || ''; + data['memory'] = wok.formatMeasurement(data['memory'], { + fixed: 2 + }); + var templated = wok.substitute(htmlTmpl, data); + $('#host-content-container').html(templated); + + initPage(); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + repositoriesGrid && repositoriesGrid.destroy(); + wok.topic('gingerbase/repositoryAdded') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryUpdated') + .unsubscribe(listRepositories); + wok.topic('gingerbase/repositoryDeleted') + .unsubscribe(listRepositories); + + reportGrid && reportGrid.destroy(); + wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); + wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); + }); + + $('#host-root-container').on('remove', function() { + if (gingerbase.hostTimer) { + gingerbase.hostTimer.stop(); + delete gingerbase.hostTimer; + } + + softwareUpdatesGrid && softwareUpdatesGrid.destroy(); + wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); + + }); +}; diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js deleted file mode 100644 index 4a237df..0000000 --- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host.js +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Licensed 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. - */ -gingerbase.host = {}; - -gingerbase.host_main = function() { - "use strict"; - var repositoriesGrid = null; - var initRepositoriesGrid = function(repo_type) { - var gridFields = []; - if (repo_type === "yum") { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'config[display_repo_name]', - label: i18n['GGBREPO6005M'], - 'class': 'repository-name', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }]; - } else if (repo_type === "deb") { - gridFields = [{ - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl deb', - type: 'description' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled deb', - type: 'status' - }, { - name: 'config[dist]', - label: "dist", - 'class': 'repository-gpgcheck deb' - }, { - name: 'config[comps]', - label: "comps", - 'class': 'repository-gpgcheck deb' - }]; - } else { - gridFields = [{ - name: 'repo_id', - label: i18n['GGBREPO6004M'], - 'class': 'repository-id', - type: 'name' - }, { - name: 'enabled', - label: i18n['GGBREPO6009M'], - 'class': 'repository-enabled', - type: 'status' - }, { - name: 'baseurl', - label: i18n['GGBREPO6006M'], - makeTitle: true, - 'class': 'repository-baseurl', - type: 'description' - }]; - } - repositoriesGrid = new wok.widget.List({ - container: 'repositories-section', - id: 'repositories-grid', - title: i18n['GGBREPO6003M'], - toolbarButtons: [{ - id: 'repositories-grid-add-button', - label: i18n['GGBREPO6012M'], - class: 'fa fa-plus-circle', - onClick: function(event) { - wok.window.open({ - url: 'plugins/gingerbase/repository-add.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-enable-button', - label: i18n['GGBREPO6016M'], - class: 'fa fa-play-circle-o', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var name = repository['repo_id']; - var enable = !repository['enabled']; - $(this).prop('disabled', true); - gingerbase.enableRepository(name, enable, function() { - wok.topic('gingerbase/repositoryUpdated').publish(); - }); - } - }, { - id: 'repositories-grid-edit-button', - label: i18n['GGBREPO6013M'], - class: 'fa fa-pencil', - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - gingerbase.selectedRepository = repository['repo_id']; - wok.window.open({ - url: 'plugins/gingerbase/repository-edit.html', - class: repo_type - }); - } - }, { - id: 'repositories-grid-remove-button', - label: i18n['GGBREPO6014M'], - class: 'fa fa-minus-circle', - critical: true, - disabled: true, - onClick: function(event) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - - var settings = { - title: i18n['GGBREPO6001M'], - content: i18n['GGBREPO6002M'], - confirm: i18n['GGBAPI6004M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteRepository( - repository['repo_id'], - function(result) { - wok.topic('gingerbase/repositoryDeleted').publish(result); - }, - function(error) {} - ); - }); - } - }], - onRowSelected: function(row) { - var repository = repositoriesGrid.getSelected(); - if (!repository) { - return; - } - var selectedRow = $('tr',repositoriesGrid.bodyContainer); - $('#repositories-grid-remove-button',selectedRow).prop('disabled', false); - $('#repositories-grid-edit-button',selectedRow).prop('disabled', false); - var enabled = repository['enabled']; - var actionHtml,actionText,actionIcon =''; - if(enabled){ - actionText= i18n['GGBREPO6017M']; - actionIcon = 'fa-pause'; - }else{ - actionText= i18n['GGBREPO6016M']; - actionIcon = 'fa-play-circle-o'; - } - actionHtml = ['<i class="fa',' ',actionIcon,'"></i>','',actionText].join(''); - $('#repositories-grid-enable-button',selectedRow) - .html(actionHtml) - .prop('disabled', false); - }, - frozenFields: [], - fields: gridFields, - data: listRepositories - }); - }; - - var listRepositories = function(gridCallback) { - gingerbase.listRepositories(function(repositories) { - if ($.isFunction(gridCallback)) { - gridCallback(repositories); - } else { - if (repositoriesGrid) { - repositoriesGrid.setData(repositories); - } else { - initRepositoriesGrid(); - repositoriesGrid.setData(repositories); - } - } - }, - function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - repositoriesGrid && - repositoriesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - - $('#repositories-grid-remove-button').prop('disabled', true); - $('#repositories-grid-edit-button').prop('disabled', true); - $('#repositories-grid-enable-button').prop('disabled', true); - }; - - var softwareUpdatesGridID = 'software-updates-grid'; - var softwareUpdatesGrid = null; - var progressAreaID = 'software-updates-progress-textarea'; - var reloadProgressArea = function(result) { - var progressArea = $('#' + progressAreaID)[0]; - $(progressArea).text(result['message']); - var scrollTop = $(progressArea).prop('scrollHeight'); - $(progressArea).prop('scrollTop', scrollTop); - }; - - var initSoftwareUpdatesGrid = function(softwareUpdates) { - softwareUpdatesGrid = new wok.widget.Grid({ - container: 'software-updates-grid-container', - id: softwareUpdatesGridID, - title: i18n['GGBUPD6001M'], - rowSelection: 'disabled', - toolbarButtons: [{ - id: softwareUpdatesGridID + '-update-button', - label: i18n['GGBUPD6006M'], - disabled: true, - onClick: function(event) { - var updateButton = $(this); - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - $(updateButton).text(i18n['GGBUPD6007M']).prop('disabled', true); - - gingerbase.updateSoftware(function(result) { - reloadProgressArea(result); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - wok.message.error(message || i18n['GGBUPD6009M']); - $(updateButton).text(i18n['GGBUPD6006M']).prop('disabled', false); - }, reloadProgressArea); - } - }], - frozenFields: [], - fields: [{ - name: 'package_name', - label: i18n['GGBUPD6002M'], - 'class': 'software-update-name' - }, { - name: 'version', - label: i18n['GGBUPD6003M'], - 'class': 'software-update-version' - }, { - name: 'arch', - label: i18n['GGBUPD6004M'], - 'class': 'software-update-arch' - }, { - name: 'repository', - label: i18n['GGBUPD6005M'], - 'class': 'software-update-repos' - }], - data: listSoftwareUpdates - }); - }; - - var startSoftwareUpdateProgress = function() { - var progressArea = $('#' + progressAreaID)[0]; - $('#software-updates-progress-container').removeClass('hidden'); - $(progressArea).text(''); - !wok.isElementInViewport(progressArea) && - progressArea.scrollIntoView(); - - gingerbase.softwareUpdateProgress(function(result) { - reloadProgressArea(result); - wok.topic('gingerbase/softwareUpdated').publish({ - result: result - }); - wok.message.warn(i18n['GGBUPD6010M']); - }, function(error) { - wok.message.error(i18n['GGBUPD6011M']); - }, reloadProgressArea); - }; - - var listSoftwareUpdates = function(gridCallback) { - gingerbase.listSoftwareUpdates(function(softwareUpdates) { - if ($.isFunction(gridCallback)) { - gridCallback(softwareUpdates); - } else { - if (softwareUpdatesGrid) { - softwareUpdatesGrid.setData(softwareUpdates); - } else { - initSoftwareUpdatesGrid(softwareUpdates); - } - } - - var updateButton = $('#' + softwareUpdatesGridID + '-update-button'); - $(updateButton).prop('disabled', softwareUpdates.length === 0); - }, function(error) { - var message = error && error['responseJSON'] && error['responseJSON']['reason']; - - // cannot get the list of packages because there is another - // package manager instance running, so follow that instance updates - if (message.indexOf("GGBPKGUPD0005E") !== -1) { - startSoftwareUpdateProgress(); - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - return; - } - - if ($.isFunction(gridCallback)) { - gridCallback([]); - } - softwareUpdatesGrid && - softwareUpdatesGrid.showMessage(message || i18n['GGBUPD6008M']); - }); - }; - - var reportGridID = 'available-reports-grid'; - var reportGrid = null; - var enableReportButtons = function(toEnable) { - var buttonID = '#{grid}-{btn}-button'; - $.each(['rename', 'remove', 'download'], function(i, n) { - $(wok.substitute(buttonID, { - grid: reportGridID, - btn: n - })).prop('disabled', !toEnable); - }); - }; - var initReportGrid = function(reports) { - reportGrid = new wok.widget.List({ - container: 'debug-report-section', - id: reportGridID, - title: i18n['GGBDR6002M'], - toolbarButtons: [{ - id: reportGridID + '-generate-button', - class: 'fa fa-plus-circle', - label: i18n['GGBDR6006M'], - onClick: function(event) { - wok.window.open('plugins/gingerbase/report-add.html'); - } - }, { - id: reportGridID + '-rename-button', - class: 'fa fa-pencil', - label: i18n['GGBDR6008M'], - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.selectedReport = report['name']; - wok.window.open('plugins/gingerbase/report-rename.html'); - } - }, { - id: reportGridID + '-download-button', - label: i18n['GGBDR6010M'], - class: 'fa fa-download', - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - gingerbase.downloadReport({ - file: report['uri'] - }); - } - }, { - id: reportGridID + '-remove-button', - class: 'fa fa-minus-circle', - label: i18n['GGBDR6009M'], - critical: true, - disabled: true, - onClick: function(event) { - var report = reportGrid.getSelected(); - if (!report) { - return; - } - - var settings = { - title: i18n['GGBAPI6004M'], - content: i18n['GGBDR6001M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - gingerbase.deleteReport({ - name: report['name'] - }, function(result) { - listDebugReports(); - }, function(error) { - wok.message.error(error.responseJSON.reason); - }); - }); - } - }], - onRowSelected: function(row) { - var report = reportGrid.getSelected(); - // Only enable report buttons if the selected line is not a - // pending report - if (report['time'] === i18n['GGBDR6007M']) { - var gridElement = $('#' + reportGridID); - var row = $('tr:contains(' + report['name'] + ')', gridElement); - enableReportButtons(false); - row.attr('class', ''); - } else { - enableReportButtons(true); - } - }, - frozenFields: [], - fields: [{ - name: 'name', - label: i18n['GGBDR6003M'], - 'class': 'debug-report-name', - type: 'name' - }, { - name: 'time', - label: i18n['GGBDR6005M'], - 'class': 'debug-report-time', - type: 'description' - }], - data: reports - }); - }; - - var getPendingReports = function() { - var reports = []; - var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/gingerbase/debugreports/*'); - - gingerbase.getTasksByFilter(filter, function(tasks) { - for (var i = 0; i < tasks.length; i++) { - var reportName = tasks[i].target_uri.replace(/^\/plugins\/gingerbase\/debugreports\//, '') || i18n['GGBDR6012M']; - reports.push({ - 'name': reportName, - 'time': i18n['GGBDR6007M'] - }); - - if (gingerbase.trackingTasks.indexOf(tasks[i].id) >= 0) { - continue; - } - - gingerbase.trackTask(tasks[i].id, function(result) { - wok.topic('gingerbase/debugReportAdded').publish(); - }, function(result) { - // Error message from Async Task status - if (result['message']) { - var errText = result['message']; - } - // Error message from standard gingerbase exception - else { - var errText = result['responseJSON']['reason']; - } - result && wok.message.error(errText); - wok.topic('gingerbase/debugReportAdded').publish(); - }, null); - } - }, null, true); - - return reports; - }; - - var listDebugReports = function() { - gingerbase.listReports(function(reports) { - var pendingReports = getPendingReports(); - var allReports = pendingReports.concat(reports); - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - - - // Row selection will be cleared so disable buttons here - enableReportButtons(false); - - if (reportGrid) { - reportGrid.setData(allReports); - } else { - initReportGrid(allReports); - } - - if (!allReports.length) { - $('#available-reports-grid-btn-group').removeClass('hidden'); - } else { - $('#available-reports-grid-btn-group').addClass('hidden'); - } - - // Set id-debug-img to pending reports - // It will display a loading icon - var gridElement = $('#' + reportGridID); - // "Generating..." - $.each($('td:contains(' + i18n['GGBDR6007M'] + ')', gridElement), function(index, row) { - console.log(row); - $(row).parent().addClass('generating'); - $(row).parent().find('.dropdown-toggle').addClass('disabled'); - //$(row).attr('id', 'id-debug-img'); - }); - }, function(error) { - if (error['status'] === 403) { - $('#debug-report-section').addClass('hidden'); - // Check Repositories and resize column - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#repositories-section').removeClass('col-md-4'); - $('#repositories-section').addClass('col-md-8'); - } else { - $('#content-sys-info').removeClass('col-md-4'); - $('#content-sys-info').addClass('col-md-12'); - } - return; - } - $('#debug-report-section').removeClass('hidden'); - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - $('#debug-report-section, #repositories-section').removeClass('col-md-8'); - $('#debug-report-section, #repositories-section').addClass('col-md-4'); - } else { - $('#content-sys-info').removeClass('col-md-12'); - $('#content-sys-info').addClass('col-md-4'); - } - }); - }; - - var shutdownButtonID = '#host-button-shutdown'; - var restartButtonID = '#host-button-restart'; - var shutdownHost = function(params) { - var settings = { - content: i18n['GGBHOST6008M'], - confirm: i18n['GGBAPI6002M'], - cancel: i18n['GGBAPI6003M'] - }; - - wok.confirm(settings, function() { - $(shutdownButtonID).prop('disabled', true); - $(restartButtonID).prop('disabled', true); - // Check if there is any VM is running. - // Based on the success will shutdown/reboot - gingerbase.shutdown(params, function(success) { - wok.message.success(i18n['GGBHOST6009M']) - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - return; - }, function(error) { - // Looks like VMs are running. - wok.message.error.code('GGBHOST6001E'); - $(shutdownButtonID).prop('disabled', false); - $(restartButtonID).prop('disabled', false); - }); - }, function() { - }); - }; - - var initPage = function() { - - $('#host-button-shutdown').on('click', function(event) { - event.preventDefault(); - shutdownHost(null); - }); - - $('#host-button-restart').on('click', function(event) { - event.preventDefault(); - shutdownHost({ - reboot: true - }); - }); - - var setupUI = function() { - if (gingerbase.capabilities === undefined) { - setTimeout(setupUI, 2000); - return; - } - - if ((gingerbase.capabilities['repo_mngt_tool']) && (gingerbase.capabilities['repo_mngt_tool'] !== "None")) { - initRepositoriesGrid(gingerbase.capabilities['repo_mngt_tool']); - $('#repositories-section').switchClass('hidden', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').removeClass('col-md-12', gingerbase.capabilities['repo_mngt_tool']); - $('#content-sys-info').addClass('col-md-4', gingerbase.capabilities['repo_mngt_tool']); - wok.topic('gingerbase/repositoryAdded') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .subscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .subscribe(listRepositories); - } - - if (gingerbase.capabilities['update_tool']) { - $('#software-update-section').removeClass('hidden'); - initSoftwareUpdatesGrid(); - wok.topic('gingerbase/softwareUpdated') - .subscribe(listSoftwareUpdates); - } - - if (gingerbase.capabilities['system_report_tool']) { - listDebugReports(); - wok.topic('gingerbase/debugReportAdded') - .subscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed') - .subscribe(listDebugReports); - } - }; - setupUI(); - }; - - gingerbase.getHost(function(data) { - var htmlTmpl = $('#host-tmpl').html(); - data['logo'] = data['logo'] || ''; - data['memory'] = wok.formatMeasurement(data['memory'], { - fixed: 2 - }); - var templated = wok.substitute(htmlTmpl, data); - $('#host-content-container').html(templated); - - initPage(); - initTracker(); - }); - - var StatsMgr = function() { - var statsArray = { - cpu: { - u: { - type: 'percent', - legend: i18n['GGBHOST6002M'], - points: [] - } - }, - memory: { - u: { - type: 'value', - base: 2, - fixed: 2, - legend: i18n['GGBHOST6003M'], - points: [] - } - }, - diskIO: { - w: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6005M'], - 'class': 'disk-write', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6004M'], - points: [] - } - }, - networkIO: { - s: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6007M'], - 'class': 'network-sent', - points: [] - }, - r: { - type: 'value', - base: 2, - fixed: 2, - unit: 'B/s', - legend: i18n['GGBHOST6006M'], - points: [] - } - } - }; - var SIZE = 20; - var cursor = SIZE; - - var add = function(stats) { - for (var key in stats) { - var item = stats[key]; - for (var metrics in item) { - var value = item[metrics]['v']; - var max = item[metrics]['max']; - var unifiedMetrics = statsArray[key][metrics]; - var ps = unifiedMetrics['points']; - if (!Array.isArray(value)) { - ps.push(value); - if (ps.length > SIZE + 1) { - ps.shift(); - } - } else { - ps = ps.concat(value); - ps.splice(0, ps.length - SIZE - 1); - unifiedMetrics['points'] = ps; - } - if (max !== undefined) { - unifiedMetrics['max'] = max; - } else { - if (unifiedMetrics['type'] !== 'value') { - continue; - } - max = -Infinity; - $.each(ps, function(i, value) { - if (value > max) { - max = value; - } - }); - if (max === 0) { - ++max; - } - max *= 1.1; - unifiedMetrics['max'] = max; - } - } - } - cursor++; - }; - - var get = function(which) { - var stats = statsArray[which]; - var lines = []; - for (var k in stats) { - var obj = stats[k]; - var line = { - type: obj['type'], - base: obj['base'], - unit: obj['unit'], - fixed: obj['fixed'], - legend: obj['legend'] - }; - if (obj['max']) { - line['max'] = obj['max']; - } - if (obj['class']) { - line['class'] = obj['class']; - } - var ps = obj['points']; - var numStats = ps.length; - var unifiedPoints = []; - $.each(ps, function(i, value) { - unifiedPoints.push({ - x: cursor - numStats + i, - y: value - }); - }); - line['points'] = unifiedPoints; - lines.push(line); - } - return lines; - }; - - return { - add: add, - get: get - }; - }; - - var Tracker = function(charts) { - var charts = charts; - var timer = null; - var statsPool = new StatsMgr(); - var setCharts = function(newCharts) { - charts = newCharts; - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - }; - - var self = this; - - var UnifyStats = function(stats) { - var result = { - cpu: { - u: { - v: stats['cpu_utilization'] - } - }, - memory: { - u: {} - }, - diskIO: { - w: { - v: stats['disk_write_rate'] - }, - r: { - v: stats['disk_read_rate'] - } - }, - networkIO: { - s: { - v: stats['net_sent_rate'] - }, - r: { - v: stats['net_recv_rate'] - } - } - }; - if (Array.isArray(stats['memory'])) { - result.memory.u['v'] = []; - result.memory.u['max'] = -Infinity; - for (var i = 0; i < stats['memory'].length; i++) { - result.memory.u['v'].push(stats['memory'][i]['avail']); - result.memory.u['max'] = Math.max(result.memory.u['max'], stats['memory'][i]['total']); - } - } else { - result.memory.u['v'] = stats['memory']['avail'], - result.memory.u['max'] = stats['memory']['total'] - } - return (result); - }; - - - var statsCallback = function(stats) { - var unifiedStats = UnifyStats(stats); - statsPool.add(unifiedStats); - for (var key in charts) { - var chart = charts[key]; - chart.updateUI(statsPool.get(key)); - } - timer = setTimeout(function() { - continueTrack(); - }, 1000); - }; - - var track = function() { - gingerbase.getHostStatsHistory(statsCallback, - function() { - continueTrack(); - }); - }; - - var continueTrack = function() { - gingerbase.getHostStats(statsCallback, - function() { - continueTrack(); - }); - }; - - var destroy = function() { - timer && clearTimeout(timer); - timer = null; - }; - - return { - setCharts: setCharts, - start: track, - stop: destroy - }; - }; - - var initTracker = function() { - // TODO: Extend tabs with onUnload event to unregister timers. - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - var trackedCharts = { - cpu: new wok.widget.LineChart({ - id: 'chart-cpu', - node: 'container-chart-cpu', - type: 'percent' - }), - memory: new wok.widget.LineChart({ - id: 'chart-memory', - node: 'container-chart-memory', - type: 'value' - }), - diskIO: new wok.widget.LineChart({ - id: 'chart-disk-io', - node: 'container-chart-disk-io', - type: 'value' - }), - networkIO: new wok.widget.LineChart({ - id: 'chart-network-io', - node: 'container-chart-network-io', - type: 'value' - }) - }; - - if (gingerbase.hostTimer) { - gingerbase.hostTimer.setCharts(trackedCharts); - } else { - gingerbase.hostTimer = new Tracker(trackedCharts); - gingerbase.hostTimer.start(); - } - }; - - $('#host-root-container').on('remove', function() { - if (gingerbase.hostTimer) { - gingerbase.hostTimer.stop(); - delete gingerbase.hostTimer; - } - - repositoriesGrid && repositoriesGrid.destroy(); - wok.topic('gingerbase/repositoryAdded') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryUpdated') - .unsubscribe(listRepositories); - wok.topic('gingerbase/repositoryDeleted') - .unsubscribe(listRepositories); - - softwareUpdatesGrid && softwareUpdatesGrid.destroy(); - wok.topic('gingerbase/softwareUpdated').unsubscribe(listSoftwareUpdates); - - reportGrid && reportGrid.destroy(); - wok.topic('gingerbase/debugReportAdded').unsubscribe(listDebugReports); - wok.topic('gingerbase/debugReportRenamed').unsubscribe(listDebugReports); - }); -}; diff --git a/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl new file mode 100644 index 0000000..06b8088 --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl @@ -0,0 +1,135 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + <ul class="nav navbar-nav navbar-right tools"> + <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> + <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> + <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> + </ul> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-dashboard-tmpl" type="gingerbase/template"> +<div class="host-dashboard"> + <div class="container"> + <div id="alert-container"></div> + <div id="content-sys-statistics" class="row"> + <div class="col-md-3"> + <div id="cpu-dashboard"> + <h3 class="section-label">$_("CPU")</h3> + <div class="section-value"> + <div id="container-chart-cpu" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="memory-dashboard"> + <h3 class="section-label">$_("Memory")</h3> + <div class="section-value"> + <div id="container-chart-memory" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="disk-dashboard"> + <h3 class="section-label">$_("Disk I/O")</h3> + <div class="section-value"> + <div id="container-chart-disk-io" class="inline-block"></div> + </div> + </div> + </div> + <div class="col-md-3"> + <div id="network-dashboard"> + <h3 class="section-label">$_("Network I/O")</h3> + <div class="section-value"> + <div id="container-chart-network-io" class="inline-block"></div> + </div> + </div> + </div> + </div> + </div> +</div> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="content-sys-info" class="panel panel-default col-md-6"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Basic Information")</h3> + </div> + <div class="panel-body"> + <dl class="basic-information-list"> + <dt>{os_distro}</dt> + <dd>$_("OS Distro")</dd> + <dt>{os_version}</dt> + <dd>$_("OS Version")</dd> + <dt>{os_codename}</dt> + <dd>$_("OS Code Name")</dd> + <dt>{cpu_model}</dt> + <dd>$_("Processor")</dd> + <dt>{cpus}</dt> + <dd>$_("CPU(s)")</dd> + <dt>{memory}</dt> + <dd>$_("Memory")</dd> + </dl> + </div> + </div> + <div id="debug-report-section" class="col-md-6 hidden"></div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_dashboard(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl new file mode 100644 index 0000000..20790ed --- /dev/null +++ b/src/wok/plugins/gingerbase/ui/pages/host-update.html.tmpl @@ -0,0 +1,90 @@ +#* + * Project Ginger Base + * + * Copyright IBM, Corp. 2013-2015 + * + * Code derived from Project Kimchi + * + * Licensed 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. + *# + +#unicode UTF-8 +#import gettext +#from wok.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> +<script src="plugins/gingerbase/js/gingerbase.min.js"></script> +</head> +<body> +<div id="host-root-container"> +<nav class="navbar navbar-default toolbar"> + <div class="container"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse" id="toolbar"> + </div> + </div> +</nav> + <div id="host-content-container" class="empty-when-logged-off"></div> +</div> + +<script id="host-update-tmpl" type="gingerbase/template"> +<div class="host-panel"> + <div class="container"> + <div id="host-info-container" class="row"> + <div id="repositories-section" class="col-md-12 hidden"></div> + </div> + <div class="row"> + <div id="software-update-section" class="panel panel-default col-md-12 hidden"> + <div class="panel-heading"> + <h3 class="panel-title">$_("Software Updates")</h3> + </div> + <div id="content-software-update" class="panel panel-default"> + <div id="software-updates-grid-container"></div> + <div id="software-updates-progress-container" class="hidden"> + <div class="software-updates-main"> + <h3> + <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> + <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> + </a> + </h3> + <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> + </div> + </div> + </div> + </div> + </div> + </div> +</div> +</script> +<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> +</div> +<script type="text/javascript"> + gingerbase.host_update(); +</script> +</body> +</html> diff --git a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl deleted file mode 100644 index d17f184..0000000 --- a/src/wok/plugins/gingerbase/ui/pages/host.html.tmpl +++ /dev/null @@ -1,156 +0,0 @@ -#* - * Project Ginger Base - * - * Copyright IBM, Corp. 2013-2015 - * - * Code derived from Project Kimchi - * - * Licensed 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. - *# - -#unicode UTF-8 -#import gettext -#from wok.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -<!DOCTYPE html> -<html> -<head> -<link rel="stylesheet" href="plugins/gingerbase/css/gingerbase.css"> -<script src="plugins/gingerbase/js/gingerbase.min.js"></script> -</head> -<body> -<div id="host-root-container"> -<nav class="navbar navbar-default toolbar"> - <div class="container"> - <!-- Brand and toggle get grouped for better mobile display --> - <div class="navbar-header"> - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toolbar" aria-expanded="false"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - - <!-- Collect the nav links, forms, and other content for toggling --> - <div class="collapse navbar-collapse" id="toolbar"> - <ul class="nav navbar-nav navbar-right tools"> - <li><a id="host-button-restart" href="javascript:void(0);"><i class="fa fa-undo"></i><span>$_("Restart")</span></a></li> - <li><a id="host-button-shutdown" href="javascript:void(0);"><i class="fa fa-ban"></i><span>$_("Shut down")</span></a></li> - <!-- <li><a href="javascript:void(0);"><i class="fa fa-desktop"></i><span>$_("Connect")</span></a></li> --> - </ul> - </div> - </div> -</nav> - <div id="host-content-container" class="empty-when-logged-off"></div> -</div> - -<script id="host-tmpl" type="gingerbase/template"> -<div class="host-dashboard"> - <div class="container"> - <div id="alert-container"></div> - <div id="content-sys-statistics" class="row"> - <div class="col-md-3"> - <div id="cpu-dashboard"> - <h3 class="section-label">$_("CPU")</h3> - <div class="section-value"> - <div id="container-chart-cpu" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="memory-dashboard"> - <h3 class="section-label">$_("Memory")</h3> - <div class="section-value"> - <div id="container-chart-memory" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="disk-dashboard"> - <h3 class="section-label">$_("Disk I/O")</h3> - <div class="section-value"> - <div id="container-chart-disk-io" class="inline-block"></div> - </div> - </div> - </div> - <div class="col-md-3"> - <div id="network-dashboard"> - <h3 class="section-label">$_("Network I/O")</h3> - <div class="section-value"> - <div id="container-chart-network-io" class="inline-block"></div> - </div> - </div> - </div> - </div> - </div> -</div> -<div class="host-panel"> - <div class="container"> - <div id="host-info-container" class="row"> - <div id="content-sys-info" class="panel panel-default col-md-12"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Basic Information")</h3> - </div> - <div class="panel-body"> - <dl class="basic-information-list"> - <dt>{os_distro}</dt> - <dd>$_("OS Distro")</dd> - <dt>{os_version}</dt> - <dd>$_("OS Version")</dd> - <dt>{os_codename}</dt> - <dd>$_("OS Code Name")</dd> - <dt>{cpu_model}</dt> - <dd>$_("Processor")</dd> - <dt>{cpus}</dt> - <dd>$_("CPU(s)")</dd> - <dt>{memory}</dt> - <dd>$_("Memory")</dd> - </dl> - </div> - </div> - <div id="repositories-section" class="col-md-8 hidden"></div> - <div id="debug-report-section" class="col-md-8 hidden"></div> - </div> - <div class="row"> - <div id="software-update-section" class="panel panel-default col-md-12 hidden"> - <div class="panel-heading"> - <h3 class="panel-title">$_("Software Updates")</h3> - </div> - <div id="content-software-update" class="panel panel-default"> - <div id="software-updates-grid-container"></div> - <div id="software-updates-progress-container" class="hidden"> - <div class="software-updates-main"> - <h3> - <a role="button" data-toggle="collapse" data-parent="#accordion" href="#software-updates-progress-textarea" aria-expanded="true" aria-controls="software-updates-progress-textarea" class=""> - <span class="accordion-icon"></span><span class="accordion-text">$_("Update Progress")</span> - </a> - </h3> - <textarea class="collapse in" id="software-updates-progress-textarea" readonly></textarea> - </div> - </div> - </div> - </div> - </div> - </div> -</div> -</script> -<div id="modalWindow" class="modal fade host-modal" tabindex="-1" role="dialog" aria-labelledby="hostsModalLabel" aria-hidden="true"> -</div> -<script type="text/javascript"> - gingerbase.host_main(); -</script> -</body> -</html>
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com> New UI screen shot shows 1. New UI page 2. Feature tab split --- .../gingerbase/docs/gingerbase-host-tab.png | Bin 79669 -> 105906 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png b/src/wok/plugins/gingerbase/docs/gingerbase-host-tab.png index d84168d7e0182e91a2ed839c70051e0c1e0c8a45..593edbe0ec06c07cf593e79eac6abe7c72ccfcfb 100644 GIT binary patch literal 105906 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:WCz4 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%0D=ey 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 UcfO1j{+{}r#j|g!uKDBt0CW}fE&u=k literal 79669 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 VxXX0{+N^&SV)#2i3&@w&{{w*cbGrZl -- 2.4.0

From: Chandra Shekhar Reddy Potula <chandra@linux.vnet.ibm.com> UI changes to accommodate the basic system info 1. memory shows online, offline memory info 2. cpu shows online, offline cpu info On s390x deidcated, shared cpu info shown 3. On s390x hypervisor, LPAR details shown --- .../gingerbase/ui/css/src/modules/_host.scss | 9 +++++---- .../ui/js/src/gingerbase.host-dashboard.js | 23 +++++++++++++++++++++- .../gingerbase/ui/pages/host-dashboard.html.tmpl | 8 ++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/wok/plugins/gingerbase/ui/css/src/modules/_host.scss b/src/wok/plugins/gingerbase/ui/css/src/modules/_host.scss index 1fb062c..dc27df5 100644 --- a/src/wok/plugins/gingerbase/ui/css/src/modules/_host.scss +++ b/src/wok/plugins/gingerbase/ui/css/src/modules/_host.scss @@ -104,22 +104,23 @@ #host-info-container { padding-top: 10px; .basic-information-list { - height: 517px; + height: auto; overflow-x: hidden; overflow-y: auto; margin: 0; @extend .row; // Extending bootstrap .row clearfix util - .basic-information-list dt { + + } + .panel-body dt { font-weight: 600; font-size: 14.5pt; line-height: 12px; } - .basic-information-list dd { + .panel-body dd { font-size: 12.5pt; font-weight: 400; margin-bottom: 12px; } - } } diff --git a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js index 047ba5b..c4530d7 100644 --- a/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js +++ b/src/wok/plugins/gingerbase/ui/js/src/gingerbase.host-dashboard.js @@ -297,15 +297,36 @@ gingerbase.host_dashboard = function() { gingerbase.getHost(function(data) { var htmlTmpl = $('#host-dashboard-tmpl').html(); + var memory = null + var cpus = null data['logo'] = data['logo'] || ''; - data['memory'] = wok.formatMeasurement(data['memory'], { + // Memory fetch online, offline details + data['memory']['online'] = wok.formatMeasurement(data['memory']['online'], { fixed: 2 }); + data['memory']['offline'] = wok.formatMeasurement(data['memory']['offline'], { + fixed: 2 + }); + memory = "Online: " + data['memory']['online'] + ", Offline: " + data['memory']['offline']; + // CPU fetch online, offline details + cpus = 'Online: ' + data['cpus']['online'] + ', Offline: ' + data['cpus']['offline']; + // This code is only for s390x architecture where hypervisor details required. + if (data['architecture'] == 's390x'){ + cpus += ', Shared: ' + data['cpus']['shared'] + ', Dedicated: ' + data['cpus']['dedicated']; + data['lpar_details'] = 'Name: ' + data['virtualization']['lpar_name'] + ', ID: ' + data['virtualization']['lpar_number']; + data['hypervisor_details'] = 'Name: ' + data['virtualization']['hypervisor'] + ', Vendor :' + data['virtualization']['hypervisor_vendor']; + } + data['memory'] = memory + data['cpus'] = cpus var templated = wok.substitute(htmlTmpl, data); $('#host-content-container').html(templated); initPage(); initTracker(); + // Enable hypervisor, LPAR details on s390x architechture + if (data['architecture'] == 's390x'){ + $('#s390x-info').removeClass(); + } }); var StatsMgr = function() { diff --git a/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl index 06b8088..eec40c3 100644 --- a/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl +++ b/src/wok/plugins/gingerbase/ui/pages/host-dashboard.html.tmpl @@ -106,6 +106,8 @@ </div> <div class="panel-body"> <dl class="basic-information-list"> + <dt>{architecture}</dt> + <dd>$_("Architecture")</dd> <dt>{os_distro}</dt> <dd>$_("OS Distro")</dd> <dt>{os_version}</dt> @@ -119,6 +121,12 @@ <dt>{memory}</dt> <dd>$_("Memory")</dd> </dl> + <dl id="s390x-info" class="hidden"> + <dt>{lpar_details}</dt> + <dd>$_("LPAR Details")</dd> + <dt>{hypervisor_details}</dt> + <dd>$_("Hypervisor Details")</dd> + </dl> </div> </div> <div id="debug-report-section" class="col-md-6 hidden"></div> -- 2.4.0
participants (2)
-
Aline Manera
-
chandra@linux.vnet.ibm.com