Updated Branches:
refs/heads/autoscale f418db25d -> 93e7b86c4
Merge Autoscaler UI implemetation
This change includes the new dialog box for the CloudStack Autoscaler
implementation. It is accessible by a button ('Autoscaler') that
appears under each LB rule.
This also contains changes to the multiEdit widget to support features
required for Autoscaler:
-Fixes context/data passing to custom button widgets
-Fixes data retrieval for select fields
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit:
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/93e7b86c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/93e7b86c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/93e7b86c
Branch: refs/heads/autoscale
Commit: 93e7b86c46368ab29893d7926ea4652bc5d0e177
Parents: f418db2
Author: Brian Federle <[email protected]>
Authored: Mon Jul 30 11:29:43 2012 -0700
Committer: Brian Federle <[email protected]>
Committed: Mon Jul 30 11:29:43 2012 -0700
----------------------------------------------------------------------
ui/css/cloudstack3.css | 225 +++++++-
ui/images/minus.png | Bin 0 -> 1544 bytes
ui/index.jsp | 2 +
ui/scripts/autoscaler.js | 1043 +++++++++++++++++++++++++++++++
ui/scripts/network.js | 764 ++++++++++++-----------
ui/scripts/ui-custom/autoscaler.js | 285 +++++++++
ui/scripts/ui/widgets/multiEdit.js | 33 +-
7 files changed, 1969 insertions(+), 383 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index a60e480..65acf2b 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -9597,6 +9597,229 @@ div.panel.ui-dialog div.list-view div.fixed-header {
overflow: auto;
}
+/*Autoscaler*/
+.ui-dialog div.autoscaler {
+ overflow: auto;
+ max-height: 600px;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=securityGroups]
{
+ display: block;
+ width: 370px;
+ float: left;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=diskOfferingId]
{
+ display: inline-block;
+ width: 370px;
+ float: left;
+ position: relative;
+ margin-top: 1px;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=minInstance] {
+ display: block;
+ width: 50%;
+ float: left;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=maxInstance] {
+ display: inline-block;
+ width: 50%;
+ float: left;
+ left: -30px;
+ position: relative;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=interval] {
+ display: block;
+ width: 50%;
+ float: left;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=quietTime] {
+ display: inline-block;
+ width: 50%;
+ float: left;
+ left: -15px;
+ position: relative;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=snmpCommunity] {
+ display: block;
+ width: 50%;
+ float: left;
+}
+
+.ui-dialog div.autoscaler div.form-container div.form-item[rel=snmpPort] {
+ display: inline-block;
+ width: 50%;
+ float: left;
+ left: -15px;
+ position: relative;
+}
+
+.ui-dialog div.autoscaler div.form-container div.value select {
+ width: 88%;
+ float: left;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container {
+ height: 55px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container {
+ height: 55px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy div.multi-edit {
+ margin-top: 0px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit {
+ margin-top: 0px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title {
+ color: #0055BB;
+ margin-left: -650px;
+ margin-top: 40px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title label {
+ font-size: 13px;
+ margin-left: 200px;
+ margin-right: 10px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title hr.policy-divider {
+ border-left: 1px none #38546D;
+ border-right: 1px none #16222C;
+ border-top: 1px none #38546D;
+ margin-bottom: 12px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title hr.policy-divider {
+ border-left: 1px none #38546D;
+ border-right: 1px none #16222C;
+ border-top: 1px none #38546D;
+ margin-bottom: 12px;
+}
+
+div.ui-dialog div.autoscaler div.field-group.bottom-fields hr.policy-divider {
+ border-left: 1px none #38546D;
+ border-right: 1px none #16222C;
+ border-top: 1px none #38546D;
+ margin-top: 15px;
+ margin-bottom: -1px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title label {
+ font-size: 13px;
+ margin-left: 170px;
+ margin-right: 10px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title {
+ color: #0055BB;
+ margin-left: -620px;
+ margin-top: 10px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container
div.form-item div.value input[type=text] {
+ margin-left: 195px;
+ width: 30%;
+ margin-top: 1px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy-title div.form-container
div.form-item div.name {
+ margin-left: 390px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container
div.form-item div.value input[type=text] {
+ margin-left: 670px;
+ width: 30%;
+ margin-top: -16px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy-title div.form-container
div.form-item div.name {
+ margin-left: 390px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy div.multi-edit div.data
div.data-body div.data-item {
+ margin-bottom: 0px;
+ margin-right: 22px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data
div.data-body div.data-item {
+ margin-bottom: 0px;
+ margin-right: 22px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy div.slide-label {
+ color: #A5A3A7;
+ font-size: 14px;
+ margin-bottom: 3px;
+ margin-left: 755px;
+ width: 12px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label {
+ color: #A5A3A7;
+ font-size: 14px;
+ margin-bottom: 3px;
+ margin-left: 755px;
+ width: 12px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy div.hide {
+ background: #FFFFFF url("../images/minus.png") no-repeat 38% 59%;
+ border: 1px solid #D0D0D0;
+ border-radius: 9px 9px 9px 9px;
+ cursor: pointer;
+ float: right;
+ height: 15px;
+ margin: -20px 45px 0 11px;
+ width: 14px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy div.hide {
+ background: #FFFFFF url("../images/minus.png") no-repeat 31% 54%;
+ border: 1px solid #D0D0D0;
+ border-radius: 9px 9px 9px 9px;
+ cursor: pointer;
+ float: right;
+ height: 15px;
+ margin: -20px 45px 0 11px;
+ width: 14px;
+}
+
+div.ui-dialog div.autoscaler div.scale-up-policy div.expand {
+ background: #FFFFFF url("../images/sprites.png") repeat -541px -499px;
+ border: 1px solid #D0D0D0;
+ border-radius: 9px 9px 9px 9px;
+ cursor: pointer;
+ float: right;
+ height: 15px;
+ margin: -20px 45px 0 11px;
+ width: 14px;
+}
+
+div.ui-dialog div.autoscaler div.scale-down-policy div.expand {
+ background: #FFFFFF url("../images/sprites.png") repeat -541px -499px;
+ border: 1px solid #D0D0D0;
+ border-radius: 9px 9px 9px 9px;
+ cursor: pointer;
+ float: right;
+ height: 15px;
+ margin: -20px 45px 0 11px;
+ width: 14px;
+}
+
+div.ui-dialog div.autoscaler div.field-group div.form-container form
div.form-item div.name label {
+ font-size: 11px;
+}
+
/*Action icons*/
.action.edit .icon {
background-position: 1px -1px;
@@ -9970,4 +10193,4 @@ div.panel.ui-dialog div.list-view div.fixed-header {
.label-hovered {
cursor: pointer;
color: blue !important;
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/images/minus.png
----------------------------------------------------------------------
diff --git a/ui/images/minus.png b/ui/images/minus.png
new file mode 100644
index 0000000..077db99
Binary files /dev/null and b/ui/images/minus.png differ
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/index.jsp
----------------------------------------------------------------------
diff --git a/ui/index.jsp b/ui/index.jsp
index 1ee8f0b..5488eb7 100644
--- a/ui/index.jsp
+++ b/ui/index.jsp
@@ -1636,6 +1636,8 @@
<script type="text/javascript"
src="scripts/ui-custom/projects.js?t=<%=now%>"></script>
<script type="text/javascript"
src="scripts/cloudStack.js?t=<%=now%>"></script>
<script type="text/javascript"
src="scripts/lbStickyPolicy.js?t=<%=now%>"></script>
+ <script type="text/javascript"
src="scripts/ui-custom/autoscaler.js?t=<%=now%>"></script>
+ <script type="text/javascript"
src="scripts/autoscaler.js?t=<%=now%>"></script>
<script type="text/javascript"
src="scripts/ui-custom/zoneChart.js?t=<%=now%>"></script>
<script type="text/javascript"
src="scripts/ui-custom/dashboard.js?t=<%=now%>"></script>
<script type="text/javascript"
src="scripts/installWizard.js?t=<%=now%>"></script>
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/scripts/autoscaler.js
----------------------------------------------------------------------
diff --git a/ui/scripts/autoscaler.js b/ui/scripts/autoscaler.js
new file mode 100644
index 0000000..ff5c542
--- /dev/null
+++ b/ui/scripts/autoscaler.js
@@ -0,0 +1,1043 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+(function($,cloudstack) {
+ var scaleUpData = [];
+ var totalScaleUpCondition = 0;
+ var scaleDownData = [];
+ var totalScaleDownCondition = 0;
+
+ cloudStack.autoscaler = {
+ dataProvider: function(args) {
+ // Reset data
+ scaleUpData = [];
+ totalScaleUpCondition = 0;
+ scaleDownData = [];
+ totalScaleDownCondition = 0;
+
+ var sampleData = null;
+ /*
+ var sampleData = {
+ templateNames: '58d3f4b2-e847-4f93-993d-1ab1505129b6', //(will set this
value to dropdown)
+ serviceOfferingId: '4aa823f3-27ec-46af-9e07-b023d7a7a6f1', //(will set
this value to dropdown)
+ minInstance: 1,
+ maxInstance: 10,
+ scaleUpPolicy: {
+ id: 12345,
+ duration: 1000,
+ conditions: [
+ {
+ id: 1,
+ counterid: 'cpu',
+ relationaloperator: "GE",
+ threshold: 100
+ },
+ {
+ id: 2,
+ counterid: 'memory',
+ relationaloperator: "LT",
+ threshold: 200
+ }
+
+ ]
+ },
+ scaleDownPolicy: {
+ id: 6789,
+ duration: 500,
+ conditions: [
+ {
+ id: 1,
+ counterid: 'cpu',
+ relationaloperator: "LT",
+ threshold: 30
+ },
+ {
+ id: 2,
+ counterid: 'cpu',
+ relationaloperator: "LT",
+ threshold: 50
+ }
+
+ ]
+ },
+ interval: 200,
+ quietTime: 300,
+ destroyVMgracePeriod: null,
+ securityGroups: null, // (will set this value to dropdown)
+ diskOfferingId: 'a21c9aa4-ef7e-41dd-91eb-70b2182816b0', // (will set
this value to dropdown)
+ snmpCommunity: 1,
+ snmpPort: 225,
+
+ isAdvanced: false // Set this to true if any advanced field data is
present
+ };
+ */
+
+ args.response.success({ data: sampleData });
+ },
+
+ // --
+ // Add the following object blocks:
+ //
+ // topFields: { <standard createForm field format> }
+ // bottomFields: { <standard createForm field format> },
+ // scaleUpPolicy: { <standard multiEdit field format> },
+ // scaleDownPolicy: { <standard multiEdit field format> }
+ // --
+ //
+ forms: {
+ topFields: {
+ //**
+ //** Disabled due to UI issues
+ //**
+ // templateCategory: {
+ // label: 'Template',
+ // id: 'templatecategory',
+ // select: function(args) {
+ // args.response.success({
+ // data: [
+ // { id: 'all', description: _l('ui.listView.filters.all') },
+ // { id: 'featured', description: _l('label.featured') },
+ // { id: 'Community', description:
_l('label.menu.community.templates') },
+ // { id: 'self', description: _l('ui.listView.filters.mine') }
+ // ]
+ // });
+ // }
+ // },
+ //**
+
+ templateNames: {
+ label: 'label.template',
+ id: 'templatename',
+ select: function(args) {
+ var templates;
+ var templateIdMap = {};
+ $.ajax({
+ url: createURL('listTemplates'),
+ data: {
+ templatefilter: 'featured',
+ zoneid: args.context.networks[0].zoneid
+ },
+ async: false,
+ success: function(json) {
+ templates = json.listtemplatesresponse.template;
+ if (templates == null)
+ templates = [];
+ $(templates).each(function() {
+ templateIdMap[this.id] = 1;
+ });
+ }
+ });
+
+ $.ajax({
+ url: createURL('listTemplates'),
+ data: {
+ templatefilter: 'community',
+ zoneid: args.context.networks[0].zoneid
+ },
+ async: false,
+ success: function(json) {
+ var items = json.listtemplatesresponse.template;
+ $(items).each(function() {
+ if(!(this.id in templateIdMap)) {
+ templates.push(this);
+ templateIdMap[this.id] = 1;
+ }
+ });
+ }
+ });
+
+ $.ajax({
+ url: createURL('listTemplates'),
+ data: {
+ templatefilter: 'selfexecutable',
+ zoneid: args.context.networks[0].zoneid
+ },
+ async: false,
+ success: function(json) {
+ var items = json.listtemplatesresponse.template;
+ $(items).each(function() {
+ if(!(this.id in templateIdMap)) {
+ templates.push(this);
+ templateIdMap[this.id] = 1;
+ }
+ });
+ }
+ });
+
+ args.response.success({
+ data: $.map(templates, function(template) {
+ return {
+ id: template.id,
+ description: template.name
+ };
+ })
+ });
+ }
+ },
+
+ serviceOfferingId: {
+ label: 'label.compute.offering',
+ select: function(args) {
+ $.ajax({
+ url: createURL("listServiceOfferings&issystem=false"),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var serviceofferings =
json.listserviceofferingsresponse.serviceoffering;
+ args.response.success({
+ data: $.map(serviceofferings, function(serviceoffering) {
+ return {
+ id: serviceoffering.id,
+ description: serviceoffering.name
+ };
+ })
+ });
+ }
+ });
+ }
+ },
+
+ minInstance: {
+ label: 'Min Instances',
+ defaultValue: '3',
+ validation: { required: true }
+ },
+
+ maxInstance: {
+ label: 'Max Instances',
+ defaultValue: '10',
+ validation: { required: true }
+ }
+ },
+
+ bottomFields: {
+ isAdvanced: { isBoolean: true, label: 'Show advanced settings' },
+ interval: {
+ label: 'Polling Interval (in sec)',
+ defaultValue: '30',
+ validation: { required: true }
+ },
+
+ quietTime: {
+ label: 'Quiet Time (in sec)',
+ defaultValue: '300',
+ validation: { required: true }
+ },
+
+ destroyVMgracePeriod: {
+ label: 'Destroy VM Grace Period',
+ defaultValue: '30',
+ isHidden:true,
+ dependsOn:'isAdvanced',
+ validation: { required: true }
+ },
+ securityGroups: {
+ label: 'label.menu.security.groups',
+ isHidden: true,
+ dependsOn: 'isAdvanced',
+ select: function(args) {
+ $.ajax({
+ url: createURL("listSecurityGroups&listAll=true"),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var securitygroups =
json.listsecuritygroupsresponse.securitygroup;
+ var items = [];
+ items.push({id: "", description: ""});
+ $(securitygroups).each(function(){
+ items.push({id: this.id, description: this.name});
+ });
+ args.response.success({ data: items });
+ }
+ });
+ }
+ },
+
+ diskOfferingId: {
+ label: 'label.menu.disk.offerings',
+ isHidden: true,
+ dependsOn: 'isAdvanced',
+ select: function(args) {
+ $.ajax({
+ url: createURL("listDiskOfferings&listAll=true"),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var diskofferings =
json.listdiskofferingsresponse.diskoffering;
+ var items = [];
+ items.push({id: "", description: ""});
+ $(diskofferings).each(function(){
+ items.push({id: this.id, description: this.name});
+ });
+ args.response.success({ data: items });
+ }
+ });
+ }
+ },
+
+ snmpCommunity: {
+ isHidden: true,
+ dependsOn: 'isAdvanced',
+ label: 'SNMP Community',
+ defaultValue: 'public',
+ validation: { required: true }
+ },
+
+ snmpPort: {
+ isHidden: true,
+ dependsOn: 'isAdvanced',
+ label: 'SNMP Port',
+ defaultValue: '161',
+ validation: { required: true }
+ },
+
+ username: {
+ isHidden: true,
+ dependsOn: 'isAdvanced',
+ 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: ""});
+ }
+ }
+ }
+ },
+ scaleUpPolicy: {
+ title: 'ScaleUp Policy',
+ label: 'SCALE UP POLICY',
+ noSelect: true,
+ noHeaderActionsColumn: true,
+ ignoreEmptyFields: true,
+ fields: {
+ 'counterid': {
+ label: 'Counter',
+ select: function(args) {
+ $.ajax({
+ url: createURL("listCounters"),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var counters = json.counterresponse.counter;
+
+ args.response.success({
+ data: $.map(counters, function(counter) {
+ return {
+ name: counter.id,
+ description: counter.name
+ };
+ })
+ });
+ }
+ });
+ }
+ },
+ 'relationaloperator': {
+ label: 'Operator',
+ select: function(args) {
+ args.response.success({
+ data: [
+ { name: 'GT', description: 'greater-than' },
+ { name: 'GE', description: 'greater-than or equals to' },
+ { name: 'LT', description: 'less-than' },
+ { name: 'LE', description: 'less-than or equals to' },
+ { name: 'EQ', description: 'equals-to' }
+ ]
+ });
+ }
+ },
+ 'threshold': { edit: true, label: 'Threshold' },
+ 'add-scaleUpcondition': {
+ label: 'label.add',
+ addButton: true
+ }
+ },
+ add: {
+ label: 'label.add',
+ action: function(args) {
+ scaleUpData.push($.extend(args.data, {
+ index: totalScaleUpCondition
+ }));
+
+ totalScaleUpCondition++;
+ args.response.success();
+ }
+ },
+ actions: {
+ destroy: {
+ label: '',
+ action: function(args) {
+ scaleUpData = $.grep(scaleUpData, function(item) {
+ return item.index != args.context.multiRule[0].index;
+ });
+ totalScaleUpCondition--;
+ args.response.success();
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = scaleUpData;
+ var $autoscaler = $('.ui-dialog .autoscaler');
+ var initialData = $autoscaler.data('autoscaler-scale-up-data');
+
+ if ($.isArray(initialData)) {
+ $(initialData).each(function() {
+ this.index = totalScaleUpCondition;
+ totalScaleUpCondition++;
+ scaleUpData.push(this);
+ });
+
+ $autoscaler.data('autoscaler-scale-up-data', null);
+ }
+
+ args.response.success({
+ data: scaleUpData
+ });
+ }
+ /*actions: {
+ destroy: {
+ label: '',
+ action: function(args) {
+ $.ajax({
+ url: createURL("deleteCondition&id=" +
args.context.multiRule[0].counterid),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ var jobId = data.deleteconditionresponse.jobid;
+
+ args.response.success({
+ _custom: {
+ jobId: jobId
+ }
+ });
+ }
+ });
+ }
+ }
+ },
+ ignoreEmptyFields: true,
+ dataProvider: function(args) {
+ $.ajax({
+ url: createURL('listConditions'),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ args.response.success({
+ data: $.map(
+ data.listconditionsresponse.condition ?
+ data.listconditionsresponse.condition : [],
+ function(elem) {
+ return {
+ counterid: elem.id,
+ relationaloperator: elem.relationaloperator,
+ threshold: elem.threshold
+ };
+ }
+ )
+ });
+ }
+ });
+ }*/
+ },
+
+ scaleDownPolicy: {
+ title: 'ScaleDown Policy',
+ noSelect: true,
+ noHeaderActionsColumn: true,
+ ignoreEmptyFields: true,
+ fields: {
+ 'counterid': {
+ label: 'Counter',
+ select: function(args) {
+ $.ajax({
+ url: createURL("listCounters"),
+ dataType: "json",
+ async: true,
+ success: function(json) {
+ var counters = json.counterresponse.counter;
+
+ args.response.success({
+ data: $.map(counters, function(counter) {
+ return {
+ name: counter.id,
+ description: counter.name
+ };
+ })
+ });
+ }
+ });
+ }
+ },
+ 'relationaloperator': {
+ label: 'Operator',
+ select: function(args) {
+ args.response.success({
+ data: [
+ { name: 'GT', description: 'greater-than' },
+ { name: 'GE', description: 'greater-than or equals to' },
+ { name: 'LT', description: 'less-than' },
+ { name: 'LE', description: 'less-than or equals to' },
+ { name: 'EQ', description: 'equals-to' }
+ ]
+ });
+ }
+ },
+ 'threshold': { edit: true, label: 'Threshold'},
+ 'add-scaleDowncondition': {
+ label: 'label.add',
+ addButton: true
+ }
+ },
+ add: {
+ label: 'label.add',
+ action: function(args) {
+ scaleDownData.push($.extend(args.data, {
+ index: totalScaleDownCondition
+ }));
+ totalScaleDownCondition++;
+ args.response.success();
+ }
+ },
+ actions: {
+ destroy: {
+ label: '',
+ action: function(args) {
+ scaleDownData = $.grep(scaleDownData, function(item) {
+ return item.index != args.context.multiRule[0].index;
+ });
+ totalScaleDownCondition--;
+ args.response.success();
+ }
+ }
+ },
+ dataProvider: function(args) {
+ var data = scaleDownData;
+ var $autoscaler = $('.ui-dialog .autoscaler');
+ var initialData = $autoscaler.data('autoscaler-scale-down-data');
+
+ if ($.isArray(initialData)) {
+ $(initialData).each(function() {
+ this.index = totalScaleDownCondition;
+ totalScaleDownCondition++;
+ scaleDownData.push(this);
+ });
+
+ $autoscaler.data('autoscaler-scale-down-data', null);
+ }
+
+ args.response.success({
+ data: scaleDownData
+ });
+ }
+ /*
+ actions: {
+ destroy: {
+ label: '',
+ action: function(args) {
+ $.ajax({
+ url: createURL("deleteCondition&id=" +
args.context.multiRule[0].counterid),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ var jobId = data.deleteconditionresponse.jobid;
+
+ args.response.success({
+ _custom: {
+ jobId: jobId
+ }
+ });
+ }
+ });
+ }
+ }
+ },
+ ignoreEmptyFields: true,
+ dataProvider: function(args) {
+ $.ajax({
+ url: createURL('listConditions'),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ args.response.success({
+ data: $.map(
+ data.listconditionsresponse.condition ?
+ data.listconditionsresponse.condition : [],
+ function(elem) {
+ return {
+ counterid: elem.id,
+ relationaloperator: elem.relationaloperator,
+ threshold: elem.threshold
+ };
+ }
+ )
+ });
+ }
+ });
+ }*/
+ }
+ },
+
+ actions: {
+ add: function(args) {
+ //validation (begin) *****
+ if(isAdmin() || isDomainAdmin()) { //only admin and domain-admin has
access to listUers API
+ var havingApiKeyAndSecretKey = false;
+ $.ajax({
+ url: createURL('listUsers'),
+ data: {
+ id: args.data.username
+ },
+ async: false,
+ success: function(json) {
+ if(json.listusersresponse.user[0].apikey != null &&
json.listusersresponse.user[0].secretkey != null) {
+ havingApiKeyAndSecretKey = true;
+ }
+ }
+ });
+ if(havingApiKeyAndSecretKey == false) {
+ args.response.error('The selected user in advanced settings does
not have API key or secret key');
+ return;
+ }
+ }
+
+ if(isAdmin()) { //only admin has access to listConfigurations API
+ var hasValidEndpointeUrl = false;
+ $.ajax({
+ url: createURL('listConfigurations'),
+ data: {
+ name: 'endpointe.url'
+ },
+ async: false,
+ success: function(json) {
+ if(json.listconfigurationsresponse.configuration != null) {
+
if(json.listconfigurationsresponse.configuration[0].value.indexOf('localhost')
== -1) {
+ hasValidEndpointeUrl = true;
+ }
+ }
+ }
+ });
+ if(hasValidEndpointeUrl == false) {
+ args.response.error("Global setting endpointe.url has to be set to
the Management Server's API end point");
+ return;
+ }
+ }
+ //validation (end) *****
+
+
+ var scaleVmProfileResponse = [];
+ var loadBalancerResponse = [];
+ var scaleVmGroupResponse = [];
+ var scaleUpConditionIds = [];
+ var scaleDownConditionIds = [];
+
+ var scaleUp = function(args){
+ var scaleUpConditionIds = [];
+ $(scaleUpData).each(function(){
+ var data = {
+ counterid: this.counterid,
+ relationaloperator: this.relationaloperator,
+ threshold: this.threshold
+ };
+ $.ajax({
+ url: createURL('createCondition'),
+ data: data,
+ success: function(json) {
+ var createConditionIntervalID = setInterval(function() {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobid=" +
json.conditionresponse.jobid),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if(result.jobstatus == 0) {
+ return;
+ }
+ else {
+ clearInterval(createConditionIntervalID);
+ if(result.jobstatus == 1) {
+ var item =
json.queryasyncjobresultresponse.jobresult.condition;
+ scaleUpConditionIds.push(item.id);
+ if (scaleUpConditionIds.length ==
scaleUpData.length) {
+ var data = {
+ action: 'scaleup',
+ conditionids: scaleUpConditionIds.join(","),
+ duration: args.data.scaleUpDuration,
+ quiettime: args.data.quietTime
+ };
+ $.ajax({
+ url: createURL('createAutoScalePolicy'),
+ data: data,
+ success: function(json) {
+ var jobId = json.autoscalepolicyresponse.jobid;
+ var createAutoScalePolicyInterval =
setInterval(function(){
+ $.ajax({
+ url:
createURL("queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result =
json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ }
+ else {
+
clearInterval(createAutoScalePolicyInterval);
+ if (result.jobstatus == 1) {
//AutoScalePolicy successfully created
+ var item =
result.jobresult.autoscalepolicy;
+ scaleDown($.extend(args, {
+ scaleUpPolicyResponse: item
+ }));
+ }
+ else if (result.jobstatus == 2) {
+ args.response.error({ message:
_s(result.jobresult.errortext) });
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ }
+ }
+ else if(result.jobstatus == 2) {
+ args.response.error({ message:
_s(result.jobresult.errortext) });
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+ args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ });
+ };
+
+ var scaleDown = function(args){
+ var scaleDownConditionIds = [];
+ $(scaleDownData).each(function(){
+ var data = {
+ counterid: this.counterid,
+ relationaloperator: this.relationaloperator,
+ threshold: this.threshold
+ };
+ $.ajax({
+ url: createURL('createCondition'),
+ data: data,
+ success: function(json) {
+ var createConditionIntervalID = setInterval(function() {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobid=" +
json.conditionresponse.jobid),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if(result.jobstatus == 0) {
+ return;
+ }
+ else {
+ clearInterval(createConditionIntervalID);
+ if(result.jobstatus == 1) {
+ var item =
json.queryasyncjobresultresponse.jobresult.condition;
+ scaleDownConditionIds.push(item.id);
+ if (scaleDownConditionIds.length ==
scaleDownData.length) {
+ var data = {
+ action: 'scaledown',
+ conditionids: scaleDownConditionIds.join(","),
+ duration: args.data.scaleDownDuration,
+ quiettime: args.data.quietTime
+ };
+ $.ajax({
+ url: createURL('createAutoScalePolicy'),
+ data: data,
+ success: function(json) {
+ var jobId = json.autoscalepolicyresponse.jobid;
+ var createAutoScalePolicyInterval =
setInterval(function(){
+ $.ajax({
+ url:
createURL("queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result =
json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ }
+ else {
+
clearInterval(createAutoScalePolicyInterval);
+ if (result.jobstatus == 1) {
//AutoScalePolicy successfully created
+ var item =
result.jobresult.autoscalepolicy;
+ createVmProfile($.extend(args, {
+ scaleDownPolicyResponse: item
+ }));
+ }
+ else if (result.jobstatus == 2) {
+ args.response.error({ message:
_s(result.jobresult.errortext) });
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ }
+ }
+ else if(result.jobstatus == 2) {
+ args.response.error({ message:
_s(result.jobresult.errortext) });
+ }
+ }
+ },
+ error: function(XMLHttpResponse) {
+
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ }, 3000);
+ }
+ });
+ });
+ };
+
+ var createVmProfile = function(args){
+ var array1 = [];
+ array1.push("&zoneid=" + args.context.networks[0].zoneid);
+ array1.push("&templateid=" + args.data.templateNames);
+ array1.push("&serviceofferingid=" + args.data.serviceOfferingId);
+ array1.push("&snmpcommunity=" + args.data.snmpCommunity);
+ array1.push("&snmpport=" + args.data.snmpPort);
+ array1.push("&destroyvmgraceperiod=" +
args.data.destroyVMgracePeriod);
+
+ if(args.data.username != "")
+ array1.push("&autoscaleuserid=" + args.data.username);
+
+ var array2 = [];
+ if(args.data.diskOfferingId != "")
+ array2.push("diskofferingid=" + args.data.diskOfferingId);
+ if(args.data.securityGroups != ""){
+ if(array2.join("") != "")
+ array2.push("&securitygroupids=" + args.data.securityGroups);
+ else
+ array2.push("securitygroupids=" + args.data.securityGroups);
+ }
+ array2 = array2.join("");
+ if(array2 != "")
+ array1.push("&otherdeployparams=" + encodeURIComponent(array2));
+
+ $.ajax({
+ url: createURL('createAutoScaleVmProfile' + array1.join("")),
+ dataType: 'json',
+ async: true,
+ success: function(data) {
+ var jobId = data.autoscalevmprofileresponse.jobid;
+ var autoscaleVmProfileTimer = setInterval(function(){
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ }
+ else {
+ clearInterval(autoscaleVmProfileTimer);
+ if (result.jobstatus == 1) { //VM Profile successfully
created
+ scaleVmProfileResponse =
result.jobresult.autoscalevmprofile;
+ loadBalancer(args);
+ }
+ else if (result.jobstatus == 2) {
+ args.response.error({message:
_s(result.jobresult.errortext)});
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+ args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ };
+
+ var loadBalancer = function(args){
+ var networkid;
+ if('vpc' in args.context) { //from VPC section
+ if(args.data.tier == null) {
+ cloudStack.dialog.notice({ message: 'Tier is required' });
+ return;
+ }
+ networkid = args.data.tier;
+ }
+ else if('networks' in args.context) { //from Guest Network
section
+ networkid = args.context.networks[0].id;
+ }
+ var data = {
+ algorithm: args.formData.algorithm,
+ name: args.formData.name,
+ privateport: args.formData.privateport,
+ publicport: args.formData.publicport,
+ openfirewall: false,
+ networkid: networkid,
+ publicipid: args.context.ipAddresses[0].id
+ };
+
+ $.ajax({
+ url: createURL('createLoadBalancerRule'),
+ dataType: 'json',
+ data: data,
+ async: true,
+ success: function(json) {
+ var jobId = json.createloadbalancerruleresponse.jobid;
+ var loadBalancerTimer = setInterval(function(){
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ }
+ else {
+ clearInterval(loadBalancerTimer);
+ if (result.jobstatus == 1) { //LoadBalancerRule
successfully created
+ loadBalancerResponse = result.jobresult.loadbalancer;
+ autoScaleVmGroup(args);
+ }
+ else if (result.jobstatus == 2) {
+ args.response.error({message:
_s(result.jobresult.errortext)});
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+ args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ };
+
+ var autoScaleVmGroup = function(args){
+ var array1 = [];
+ array1.push("&lbruleid=" + loadBalancerResponse.id);
+ array1.push("&minMembers=" + args.data.minInstance);
+ array1.push("&maxMembers=" + args.data.maxInstance );
+ array1.push("&vmprofileid=" + scaleVmProfileResponse.id);
+ array1.push("&interval=" + args.data.interval);
+ array1.push("&scaleuppolicyids=" + args.scaleUpPolicyResponse.id);
+ array1.push("&scaledownpolicyids=" + args.scaleDownPolicyResponse.id
);
+ $.ajax({
+ url: createURL('createAutoScaleVmGroup' + array1.join("")),
+ dataType: 'json',
+ async: true,
+ success: function(json) {
+ var jobId = json.autoscalevmgroupresponse.jobid;
+ var scaleVmGroupTimer = setInterval(function(){
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId="+jobId),
+ dataType: "json",
+ success: function(json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ }
+ else {
+ clearInterval(scaleVmGroupTimer);
+ if (result.jobstatus == 1) { //autoscale Vm group
successfully created
+ scaleVmGroupResponse =
result.jobresult.autoscalevmgroup;
+ args.response.success();
+ }
+ else if (result.jobstatus == 2) {
+ args.response.error({message:
_s(result.jobresult.errortext)});
+ }
+ }
+ }
+ });
+ }, 3000);
+ },
+ error: function(XMLHttpResponse) {
+ args.response.error(parseXMLHttpResponse(XMLHttpResponse));
+ }
+ });
+ };
+
+ scaleUp(args);
+
+ //setTimeout(function() { args.response.success(); }, 1000);
+ //setTimeout(function() { args.response.error('Error!'); }, 1000);
+ },
+ destroy: function(args) {
+ $.ajax({
+ url: createURL('')
+ });
+ }
+ },
+
+ dialog: function(args) {
+ return function(args) {
+ var context = args.context;
+
+ var $dialog= $('<div>');
+ $dialog.dialog ({
+ title: 'AutoScale Configuration Wizard',
+ closeonEscape: false,
+
+ draggable:true,
+ width: 825 ,
+ height :600,
+ buttons: {
+ 'Cancel': function() {
+ $(this).dialog("close");
+ $('.overlay').remove();
+ },
+
+
+ 'Apply': function() {
+ $(':ui-dialog').remove();
+ $('.overlay').remove();
+ }
+ }
+ }).closest('.ui-dialog').overlay();
+
+ $("buttons").each(function() {
+ $(this).attr('style','float: right');
+ });
+ var $field = $('<div>').addClass('field username');
+ var $input = $('<input>').attr({ name: 'username' });
+ var $inputLabel = $('<label>').html('Username');
+
+ $field.append($input, $inputLabel);
+ $field.appendTo($dialog);
+ }
+ }
+ }
+} (jQuery,cloudStack));