
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