From 98b4f598beeffa04b779d67e61ecaa03590ea93b Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 Aug 2012 13:19:35 -0700 Subject: [PATCH 01/15] Autoscale UI: Add actions to top of dialog Support performing actions via the autoscaler dialog. This adds 'autoscaleActions' and 'actionFilter' options to the autoscaler, which specify and handle the actions appearing in the UI. Performing these actions will cause a loading overlay to appear until actions are finished, when the action bar is refreshed via the action filter. --- ui/css/cloudstack3.css | 13 +++++ ui/scripts/autoscaler.js | 61 ++++++++++++++++++++ ui/scripts/ui-custom/autoscaler.js | 89 +++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 1 deletion(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 1abac2fe60e..45d9ba4debf 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -9683,6 +9683,19 @@ div.panel.ui-dialog div.list-view div.fixed-header { max-height: 600px; } +.ui-dialog div.autoscaler .detail-actions { +} + +.ui-dialog div.autoscaler .detail-actions .buttons { + float: right; + margin-right: 6px; +} + +.ui-dialog div.autoscaler .detail-actions .buttons .action { + width: 32px; + float: left; +} + .ui-dialog div.autoscaler div.form-container div.form-item[rel=securityGroups] { display: block; width: 370px; diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index 7bd3f7e3c83..91543c17b61 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -17,6 +17,67 @@ var totalScaleDownCondition = 0; cloudStack.autoscaler = { + // UI actions to appear in dialog + autoscaleActions: { + enable: { + label: 'Enable Autoscaler', + action: function(args) { + args.response.success({ + _custom: { jobId: 12345 }, + notification: { + poll: function(args) { + args.complete({ + data: { state: 'Enabled' } + }); + } + } + }); + } + }, + disable: { + label: 'Disable Autoscaler', + action: function(args) { + args.response.success({ + _custom: { jobId: 12345 }, + notification: { + poll: function(args) { + args.complete({ + data: { state: 'Disabled' } + }); + } + } + }); + } + }, + restart: { + label: 'Restart Autoscaler', + action: function(args) { + args.response.success({ + _custom: { jobId: 12345 }, + notification: { + poll: function(args) { + args.complete({ + data: { state: 'Enabled' } + }); + } + } + }); + } + } + }, + actionFilter: function(args) { + var data = $.isArray(args.context.originalAutoscaleData) ? + args.context.originalAutoscaleData[0] : {}; + + if (data.state == 'Enabled') { + return ['disable', 'restart']; + } else if (data.state == 'Disabled') { + return ['enable']; + } + + // No existing data, so actions are not visible + return []; + }, dataProvider: function(args) { // Reset data scaleUpData = []; diff --git a/ui/scripts/ui-custom/autoscaler.js b/ui/scripts/ui-custom/autoscaler.js index a897c0d0828..b0ab5859ecd 100644 --- a/ui/scripts/ui-custom/autoscaler.js +++ b/ui/scripts/ui-custom/autoscaler.js @@ -18,6 +18,8 @@ var scaleuppolicy = forms.scaleUpPolicy; var scaledownpolicy = forms.scaleDownPolicy; var dataProvider = cloudStack.autoscaler.dataProvider; + var actions = cloudStack.autoscaler.autoscaleActions; + var actionFilter = cloudStack.autoscaler.actionFilter; return function(args) { var context = args.data ? @@ -51,6 +53,88 @@ scaleDownPolicyTitleForm, $scaleDownPolicyTitleForm, scaleUpPolicyForm, scaleDownPolicyForm; + var renderActions = function(args) { + var data = args.data; + var context = args.context; + var $actions = $('
').addClass('detail-group'); + var $actionsTable = $('').append(''); + var $detailActions = $('
').addClass('detail-actions'); + var $buttons = $('
').addClass('buttons'); + var visibleActions = actionFilter ? + actionFilter({ + context: $.extend(true, {}, context, { + originalAutoscaleData: data ? [data] : null + }) + }) : + $.map(actions, function(value, key) { return key; }); + + $detailActions.append($buttons); + $actionsTable.find('tr').append($detailActions); + $actions.append($actionsTable); + + $(visibleActions).map(function(index, actionID) { + var action = actions[actionID]; + var label = _l(action.label); + var $action = $('
').addClass('action').addClass(actionID); + var $icon = $('') + .attr({ href: '#', title: label }) + .append($('').addClass('icon')); + + if (visibleActions.length == 1) $action.addClass('single'); + else if (!index) $action.addClass('first'); + else if (index == visibleActions.length - 1) $action.addClass('last'); + + // Perform action event + $action.click(function() { + var $loading = $('
').addClass('loading-overlay').appendTo($autoscalerDialog); + var success = function(args) { + $loading.remove(); + cloudStack.dialog.notice({ + message: _l('label.task.completed') + ': ' + label + }); + + // Reload actions + var $newActions = renderActions({ + data: data ? $.extend(data, args.data) : args.data, + context: context + }); + + $actions.after($newActions); + $actions.remove(); + }; + var error = function(message) { + $loading.remove(); + cloudStack.dialog.notice({ message: message }); + }; + + action.action({ + response: { + success: function(args) { + var notification = $.extend(args.notification, { + _custom: args._custom, + desc: label + }); + + cloudStack.ui.notifications.add( + notification, + success, {}, + error, {} + ); + }, + error: error + } + }); + }); + + $action.append($icon); + $action.appendTo($buttons); + }); + + if (!visibleActions || !visibleActions.length) $actions.hide(); + + return $actions; + }; + var renderDialogContent = function(args) { var data = args.data ? args.data : {}; @@ -69,7 +153,7 @@ $.extend(context, { originalAutoscaleData: args.data - }) + }); // Create and append top fields // -- uses create form to generate fields @@ -207,6 +291,9 @@ $autoscalerDialog.dialog('option', 'position', 'center'); $autoscalerDialog.dialog('option', 'height', 'auto'); + + // Setup actions + renderActions(args).prependTo($autoscalerDialog); }; var $loading = $('
').addClass('loading-overlay').appendTo($autoscalerDialog); From fa2d392ba2d7e43aefa369c787c4ba85112a6c62 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 Aug 2012 13:20:52 -0700 Subject: [PATCH 02/15] cloudstack 3.0 UI - autoscale - for regular user - fix a bug that createAutoScaleVmProfile API fails because autoscaleuserid is undefined. --- ui/scripts/autoscaler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index 91543c17b61..622f7d43fbd 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -1066,7 +1066,7 @@ array1.push("&destroyvmgraceperiod=" + args.data.destroyVMgracePeriod); array1.push("&snmpcommunity=" + args.data.snmpCommunity); array1.push("&snmpport=" + args.data.snmpPort); - if(args.data.username != "") + if(args.data.username != null && args.data.username.length > 0) array1.push("&autoscaleuserid=" + args.data.username); $.ajax({ From 365e8803cd4ca5f269de58af74de6092741e8961 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 Aug 2012 13:45:37 -0700 Subject: [PATCH 03/15] multiEdit: support validate on custom action If requireValidation: true is set for a custom action, then only perform action if multiEdit's form fields are valid. This does not apply to clicking on existing rules' action buttons. Syntax: multiEdit: { fields: { testField: { custom: { requireValidation: true, ... }, ... }, ... } } --- ui/scripts/ui/widgets/multiEdit.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index a2e382f92dd..36900214f4a 100644 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -804,6 +804,9 @@ $('
').addClass('button add-vm custom-action') .html(_l(field.custom.buttonLabel)) .click(function() { + if (field.custom.requireValidation && + !$multiForm.valid()) return false; + var formData = getMultiData($multi); field.custom.action({ @@ -816,6 +819,8 @@ } } }); + + return false; }).appendTo($td); } else if (field.addButton) { $addVM = $('
').addClass('button add-vm').html( From 38a269c1bfe5e92cc59c107154cc05a0ffae2fec Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 Aug 2012 13:46:12 -0700 Subject: [PATCH 04/15] CS-15861: Validate form fields before showing autoscale UI --only applies to new LB rule form, not existing LB rules. --- ui/scripts/network.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index b3c01d25231..f6439d32697 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -2279,6 +2279,7 @@ 'autoScale': { label: 'AutoScale', custom: { + requireValidation: true, buttonLabel: 'label.configure', action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler) } From 15d1e57b92e20ac97632d6b6fd7076fc57688019 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 Aug 2012 14:09:40 -0700 Subject: [PATCH 05/15] cloudstack 3.0 UI - autoscale - existing LB - configure AutoScale - fix a JS bug "otherdeployparams is undefined". --- ui/scripts/autoscaler.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index 622f7d43fbd..a53d24656f0 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -137,15 +137,17 @@ var diskOfferingId, securityGroups; var otherdeployparams = autoscaleVmProfile.otherdeployparams; - var array1 = otherdeployparams.split('&'); - $(array1).each(function(){ - var array2 = this.split('='); - if(array2[0] == 'diskofferingid') - diskOfferingId= array2[1]; - if(array2[0] == 'securitygroupids') - securityGroups = array2[1]; - }); - + if(otherdeployparams != null && otherdeployparams.length > 0) { + var array1 = otherdeployparams.split('&'); + $(array1).each(function(){ + var array2 = this.split('='); + if(array2[0] == 'diskofferingid') + diskOfferingId= array2[1]; + if(array2[0] == 'securitygroupids') + securityGroups = array2[1]; + }); + } + var originalAutoscaleData = { templateNames: autoscaleVmProfile.templateid, serviceOfferingId: autoscaleVmProfile.serviceofferingid, From 0cd51eafc3d6f8f9c0b33ed377a53881c4204db7 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 Aug 2012 14:33:16 -0700 Subject: [PATCH 06/15] CS-15836: cloudstack 3.0 UI - autoscale - existing LB - configure AutoScale - fix a bug that root-admin was unable to see autoscale created by regular-user or domain-admin. --- ui/scripts/autoscaler.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index a53d24656f0..280d97f15b2 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -92,6 +92,7 @@ $.ajax({ url: createURL('listAutoScaleVmGroups'), data: { + listAll: true, lbruleid: args.context.multiRules[0].id }, success: function(json) { @@ -100,6 +101,7 @@ $.ajax({ url: createURL('listAutoScaleVmProfiles'), data: { + listAll: true, id: autoscaleVmGroup.vmprofileid }, success: function(json) { From 698097a3ce2a57ab201333a76269e9759fbf2019 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 Aug 2012 15:17:08 -0700 Subject: [PATCH 07/15] cloudstack 3.0 UI - autoscale - configure AutoScale - fix a bug when root-admin tried to update an AutoScale created by regular-user or domain-admin, users dropdown was not correctly populated (should be populated with users under owner account instead of users under current login account). --- ui/scripts/autoscaler.js | 63 ++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index 280d97f15b2..c821fe6b0dd 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -402,25 +402,50 @@ label: 'User', select: function(args) { var items = []; - if(isAdmin() || isDomainAdmin()) { - $.ajax({ - url: createURL('listUsers'), - data: { - domainid: g_domainid, - account: g_account - }, - success: function(json) { - var users = json.listusersresponse.user; - $(users).each(function(){ - items.push({id: this.id, description: this.username}); - }); - args.response.success({ data: items }); - } - }); - } - else { //regular user doesn't have access to listUers API call. - items.push({id: "", description: ""}); - } + if(args.context.originalAutoscaleData == null) { //new LB rule + if(isAdmin() || isDomainAdmin()) { + $.ajax({ + url: createURL('listUsers'), + data: { + domainid: g_domainid, + account: g_account + }, + success: function(json) { + var users = json.listusersresponse.user; + $(users).each(function(){ + items.push({id: this.id, description: this.username}); + }); + args.response.success({ data: items }); + } + }); + } + else { //regular user doesn't have access to listUers API call. + items.push({id: "", description: ""}); + args.response.success({ data: items }); + } + } + else { //existing LB rule + if(isAdmin() || isDomainAdmin()) { + $.ajax({ + url: createURL('listUsers'), + data: { + domainid: args.context.originalAutoscaleData.context.autoscaleVmProfile.domainid, + account: args.context.originalAutoscaleData.context.autoscaleVmProfile.account + }, + success: function(json) { + var users = json.listusersresponse.user; + $(users).each(function(){ + items.push({id: this.id, description: this.username}); + }); + args.response.success({ data: items }); + } + }); + } + else { //regular user doesn't have access to listUers API call. + items.push({id: "", description: ""}); + args.response.success({ data: items }); + } + } } } }, From db3692e4483491201db3d8ba8e0314ba72b66e7f Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Tue, 7 Aug 2012 15:31:56 -0700 Subject: [PATCH 08/15] cloudstack 3.0 UI - autoscale - configure AutoScale - resolve an error returned by updateAutoScaleVmGroup API "Only scaleup policies can be specified in scaleuppolicyids". --- ui/scripts/autoscaler.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js index c821fe6b0dd..17bf976f2c9 100644 --- a/ui/scripts/autoscaler.js +++ b/ui/scripts/autoscaler.js @@ -1246,7 +1246,9 @@ id: args.context.originalAutoscaleData.context.autoscaleVmGroup.id, minmembers: args.data.minInstance, maxmembers: args.data.maxInstance, - interval: args.data.interval + interval: args.data.interval, + scaleuppolicyids: args.context.originalAutoscaleData.scaleUpPolicy.id, + scaledownpolicyids: args.context.originalAutoscaleData.scaleDownPolicy.id }; $.ajax({ From 5c850c9b4ce0ce80eaaed7f1791df0edb0b4484f Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 7 Aug 2012 15:09:45 -0700 Subject: [PATCH 09/15] CS-15892: Tier detail view: Show 'tier details' instead of 'details' --- client/WEB-INF/classes/resources/messages.properties | 1 + ui/index.jsp | 3 +-- ui/scripts/vpc.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 9ce8aa876b5..01088acec92 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -1,4 +1,5 @@ #new labels (begin) ********************************************************************************************** +label.tier.details=Tier details label.edit.tags=Edit tags label.network.rate.megabytes=Network Rate (MB/s) label.action.enable.physical.network=Enable physical network diff --git a/ui/index.jsp b/ui/index.jsp index c15569e7c1f..dc99232207a 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -5,7 +5,6 @@ <% long now = System.currentTimeMillis(); %> - @@ -17,7 +16,6 @@ - @@ -1652,6 +1650,7 @@