From bc45654203b6d898dbb7d4697c1afd4f99880f68 Mon Sep 17 00:00:00 2001 From: juanmont Date: Fri, 25 Nov 2016 16:55:34 +0100 Subject: [PATCH] F #4393: Add new resize dialog, remove labels for disk actions. Include better handling of units and cost for disks --- src/sunstone/etc/sunstone-views/admin.yaml | 1 + src/sunstone/public/app/opennebula/vm.js | 6 + src/sunstone/public/app/tabs/vms-tab.js | 1 + .../public/app/tabs/vms-tab/actions.js | 1 + .../app/tabs/vms-tab/dialogs/disk-resize.js | 145 ++++++++++++++++++ .../vms-tab/dialogs/disk-resize/dialogId.js | 19 +++ .../tabs/vms-tab/dialogs/disk-resize/html.hbs | 54 +++++++ .../public/app/tabs/vms-tab/panels/storage.js | 43 +++++- src/sunstone/public/app/utils/humanize.js | 14 ++ 9 files changed, 279 insertions(+), 5 deletions(-) create mode 100644 src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize.js create mode 100644 src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/dialogId.js create mode 100644 src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/html.hbs diff --git a/src/sunstone/etc/sunstone-views/admin.yaml b/src/sunstone/etc/sunstone-views/admin.yaml index c7841aa65a..d4cf221146 100644 --- a/src/sunstone/etc/sunstone-views/admin.yaml +++ b/src/sunstone/etc/sunstone-views/admin.yaml @@ -336,6 +336,7 @@ tabs: VM.terminate: true VM.terminate_hard: true VM.resize: true + VM.disk_resize: true VM.attachdisk: true VM.detachdisk: true VM.disk_saveas: true diff --git a/src/sunstone/public/app/opennebula/vm.js b/src/sunstone/public/app/opennebula/vm.js index f4f0c17ab5..b6dc9d04d7 100644 --- a/src/sunstone/public/app/opennebula/vm.js +++ b/src/sunstone/public/app/opennebula/vm.js @@ -493,6 +493,12 @@ define(function(require) { var action_obj = params.data.extra_param; OpenNebulaAction.simple_action(params, RESOURCE, "resize", action_obj); }, + "disk_resize" : function(params) { + var action_obj = params.data.extra_param; + console.log(action_obj); + console.log(RESOURCE); + OpenNebulaAction.simple_action(params, RESOURCE, "disk_resize", action_obj); + }, "attachdisk" : function(params) { var action_obj = {"disk_template": params.data.extra_param}; OpenNebulaAction.simple_action(params, RESOURCE, "attachdisk", action_obj); diff --git a/src/sunstone/public/app/tabs/vms-tab.js b/src/sunstone/public/app/tabs/vms-tab.js index 3e6aeebdf3..f8c62025f0 100644 --- a/src/sunstone/public/app/tabs/vms-tab.js +++ b/src/sunstone/public/app/tabs/vms-tab.js @@ -30,6 +30,7 @@ define(function(require) { require('./vms-tab/dialogs/attach-disk'), require('./vms-tab/dialogs/disk-snapshot'), require('./vms-tab/dialogs/disk-saveas'), + require('./vms-tab/dialogs/disk-resize'), require('./vms-tab/dialogs/attach-nic'), require('./vms-tab/dialogs/snapshot'), require('./vms-tab/dialogs/vnc'), diff --git a/src/sunstone/public/app/tabs/vms-tab/actions.js b/src/sunstone/public/app/tabs/vms-tab/actions.js index ca7172870b..f8f0711ced 100644 --- a/src/sunstone/public/app/tabs/vms-tab/actions.js +++ b/src/sunstone/public/app/tabs/vms-tab/actions.js @@ -88,6 +88,7 @@ define(function(require) { "VM.attachnic": _commonActions.singleAction('attachnic'), "VM.detachnic": _commonActions.singleAction('detachnic'), "VM.resize": _commonActions.singleAction('resize'), + "VM.disk_resize": _commonActions.singleAction('disk_resize'), "VM.snapshot_create": _commonActions.singleAction('snapshot_create'), "VM.snapshot_revert": _commonActions.singleAction('snapshot_revert'), "VM.snapshot_delete": _commonActions.singleAction('snapshot_delete'), diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize.js b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize.js new file mode 100644 index 0000000000..9f313fef8f --- /dev/null +++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize.js @@ -0,0 +1,145 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +define(function(require) { + /* + DEPENDENCIES + */ + var Locale = require('utils/locale'); + var BaseDialog = require('utils/dialogs/dialog'); + var TemplateHTML = require('hbs!./disk-resize/html'); + var Sunstone = require('sunstone'); + var Tips = require('utils/tips'); + var RangeSlider = require('utils/range-slider'); + var Humanize = require('utils/humanize'); + + /* + CONSTANTS + */ + + var DIALOG_ID = require('./disk-resize/dialogId'); + var TAB_ID = require('../tabId'); + + /* + CONSTRUCTOR + */ + + function Dialog() { + this.dialogId = DIALOG_ID; + + BaseDialog.call(this); + } + + Dialog.DIALOG_ID = DIALOG_ID; + Dialog.prototype = Object.create(BaseDialog.prototype); + Dialog.prototype.constructor = Dialog; + Dialog.prototype.html = _html; + Dialog.prototype.onShow = _onShow; + Dialog.prototype.setup = _setup; + Dialog.prototype.setParams = _setParams; + + return Dialog; + + /* + FUNCTION DEFINITIONS + */ + + function _html() { + return TemplateHTML({ + 'dialogId': this.dialogId + }); + + }function convertCostNumber(number){ + if(number >= 1000000){ + number = (number/1000000).toFixed(2) + return number.toString()+"M"; + } + else if(number >= 1000){ + number = (number/1000).toFixed(2) + return number.toString()+"K"; + } + else if (number >= 0 && number < 1000) + return number.toFixed(2); + else + return number; + } + + function _setup(context) { + var that = this; + Tips.setup(context); + $( ".diskSlider", context).html(RangeSlider.html({ + min: that.diskSize, + max: Humanize.sizeToMB("500GB"), + initial: that.diskSize, + name: "resize" + })); + $( ".uinput-slider-val",context).prop('type', 'text'); + $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val())); + + $( ".uinput-slider", context).on("change", function(){ + $( ".uinput-slider-val",context).val(Humanize.size($( ".uinput-slider",context).val())); + var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost; + document.getElementById("new_cost_resize").textContent = Locale.tr("Cost")+": "+ convertCostNumber(cost); + }); + + $( ".uinput-slider-val", context).on("change", function(){ + $( ".uinput-slider",context).val(Humanize.sizeToMB($( ".uinput-slider-val",context).val())); + var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*that.diskCost; + document.getElementById("new_cost_resize").textContent = Locale.tr("Cost")+": "+ convertCostNumber(cost); + }); + + var cost = Humanize.sizeToMB($( ".uinput-slider",context).val())*this.diskCost; + document.getElementById("new_cost_resize").textContent = Locale.tr("Cost")+": "+ convertCostNumber(cost); + + + $('#' + DIALOG_ID + 'Form', context).submit(function() { + var new_size = $( ".uinput-slider",context).val(); + var obj = { + "vm_id": that.element.ID, + "disk_id" : that.diskId, + "new_size": new_size + }; + + Sunstone.runAction('VM.disk_resize', that.element.ID, obj); + + Sunstone.getDialog(DIALOG_ID).hide(); + Sunstone.getDialog(DIALOG_ID).reset(); + return false; + }); + + return false; + } + + function _onShow(context) { + this.setNames( {tabId: TAB_ID} ); + $("#disk_id", context).val(this.diskId); + $("#resize_disk", context).focus(); + return false; + } + + /** + * @param {object} params + * - params.element : VM element + * - params.diskId : Disk ID to save as + * - params.snapshotId : Disk snapshot ID to save as. Can be undefined + */ + function _setParams(params) { + this.element = params.element; + this.diskId = params.diskId; + this.diskSize = params.diskSize; + this.diskCost = params.diskCost; + } +}); diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/dialogId.js b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/dialogId.js new file mode 100644 index 0000000000..5681388beb --- /dev/null +++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/dialogId.js @@ -0,0 +1,19 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +define(function(require) { + return 'diskResizeVMDialog'; +}); diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/html.hbs b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/html.hbs new file mode 100644 index 0000000000..7bfd00064a --- /dev/null +++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/disk-resize/html.hbs @@ -0,0 +1,54 @@ +{{! -------------------------------------------------------------------------- }} +{{! Copyright 2002-2016, OpenNebula Project, OpenNebula Systems }} +{{! }} +{{! 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. }} +{{! -------------------------------------------------------------------------- }} + +
+
+
+

{{tr "Disk Resize"}}

+
+
+
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + {{tr "Cost"}}: + {{tr "COST"}} / {{tr "MONTH"}} + +
+
+
+ +
+ +
+
+
diff --git a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js index 12d3c1289e..990693e873 100644 --- a/src/sunstone/public/app/tabs/vms-tab/panels/storage.js +++ b/src/sunstone/public/app/tabs/vms-tab/panels/storage.js @@ -42,6 +42,7 @@ define(function(require) { var DISK_SNAPSHOT_DIALOG_ID = require('../dialogs/disk-snapshot/dialogId'); var DISK_SAVEAS_DIALOG_ID = require('../dialogs/disk-saveas/dialogId'); var CONFIRM_DIALOG_ID = require('utils/dialogs/generic-confirm/dialogId'); + var DISK_RESIZE_DIALOG_ID = require('../dialogs/disk-resize/dialogId'); var RESOURCE = "VM" var XML_ROOT = "VM" @@ -287,7 +288,7 @@ define(function(require) { if (disk.IMAGE_ID && StateActions.enabledStateAction("VM.disk_saveas", that.element.STATE, that.element.LCM_STATE)) { actions += '\ - ' + Locale.tr("Save as") + '  '; +  ';//+ Locale.tr("Save as") + ';' } } @@ -295,16 +296,23 @@ define(function(require) { if (Config.isTabActionEnabled("vms-tab", "VM.detachdisk")) { if (StateActions.enabledStateAction("VM.detachdisk", that.element.STATE, that.element.LCM_STATE) && !disk.CONTEXT) { actions += ('\ - ' + Locale.tr("Detach") + - '  '); +  ');// + Locale.tr("Detach") + + } } if (Config.isTabActionEnabled("vms-tab", "VM.disk_snapshot_create")) { if (StateActions.enabledStateAction("VM.disk_snapshot_create", that.element.STATE, that.element.LCM_STATE) && disk.IMAGE_ID) { actions += ('\ - ' + Locale.tr("Snapshot") + - ''); +  ');//+ Locale.tr("Snapshot") + + + } + } + + if (Config.isTabActionEnabled("vms-tab", "VM.resize")) { + if (StateActions.enabledStateAction("VM.resize", that.element.STATE, that.element.LCM_STATE)) { + actions += ('\ + '); } } } @@ -471,9 +479,16 @@ define(function(require) { }); } + context.off("change", ".snapshot_check_item"); context.on("change", ".snapshot_check_item", function() { var snapshotsSection = $(this).closest('.snapshots'); + if(that.element.STATE == "3"){ + $(".disk_snapshot_revert", snapshotsSection).hide(); + } + else{ + $(".disk_snapshot_revert", snapshotsSection).show(); + } // Unselect other check inputs var checked = $(this).is(':checked'); @@ -561,6 +576,24 @@ define(function(require) { return false; }); } + if (Config.isTabActionEnabled("vms-tab", "VM.disk_snapshot_delete")) { + context.off('click', '.disk_sresize'); + context.on('click', '.disk_resize', function() { + var disk_id = $(this).parents('tr').attr('disk_id'); + var disk_size = that.element.TEMPLATE.DISK.SIZE*1024; //to MB + var dialog = Sunstone.getDialog(DISK_RESIZE_DIALOG_ID); + dialog.setParams( + { element: that.element, + diskId: disk_id, + diskSize: disk_size, + diskCost: that.element.TEMPLATE.DISK_COST + }); + + dialog.reset(); + dialog.show(); + return false; + }); + } Tree.setup(context); } diff --git a/src/sunstone/public/app/utils/humanize.js b/src/sunstone/public/app/utils/humanize.js index 400938ab67..c218397d9b 100644 --- a/src/sunstone/public/app/utils/humanize.js +++ b/src/sunstone/public/app/utils/humanize.js @@ -27,6 +27,7 @@ define(function(require) { 'sizeFromB': _sizeFromB, 'sizeFromKB': _sizeFromKB, 'sizeFromMB': _sizeFromMB, + 'sizeToMB': _sizeToMB, 'prettyDuration': _prettyDuration, 'prettyTime': _prettyTime, 'prettyTimeAxis': _prettyTimeAxis, @@ -95,6 +96,19 @@ define(function(require) { return st; } + function _sizeToMB(value){ + var split = value.split("B"); + var factor = split[0].slice(-1); + var number = parseFloat(split[0]); + if(factor=="K") + number = number * 1024; + else if(factor=="G") + number = number * 1024 * 1024; + else if(factor=="T") + number = number * 1024 * 1024 * 1024; + return number; + } + function _prettyDuration(duration) { var days = Math.floor(duration / 86400); duration -= days * 86400;