You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bf...@apache.org on 2012/07/30 20:32:09 UTC

[2/2] Merge Autoscaler UI implemetation

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/scripts/network.js
----------------------------------------------------------------------
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
index 0a8f970..812991a 100644
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -37,7 +37,7 @@
       var allowedActions = args.context.actions;
       var disallowedActions = [];
       var item = args.context.item;
-      var status = item.state;   
+      var status = item.state;
 
       if (status == 'Destroyed' ||
           status == 'Releasing' ||
@@ -46,71 +46,71 @@
           status == 'Allocating' ||
           item.account == 'system' ||
           item.issystem == true ) {
-        return [];
+            return [];
+          }
+
+      if(item.networkOfferingConserveMode == false) {
+        /*
+         (1) If IP is SourceNat, no StaticNat/VPN/PortForwarding/LoadBalancer can be enabled/added.
+         */
+        if (item.issourcenat == true){
+          disallowedActions.push('enableStaticNAT');
+          disallowedActions.push('enableVPN');
+        }
+
+        /*
+         (2) If IP is non-SourceNat, show StaticNat/VPN/PortForwarding/LoadBalancer at first.
+         1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
+         2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
+         3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
+         4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
+         */
+        else { //item.issourcenat == false
+          if (item.isstaticnat) { //1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
+            disallowedActions.push('enableVPN');
+          }
+          if (item.vpnenabled) { //2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
+            disallowedActions.push('enableStaticNAT');
+          }
+
+          //3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
+          $.ajax({
+            url: createURL('listPortForwardingRules'),
+            data: {
+              ipaddressid: item.id,
+              listAll: true
+            },
+            dataType: 'json',
+            async: false,
+            success: function(json) {
+              var rules = json.listportforwardingrulesresponse.portforwardingrule;
+              if(rules != null && rules.length > 0) {
+                disallowedActions.push('enableVPN');
+                disallowedActions.push('enableStaticNAT');
+              }
+            }
+          });
+
+          //4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
+          $.ajax({
+            url: createURL('listLoadBalancerRules'),
+            data: {
+              publicipid: item.id,
+              listAll: true
+            },
+            dataType: 'json',
+            async: false,
+            success: function(json) {
+              var rules = json.listloadbalancerrulesresponse.loadbalancerrule;
+              if(rules != null && rules.length > 0) {
+                disallowedActions.push('enableVPN');
+                disallowedActions.push('enableStaticNAT');
+              }
+            }
+          });
+        }
       }
-				
-			if(item.networkOfferingConserveMode == false) {			 
-				/*
-				(1) If IP is SourceNat, no StaticNat/VPN/PortForwarding/LoadBalancer can be enabled/added. 
-				*/
-	      if (item.issourcenat == true){
-					disallowedActions.push('enableStaticNAT');
-					disallowedActions.push('enableVPN');
-				}			
-				
-				/*
-				(2) If IP is non-SourceNat, show StaticNat/VPN/PortForwarding/LoadBalancer at first.
-				1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
-				2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
-				3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
-				4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
-				*/
-				else { //item.issourcenat == false				   
-					if (item.isstaticnat) { //1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
-					  disallowedActions.push('enableVPN');
-					}
-					if (item.vpnenabled) { //2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
-					  disallowedActions.push('enableStaticNAT');
-					}
-								 
-					//3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
-					$.ajax({
-						url: createURL('listPortForwardingRules'),
-						data: {
-							ipaddressid: item.id,
-							listAll: true
-						},
-						dataType: 'json',
-						async: false,
-						success: function(json) {							
-							var rules = json.listportforwardingrulesresponse.portforwardingrule;
-							if(rules != null && rules.length > 0) {
-							  disallowedActions.push('enableVPN');
-								disallowedActions.push('enableStaticNAT'); 
-							}
-						}
-					});	
-										
-					//4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
-					$.ajax({
-						url: createURL('listLoadBalancerRules'),
-						data: {
-							publicipid: item.id,
-							listAll: true
-						},
-						dataType: 'json',
-						async: false,
-						success: function(json) {
-							var rules = json.listloadbalancerrulesresponse.loadbalancerrule;
-							if(rules != null && rules.length > 0) {
-							  disallowedActions.push('enableVPN');
-								disallowedActions.push('enableStaticNAT'); 
-							}
-						}
-					});		
-				}			  				
-			}			
-			
+
       if (item.isstaticnat) {
         disallowedActions.push('enableStaticNAT');
       } else {
@@ -145,7 +145,7 @@
     securityGroups: function(args) {
       var allowedActions = [];
       var isSecurityGroupOwner = isAdmin() || isDomainAdmin() ||
-        args.context.item.account == args.context.users[0].account;
+            args.context.item.account == args.context.users[0].account;
 
       if (isSecurityGroupOwner &&
           args.context.item.state != 'Destroyed' &&
@@ -251,8 +251,8 @@
                   networkOfferingId: {
                     label: 'label.network.offering',
                     validation: { required: true },
-										dependsOn: 'zoneId',
-                    select: function(args) {										 
+                    dependsOn: 'zoneId',
+                    select: function(args) {
                       $.ajax({
                         url: createURL('listNetworkOfferings&zoneid=' + args.zoneId),
                         data: {
@@ -317,16 +317,16 @@
             vlan: { label: 'label.vlan' },
             cidr: { label: 'label.cidr' }
             /*
-            state: {
-              label: 'State',
-                indicator: {
-                'Implemented': 'on',
-                'Setup': 'on',
-                'Allocated': 'on',
-                'Destroyed': 'off'
-              }
-            }
-            */
+             state: {
+             label: 'State',
+             indicator: {
+             'Implemented': 'on',
+             'Setup': 'on',
+             'Allocated': 'on',
+             'Destroyed': 'off'
+             }
+             }
+             */
           },
           dataProvider: function(args) {
             var array1 = [];
@@ -348,7 +348,7 @@
               dataType: 'json',
               async: false,
               success: function(data) {
-                args.response.success({								  
+                args.response.success({
                   data: data.listnetworksresponse.network
                 });
               },
@@ -513,29 +513,29 @@
                 createForm: {
                   title: 'label.restart.network',
                   desc: 'message.restart.network',
-                  preFilter: function(args) {									  
-										var zoneObj;
-										$.ajax({
-										  url: createURL("listZones&id=" + args.context.networks[0].zoneid),
-											dataType: "json",
-											async: false,
-											success: function(json){											  
-											  zoneObj = json.listzonesresponse.zone[0];												
-											}
-										});																				
-										if(zoneObj.networktype == "Basic") {										  								
-											args.$form.find('.form-item[rel=cleanup]').find('input').removeAttr('checked'); //unchecked
-											args.$form.find('.form-item[rel=cleanup]').hide(); //hidden
-										}
-										else {										  												
-											args.$form.find('.form-item[rel=cleanup]').find('input').attr('checked', 'checked'); //checked											
-											args.$form.find('.form-item[rel=cleanup]').css('display', 'inline-block'); //shown
-                    }											
-									},
-									fields: {
+                  preFilter: function(args) {
+                    var zoneObj;
+                    $.ajax({
+                      url: createURL("listZones&id=" + args.context.networks[0].zoneid),
+                      dataType: "json",
+                      async: false,
+                      success: function(json){
+                        zoneObj = json.listzonesresponse.zone[0];
+                      }
+                    });
+                    if(zoneObj.networktype == "Basic") {
+                      args.$form.find('.form-item[rel=cleanup]').find('input').removeAttr('checked'); //unchecked
+                      args.$form.find('.form-item[rel=cleanup]').hide(); //hidden
+                    }
+                    else {
+                      args.$form.find('.form-item[rel=cleanup]').find('input').attr('checked', 'checked'); //checked
+                      args.$form.find('.form-item[rel=cleanup]').css('display', 'inline-block'); //shown
+                    }
+                  },
+                  fields: {
                     cleanup: {
                       label: 'label.clean.up',
-                      isBoolean: true  
+                      isBoolean: true
                     }
                   }
                 },
@@ -545,7 +545,7 @@
                   }
                 },
                 action: function(args) {
-                  var array1 = [];									
+                  var array1 = [];
                   array1.push("&cleanup=" + (args.data.cleanup == "on"));
                   $.ajax({
                     url: createURL("restartNetwork&id=" + args.context.networks[0].id + array1.join("")),
@@ -760,23 +760,23 @@
 
                 tags: cloudStack.api.tags({ resourceType: 'Network', contextId: 'networks' }),
 
-                
-                dataProvider: function(args) {								 					
-								  $.ajax({
-										url: createURL("listNetworks&id=" + args.context.networks[0].id + "&listAll=true"), //pass "&listAll=true" to "listNetworks&id=xxxxxxxx" for now before API gets fixed.
+
+                dataProvider: function(args) {
+                  $.ajax({
+                    url: createURL("listNetworks&id=" + args.context.networks[0].id + "&listAll=true"), //pass "&listAll=true" to "listNetworks&id=xxxxxxxx" for now before API gets fixed.
                     data: { listAll: true },
-										dataType: "json",
-										async: true,
-										success: function(json) {								  
-											var jsonObj = json.listnetworksresponse.network[0];   
-											args.response.success(
-												{
-													actionFilter: cloudStack.actionFilter.guestNetwork,
-													data: jsonObj
-												}
-											);		
-										}
-									});			
+                    dataType: "json",
+                    async: true,
+                    success: function(json) {
+                      var jsonObj = json.listnetworksresponse.network[0];
+                      args.response.success(
+                        {
+                          actionFilter: cloudStack.actionFilter.guestNetwork,
+                          data: jsonObj
+                        }
+                      );
+                    }
+                  });
                 }
               },
 
@@ -845,6 +845,13 @@
                             action: cloudStack.lbStickyPolicy.dialog()
                           }
                         },
+                        'autoScale': {
+                          label: 'AutoScale',
+                          custom: {
+                            buttonLabel: 'label.configure',
+                            action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler)
+                          }
+                        },
                         'add-vm': {
                           label: 'label.add.vms',
                           addButton: true
@@ -965,7 +972,7 @@
         title: 'label.menu.ipaddresses',
         listView: {
           id: 'ipAddresses',
-          label: 'IPs',          
+          label: 'IPs',
           fields: {
             ipaddress: {
               label: 'IP',
@@ -978,8 +985,8 @@
               }
             },
             zonename: { label: 'label.zone' },
-            //vlanname: { label: 'VLAN' },   					  
-						virtualmachinedisplayname: { label: 'label.vm.name' },						 
+            //vlanname: { label: 'VLAN' },
+            virtualmachinedisplayname: { label: 'label.vm.name' },
             state: {
               converter: function(str) {
                 // For localization
@@ -1234,14 +1241,14 @@
               },
               enableStaticNAT: {
                 label: 'label.action.enable.static.NAT',
-                
+
                 action: {
                   noAdd: true,
                   custom: cloudStack.uiCustom.enableStaticNAT({
                     // VPC
                     tierSelect: function(args) {
                       args.$tierSelect.hide(); // Hidden by default
-                      
+
                       // Determine if tiers are supported here
                       var enableTiers = false;
 
@@ -1270,9 +1277,9 @@
                             $.extend(data, {
                               account: args.context.ipAddresses[0].account,
                               domainid: args.context.ipAddresses[0].domainid
-                            }); 
+                            });
                           }
-                          
+
                           $.ajax({
                             url: createURL('listVirtualMachines'),
                             data: data,
@@ -1437,38 +1444,38 @@
             tabs: {
               details: {
                 title: 'label.details',
-								
-								preFilter: function(args) {
-								  var hiddenFields = [];								
-									var zoneObj;
-									$.ajax({
-									  url: createURL("listZones&id=" + args.context.ipAddresses[0].zoneid),
-										dataType: "json",
-										async: false,
-										success: function(json) {										  
-											zoneObj = json.listzonesresponse.zone[0];											
-										}
-									});							
-									if(zoneObj.networktype == "Advanced") {
-									  hiddenFields.push("issystem");
-										hiddenFields.push("purpose");
-									}																	
-									return hiddenFields;								
-								},
-								
+
+                preFilter: function(args) {
+                  var hiddenFields = [];
+                  var zoneObj;
+                  $.ajax({
+                    url: createURL("listZones&id=" + args.context.ipAddresses[0].zoneid),
+                    dataType: "json",
+                    async: false,
+                    success: function(json) {
+                      zoneObj = json.listzonesresponse.zone[0];
+                    }
+                  });
+                  if(zoneObj.networktype == "Advanced") {
+                    hiddenFields.push("issystem");
+                    hiddenFields.push("purpose");
+                  }
+                  return hiddenFields;
+                },
+
                 fields: [
                   {
                     ipaddress: { label: 'IP' }
                   },
                   {
-                    id: { label: 'label.id' },    
+                    id: { label: 'label.id' },
                     networkid: { label: 'label.network.id' },
                     associatednetworkid: { label: 'label.associated.network.id' },
                     state: { label: 'label.state' },
                     issourcenat: { label: 'label.source.nat', converter: cloudStack.converters.toBooleanText },
                     isstaticnat: { label: 'label.static.nat', converter: cloudStack.converters.toBooleanText },
                     issystem: { label: 'label.is.system', converter: cloudStack.converters.toBooleanText }, //(basic zone only)
-										purpose: { label: 'label.purpose' }, //(basic zone only) When an IP is system-generated, the purpose it serves can be Lb or static nat.
+                    purpose: { label: 'label.purpose' }, //(basic zone only) When an IP is system-generated, the purpose it serves can be Lb or static nat.
                     virtualmachinedisplayname: { label: 'label.vm.name' },
                     domain: { label: 'label.domain' },
                     account: { label: 'label.account' },
@@ -1476,7 +1483,7 @@
                     vlanname: { label: 'label.vlan' }
                   }
                 ],
- 
+
                 tags: cloudStack.api.tags({ resourceType: 'PublicIpAddress', contextId: 'ipAddresses' }),
 
                 dataProvider: function(args) {
@@ -1485,47 +1492,47 @@
                   // Get network data
                   $.ajax({
                     url: createURL('listPublicIpAddresses'),
-                    data: {                      
+                    data: {
                       id: args.context.ipAddresses[0].id
                     },
                     dataType: "json",
                     async: true,
                     success: function(json) {
-                      var ipObj = items[0];	
-											$.ajax({
-												url: createURL('listNetworkOfferings'),
-												data: {
-													id: args.context.networks[0].networkofferingid
-												},
-												dataType: 'json',
-												async: true,
-												success: function(json) {		
-													var networkOfferingObj = json.listnetworkofferingsresponse.networkoffering[0];
-													ipObj.networkOfferingConserveMode= networkOfferingObj.conservemode; 
-																									
-													// Get VPN data
-													$.ajax({
-														url: createURL('listRemoteAccessVpns'),
-														data: {
-															listAll: true,
-															publicipid: ipObj.id
-														},
-														dataType: 'json',
-														async: true,
-														success: function(vpnResponse) {
-															var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count;
-															if (isVPNEnabled) {
-																ipObj.vpnenabled = true;
-																ipObj.remoteaccessvpn = vpnResponse.listremoteaccessvpnsresponse.remoteaccessvpn[0];
-															};
-															args.response.success({
-																actionFilter: actionFilters.ipAddress,
-																data: ipObj
-															});
-														}
-													});													
-												}
-											});					
+                      var ipObj = items[0];
+                      $.ajax({
+                        url: createURL('listNetworkOfferings'),
+                        data: {
+                          id: args.context.networks[0].networkofferingid
+                        },
+                        dataType: 'json',
+                        async: true,
+                        success: function(json) {
+                          var networkOfferingObj = json.listnetworkofferingsresponse.networkoffering[0];
+                          ipObj.networkOfferingConserveMode= networkOfferingObj.conservemode;
+
+                          // Get VPN data
+                          $.ajax({
+                            url: createURL('listRemoteAccessVpns'),
+                            data: {
+                              listAll: true,
+                              publicipid: ipObj.id
+                            },
+                            dataType: 'json',
+                            async: true,
+                            success: function(vpnResponse) {
+                              var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count;
+                              if (isVPNEnabled) {
+                                ipObj.vpnenabled = true;
+                                ipObj.remoteaccessvpn = vpnResponse.listremoteaccessvpnsresponse.remoteaccessvpn[0];
+                              };
+                              args.response.success({
+                                actionFilter: actionFilters.ipAddress,
+                                data: ipObj
+                              });
+                            }
+                          });
+                        }
+                      });
                     },
                     error: function(data) {
                       args.response.error(parseXMLHttpResponse(data));
@@ -1563,70 +1570,70 @@
                         });
                       }
                     });
-																				
-										if(args.context.ipAddresses[0].networkOfferingConserveMode == false) {			 
-											/*
-											(1) If IP is SourceNat, no StaticNat/VPN/PortForwarding/LoadBalancer can be enabled/added. 
-											*/
-											if (args.context.ipAddresses[0].issourcenat){
-											  disallowedActions.push("portForwarding");			
-											  disallowedActions.push("loadBalancing");											  									
-											}
-											
-											/*
-											(2) If IP is non-SourceNat, show StaticNat/VPN/PortForwarding/LoadBalancer at first.
-											1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
-											2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
-											3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
-											4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
-											*/
-											else { //args.context.ipAddresses[0].issourcenat == false				   
-												if (args.context.ipAddresses[0].isstaticnat) { //1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
-												  disallowedActions.push("portForwarding");
-													disallowedActions.push("loadBalancing");
-												}
-												if (args.context.ipAddresses[0].vpnenabled) { //2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
-													disallowedActions.push("portForwarding");
-													disallowedActions.push("loadBalancing"); 
-												}
-																																					 
-												//3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
-												$.ajax({
-													url: createURL('listPortForwardingRules'),
-													data: {
-														ipaddressid: args.context.ipAddresses[0].id,
-														listAll: true
-													},
-													dataType: 'json',
-													async: false,
-													success: function(json) {
-														// Get instance
-														var rules = json.listportforwardingrulesresponse.portforwardingrule;
-														if(rules != null && rules.length > 0) {																
-															disallowedActions.push("loadBalancing"); 
-														}
-													}
-												});								
-												
-												//4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
-												$.ajax({
-													url: createURL('listLoadBalancerRules'),
-													data: {
-														publicipid: args.context.ipAddresses[0].id,
-														listAll: true
-													},
-													dataType: 'json',
-													async: false,
-													success: function(json) {
-														var rules = json.listloadbalancerrulesresponse.loadbalancerrule;
-														if(rules != null && rules.length > 0) {
-															disallowedActions.push("portForwarding");
-														}
-													}
-												});															
-											}						
-										}
-																				
+
+                    if(args.context.ipAddresses[0].networkOfferingConserveMode == false) {
+                      /*
+                       (1) If IP is SourceNat, no StaticNat/VPN/PortForwarding/LoadBalancer can be enabled/added.
+                       */
+                      if (args.context.ipAddresses[0].issourcenat){
+                        disallowedActions.push("portForwarding");
+                        disallowedActions.push("loadBalancing");
+                      }
+
+                      /*
+                       (2) If IP is non-SourceNat, show StaticNat/VPN/PortForwarding/LoadBalancer at first.
+                       1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
+                       2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
+                       3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
+                       4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
+                       */
+                      else { //args.context.ipAddresses[0].issourcenat == false
+                        if (args.context.ipAddresses[0].isstaticnat) { //1. Once StaticNat is enabled, hide VPN/PortForwarding/LoadBalancer.
+                          disallowedActions.push("portForwarding");
+                          disallowedActions.push("loadBalancing");
+                        }
+                        if (args.context.ipAddresses[0].vpnenabled) { //2. Once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer.
+                          disallowedActions.push("portForwarding");
+                          disallowedActions.push("loadBalancing");
+                        }
+
+                        //3. Once a PortForwarding rule is added, hide StaticNat/VPN/LoadBalancer.
+                        $.ajax({
+                          url: createURL('listPortForwardingRules'),
+                          data: {
+                            ipaddressid: args.context.ipAddresses[0].id,
+                            listAll: true
+                          },
+                          dataType: 'json',
+                          async: false,
+                          success: function(json) {
+                            // Get instance
+                            var rules = json.listportforwardingrulesresponse.portforwardingrule;
+                            if(rules != null && rules.length > 0) {
+                              disallowedActions.push("loadBalancing");
+                            }
+                          }
+                        });
+
+                        //4. Once a LoadBalancer rule is added, hide StaticNat/VPN/PortForwarding.
+                        $.ajax({
+                          url: createURL('listLoadBalancerRules'),
+                          data: {
+                            publicipid: args.context.ipAddresses[0].id,
+                            listAll: true
+                          },
+                          dataType: 'json',
+                          async: false,
+                          success: function(json) {
+                            var rules = json.listloadbalancerrulesresponse.loadbalancerrule;
+                            if(rules != null && rules.length > 0) {
+                              disallowedActions.push("portForwarding");
+                            }
+                          }
+                        });
+                      }
+                    }
+
                     if(networkOfferingHavingFirewallService == false)
                       disallowedActions.push("firewall");
                     if(networkOfferingHavingPortForwardingService == false)
@@ -1833,111 +1840,111 @@
 
                   vmDetails: cloudStack.sections.instances.listView.detailView,
 
-									
-									//"NAT Port Range" multiEdit screen for StaticNAT is obsolete in cloudstack 3.0 because createIpForwardingRule/deleteIpForwardingRule/listIpForwardingRules API are obsolete in cloudstack 3.0.
-									//cloudstack 3.0 is using createFirewallRule/listFirewallRules/deleteFirewallRule API for both staticNAT and non-staticNAT .
-									/*
-                  staticNAT: {
-                    noSelect: true,
-                    fields: {
-                      'protocol': {
-                        label: 'label.protocol',
-                        select: function(args) {
-                          args.response.success({
-                            data: [
-                              { name: 'tcp', description: 'TCP' },
-                              { name: 'udp', description: 'UDP' }
-                            ]
-                          });
-                        }
-                      },
-                      'startport': { edit: true, label: 'label.start.port' },
-                      'endport': { edit: true, label: 'label.end.port' },
-                      'add-rule': {
-                        label: 'label.add.rule',
-                        addButton: true
-                      }
-                    },
-                    add: {
-                      label: 'label.add',
-                      action: function(args) {
-                        $.ajax({
-                          url: createURL('createIpForwardingRule'),
-                          data: $.extend(args.data, {
-                            ipaddressid: args.context.ipAddresses[0].id
-                          }),
-                          dataType: 'json',
-                          success: function(data) {
-                            args.response.success({
-                              _custom: {
-                                jobId: data.createipforwardingruleresponse.jobid
-                              },
-                              notification: {
-                                label: 'label.add.static.nat.rule',
-                                poll: pollAsyncJobResult
-                              }
-                            });
-                          },
-                          error: function(data) {
-                            args.response.error(parseXMLHttpResponse(data));
-                          }
-                        });
-                      }
-                    },
-                    actions: {
-                      destroy: {
-                        label: 'label.remove.rule',
-                        action: function(args) {
-                          $.ajax({
-                            url: createURL('deleteIpForwardingRule'),
-                            data: {
-                              id: args.context.multiRule[0].id
-                            },
-                            dataType: 'json',
-                            async: true,
-                            success: function(data) {
-                              var jobID = data.deleteipforwardingruleresponse.jobid;
-                              args.response.success({
-                                _custom: {
-                                  jobId: jobID
-                                },
-                                notification: {
-                                  label: 'label.remove.static.nat.rule',
-                                  poll: pollAsyncJobResult
-                                }
-                              });
-                            },
-                            error: function(data) {
-                              args.response.error(parseXMLHttpResponse(data));
-                            }
-                          });
-                        }
-                      }
-                    },
-                    dataProvider: function(args) {
-                      setTimeout(function() {
-                        $.ajax({
-                          url: createURL('listIpForwardingRules'),
-                          data: {
-                            listAll: true,
-                            ipaddressid: args.context.ipAddresses[0].id
-                          },
-                          dataType: 'json',
-                          async: true,
-                          success: function(data) {
-                            args.response.success({
-                              data: data.listipforwardingrulesresponse.ipforwardingrule
-                            });
-                          },
-                          error: function(data) {
-                            args.response.error(parseXMLHttpResponse(data));
-                          }
-                        });
-                      }, 100);
-                    }
-                  },
-									*/
-									
+
+                  //"NAT Port Range" multiEdit screen for StaticNAT is obsolete in cloudstack 3.0 because createIpForwardingRule/deleteIpForwardingRule/listIpForwardingRules API are obsolete in cloudstack 3.0.
+                  //cloudstack 3.0 is using createFirewallRule/listFirewallRules/deleteFirewallRule API for both staticNAT and non-staticNAT .
+                  /*
+                   staticNAT: {
+                   noSelect: true,
+                   fields: {
+                   'protocol': {
+                   label: 'label.protocol',
+                   select: function(args) {
+                   args.response.success({
+                   data: [
+                   { name: 'tcp', description: 'TCP' },
+                   { name: 'udp', description: 'UDP' }
+                   ]
+                   });
+                   }
+                   },
+                   'startport': { edit: true, label: 'label.start.port' },
+                   'endport': { edit: true, label: 'label.end.port' },
+                   'add-rule': {
+                   label: 'label.add.rule',
+                   addButton: true
+                   }
+                   },
+                   add: {
+                   label: 'label.add',
+                   action: function(args) {
+                   $.ajax({
+                   url: createURL('createIpForwardingRule'),
+                   data: $.extend(args.data, {
+                   ipaddressid: args.context.ipAddresses[0].id
+                   }),
+                   dataType: 'json',
+                   success: function(data) {
+                   args.response.success({
+                   _custom: {
+                   jobId: data.createipforwardingruleresponse.jobid
+                   },
+                   notification: {
+                   label: 'label.add.static.nat.rule',
+                   poll: pollAsyncJobResult
+                   }
+                   });
+                   },
+                   error: function(data) {
+                   args.response.error(parseXMLHttpResponse(data));
+                   }
+                   });
+                   }
+                   },
+                   actions: {
+                   destroy: {
+                   label: 'label.remove.rule',
+                   action: function(args) {
+                   $.ajax({
+                   url: createURL('deleteIpForwardingRule'),
+                   data: {
+                   id: args.context.multiRule[0].id
+                   },
+                   dataType: 'json',
+                   async: true,
+                   success: function(data) {
+                   var jobID = data.deleteipforwardingruleresponse.jobid;
+                   args.response.success({
+                   _custom: {
+                   jobId: jobID
+                   },
+                   notification: {
+                   label: 'label.remove.static.nat.rule',
+                   poll: pollAsyncJobResult
+                   }
+                   });
+                   },
+                   error: function(data) {
+                   args.response.error(parseXMLHttpResponse(data));
+                   }
+                   });
+                   }
+                   }
+                   },
+                   dataProvider: function(args) {
+                   setTimeout(function() {
+                   $.ajax({
+                   url: createURL('listIpForwardingRules'),
+                   data: {
+                   listAll: true,
+                   ipaddressid: args.context.ipAddresses[0].id
+                   },
+                   dataType: 'json',
+                   async: true,
+                   success: function(data) {
+                   args.response.success({
+                   data: data.listipforwardingrulesresponse.ipforwardingrule
+                   });
+                   },
+                   error: function(data) {
+                   args.response.error(parseXMLHttpResponse(data));
+                   }
+                   });
+                   }, 100);
+                   }
+                   },
+                   */
+
 
                   // Load balancing rules
                   loadBalancing: {
@@ -1945,7 +1952,7 @@
                       listView: {
                         dataProvider: function(args) {
                           var itemData = $.isArray(args.context.multiRule) && args.context.multiRule[0]['_itemData'] ?
-                            args.context.multiRule[0]['_itemData'] : [];
+                                args.context.multiRule[0]['_itemData'] : [];
                           var data = {
                             page: args.page,
                             pageSize: pageSize,
@@ -1957,7 +1964,7 @@
                             $.extend(data, {
                               account: args.context.ipAddresses[0].account,
                               domainid: args.context.ipAddresses[0].domainid
-                            }); 
+                            });
                           }
 
                           $.ajax({
@@ -2031,6 +2038,14 @@
                           action: cloudStack.lbStickyPolicy.dialog()
                         }
                       },
+                      'autoScale': {
+                        label: 'AutoScale',
+                        custom: {
+                          buttonLabel: 'label.configure',
+                          action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler)
+                        }
+                      },
+
                       'add-vm': {
                         label: 'label.add.vms',
                         addButton: true
@@ -2053,9 +2068,9 @@
 
                         var apiCmd = "createLoadBalancerRule";
                         //if(args.context.networks[0].type == "Shared")
-                          //apiCmd += "&domainid=" + g_domainid + "&account=" + g_account;
+                        //apiCmd += "&domainid=" + g_domainid + "&account=" + g_account;
                         //else //args.context.networks[0].type == "Isolated"
-                          apiCmd += "&publicipid=" + args.context.ipAddresses[0].id;
+                        apiCmd += "&publicipid=" + args.context.ipAddresses[0].id;
 
                         $.ajax({
                           url: createURL(apiCmd),
@@ -2147,7 +2162,7 @@
                                 }
                               });
                             }
-                          });             
+                          });
                         }
                       },
                       destroy:  {
@@ -2243,10 +2258,10 @@
 
                       $.ajax({
                         url: createURL('listLoadBalancerRules'),
-												data: {
-												  publicipid: args.context.ipAddresses[0].id,
-													listAll: true
-												},
+                        data: {
+                          publicipid: args.context.ipAddresses[0].id,
+                          listAll: true
+                        },
                         dataType: 'json',
                         async: true,
                         success: function(data) {
@@ -2270,7 +2285,7 @@
                               },
                               success: function(json) {
                                 var stickyPolicy = json.listlbstickinesspoliciesresponse.stickinesspolicies ?
-                                  json.listlbstickinesspoliciesresponse.stickinesspolicies[0].stickinesspolicy : null;
+                                      json.listlbstickinesspoliciesresponse.stickinesspolicies[0].stickinesspolicy : null;
 
                                 if (stickyPolicy && stickyPolicy.length) {
                                   stickyPolicy = stickyPolicy[0];
@@ -2306,7 +2321,7 @@
                                 id: item.id
                               },
                               success: function(data) {
-                                lbInstances = data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance ? 
+                                lbInstances = data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance ?
                                   data.listloadbalancerruleinstancesresponse.loadbalancerruleinstance : [];
                               },
                               error: function(data) {
@@ -2320,13 +2335,16 @@
                                 return $.extend(vm, {
                                   _displayName: vm.id == vm.displayname ?
                                     (vm.instancename ? vm.instancename : vm.name)
-                                    : vm.displayname
+                                  : vm.displayname
                                 });
                               }),
                               _maxLength: {
                                 name: 7
                               },
-                              sticky: stickyData
+                              sticky: stickyData,
+                              autoScale: {
+                                lbRuleID: item.id
+                              }
                             });
                           });
 
@@ -2379,7 +2397,7 @@
                             $.extend(data, {
                               account: args.context.ipAddresses[0].account,
                               domainid: args.context.ipAddresses[0].domainid
-                            }); 
+                            });
                           }
 
                           $.ajax({
@@ -2517,7 +2535,7 @@
                     },
                     dataProvider: function(args) {
                       var $multi = args.$multi;
-                      
+
                       $.ajax({
                         url: createURL('listPortForwardingRules'),
                         data: {
@@ -2535,7 +2553,7 @@
 
                           $(portForwardingData).each(function() {
                             var item = this;
-                            
+
                             item._itemName = '_displayName';
 
                             $.ajax({
@@ -2623,9 +2641,9 @@
                           $.ajax({
                             url: createURL('addVpnUser'),
                             data: $.extend(args.data, {
-															domainid: args.context.ipAddresses[0].domainid,
-															account: args.context.ipAddresses[0].account
-														}),
+                              domainid: args.context.ipAddresses[0].domainid,
+                              account: args.context.ipAddresses[0].account
+                            }),
                             dataType: 'json',
                             success: function(data) {
                               args.response.success({
@@ -2986,7 +3004,7 @@
                       success: function(data) {
                         args.response.success({
                           data: $.map(
-                            data.listsecuritygroupsresponse.securitygroup[0].ingressrule ? 
+                            data.listsecuritygroupsresponse.securitygroup[0].ingressrule ?
                               data.listsecuritygroupsresponse.securitygroup[0].ingressrule : [],
                             function(elem) {
                               return {
@@ -3163,7 +3181,7 @@
                       success: function(data) {
                         args.response.success({
                           data: $.map(
-                            data.listsecuritygroupsresponse.securitygroup[0].egressrule ? 
+                            data.listsecuritygroupsresponse.securitygroup[0].egressrule ?
                               data.listsecuritygroupsresponse.securitygroup[0].egressrule : [],
                             function(elem) {
                               return {
@@ -3226,5 +3244,5 @@
       }
     }
   };
-		
+
 })(cloudStack, jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/scripts/ui-custom/autoscaler.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/autoscaler.js b/ui/scripts/ui-custom/autoscaler.js
new file mode 100644
index 0000000..4412a51
--- /dev/null
+++ b/ui/scripts/ui-custom/autoscaler.js
@@ -0,0 +1,285 @@
+// 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) {
+  cloudStack.uiCustom.autoscaler = function(args) {
+    // Place outer args here as local variables
+    // i.e, -- var dataProvider = args.dataProvider
+    var forms = $.extend(true, {}, args.forms);
+    var topfields = forms.topFields;
+    var bottomfields = forms.bottomFields;
+    var scaleuppolicy = forms.scaleUpPolicy;
+    var scaledownpolicy = forms.scaleDownPolicy;
+    var dataProvider = cloudStack.autoscaler.dataProvider;
+
+    return function(args) {
+      var context = args.data ?
+            $.extend(true, {}, args.context, {
+              lbRules: [args.data]
+            }) : args.context;
+      var formData = args.formData;
+      var $autoscalerDialog = $('<div>').addClass('autoscaler');
+      var $topFields = $('<div>').addClass('field-group top-fields');
+      var $bottomFields = $('<div>').addClass('field-group bottom-fields');
+      var $scaleUpPolicy = $('<div>').addClass('scale-up-policy');
+      var $slideScaleUp = $('<div></div>').addClass('expand');
+      var $hideScaleUp = $('<div></div>').addClass('hide');
+      var $scaleUpLabel= $('<div>Show</div>').addClass('slide-label');
+      var $scaleUpHideLabel=$('<div>Hide</div>').addClass('slide-label');
+      var $scaleDownHideLabel=$('<div>Hide</div>').addClass('slide-label');
+      var $scaleDownLabel=$('<div>Show</div>').addClass('slide-label');
+      var $slideScaleDown = $('<div></div>').addClass('expand');
+      var $hideScaleDown = $('<div></div>').addClass('hide');
+      var $scaleUpDivider = $('<hr></hr>').addClass('policy-divider');
+      var $scaleDownDivider = $('<hr></hr>').addClass('policy-divider');
+      var $bottomFieldDivider = $('<hr></hr>').addClass('policy-divider');
+      var $scaleDownPolicy = $('<div>').addClass('scale-down-policy');
+      var $scaleUpPolicyTitle = $('<div>').addClass('scale-up-policy-title')
+            .html("Scale Up Policy");
+      var $scaleDownPolicyTitle = $('<div>').addClass('scale-down-policy-title')
+            .html("Scale Down Policy");
+      var topFieldForm, $topFieldForm,
+          bottomFieldForm, $bottomFieldForm,
+          scaleUpPolicyTitleForm, $scaleUpPolicyTitleForm,
+          scaleDownPolicyTitleForm, $scaleDownPolicyTitleForm,
+          scaleUpPolicyForm, scaleDownPolicyForm;
+
+      var renderDialogContent = function(args) {
+        var data = args.data ? args.data : {};
+
+        // Setup default values, in case where existing data is present
+        var setDefaultFields = function(fieldID, field) {
+          var fieldData = data[fieldID];
+
+          if (fieldData && !field.isBoolean) {
+            field.defaultValue = fieldData;
+          } else {
+            field.isChecked = fieldData;
+          }
+        };
+        $.each(topfields, setDefaultFields);
+        $.each(bottomfields, setDefaultFields);
+
+        // Create and append top fields
+        // -- uses create form to generate fields
+        topFieldForm = cloudStack.dialog.createForm({
+          context: context,
+          noDialog: true, // Don't render a dialog, just return $formContainer
+          form: {
+            title: '',
+            fields: topfields
+          }
+        });
+        $topFieldForm = topFieldForm.$formContainer;
+        $topFieldForm.appendTo($topFields);
+
+        scaleUpPolicyTitleForm = cloudStack.dialog.createForm({
+          context: context,
+          noDialog: true,
+          form: {
+            title: '',
+            fields: {
+              scaleUpDuration: { label: 'Duration', validation: { required: true } }
+            }
+          }
+        });
+        $scaleUpPolicyTitleForm = scaleUpPolicyTitleForm.$formContainer;
+        $scaleUpPolicyTitleForm.appendTo($scaleUpPolicyTitle);
+
+
+        scaleDownPolicyTitleForm = cloudStack.dialog.createForm({
+          context: context,
+          noDialog: true,
+          form: {
+            title: '',
+            fields: {
+              scaleDownDuration: { label: 'Duration', validation: { required: true } }
+            }
+          }
+        });
+        $scaleDownPolicyTitleForm = scaleDownPolicyTitleForm.$formContainer;
+        $scaleDownPolicyTitleForm.appendTo($scaleDownPolicyTitle);
+
+        // Make multi-edits
+        //
+        // Scale up policy
+        if (data.scaleUpPolicy && $.isArray(data.scaleUpPolicy.conditions)) {
+          $autoscalerDialog.data('autoscaler-scale-up-data',
+                                 data.scaleUpPolicy.conditions);
+        }
+
+        if (data.scaleUpPolicy && data.scaleUpPolicy.duration) {
+          $scaleUpPolicyTitleForm.find('input[name=scaleUpDuration]').val(
+            data.scaleUpPolicy.duration
+          );
+        }
+
+        scaleuppolicy.context = context;
+        scaleUpPolicyForm = $scaleUpPolicy.multiEdit(scaleuppolicy);
+
+        // Scale down policy
+        if (data.scaleDownPolicy && $.isArray(data.scaleDownPolicy.conditions)) {
+          $autoscalerDialog.data('autoscaler-scale-down-data',
+                                 data.scaleDownPolicy.conditions);
+        }
+
+        if (data.scaleDownPolicy && data.scaleDownPolicy.duration) {
+          $scaleDownPolicyTitleForm.find('input[name=scaleDownDuration]').val(
+            data.scaleDownPolicy.duration
+          );
+        }
+
+        scaledownpolicy.context = context;
+        scaleDownPolicyForm = $scaleDownPolicy.multiEdit(scaledownpolicy);
+
+        // Create and append bottom fields
+        bottomFieldForm = cloudStack.dialog.createForm({
+          context: context,
+          noDialog: true, // Don't render a dialog, just return $formContainer
+          form: {
+            title: '',
+            fields: bottomfields
+          }
+        });
+        $bottomFieldForm = bottomFieldForm.$formContainer;
+        $bottomFieldForm.appendTo($bottomFields);
+
+        // Append main div elements
+        $autoscalerDialog.append(
+          $topFields,
+          $scaleUpPolicyTitle,
+          $scaleUpPolicy,
+          $scaleDownPolicyTitle,
+          $scaleDownPolicy,
+          $bottomFields
+        );
+
+        // Render dialog
+        //$autoscalerDialog.find('.form-item[rel=templateNames] label').hide();
+        /* Duration Fields*/
+        //$('div.ui-dialog div.autoscaler').find('div.scale-up-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
+        //$('div.ui-dialog div.autoscaler').find('div.scale-down-policy-title').append("<br></br>").append($inputLabel = $('<label>').html('Duration').attr({left:'200'})).append($('<input>').attr({ name: 'username' }));
+
+        /*Dividers*/
+        $autoscalerDialog.find('div.scale-up-policy-title').prepend($scaleUpDivider);
+        $autoscalerDialog.find('div.scale-down-policy-title').prepend($scaleDownDivider);
+        $autoscalerDialog.find('div.field-group.bottom-fields').prepend($bottomFieldDivider);
+
+        /* Hide effects for multi-edit table*/
+        $autoscalerDialog.find('div.scale-up-policy').prepend($hideScaleUp);
+        $autoscalerDialog.find('div.scale-down-policy ').prepend($hideScaleDown);
+        $autoscalerDialog.find('div.scale-up-policy').prepend($scaleUpHideLabel);
+        $autoscalerDialog.find('div.scale-down-policy').prepend($scaleDownHideLabel);
+
+        /*Toggling the labels and data-item table - SCALE UP POLICY*/
+        $autoscalerDialog.find('div.scale-up-policy div.hide').click(function() {
+          $autoscalerDialog.find('div.scale-up-policy div.multi-edit div.data-item').slideToggle();
+          $scaleUpLabel = $autoscalerDialog.find('div.scale-up-policy div.slide-label').replaceWith($scaleUpLabel);
+        });
+
+        /*Toggling the images */
+        $('div.ui-dialog div.autoscaler div.scale-up-policy div.hide').click(function() {
+          $(this).toggleClass('expand hide');
+        });
+
+        $('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
+          $(this).toggleClass('expand hide');
+        });
+
+        /*Toggling the labels and data-item table - SCALE DOWN POLICY*/
+        $('div.ui-dialog div.autoscaler div.scale-down-policy div.hide').click(function() {
+          $('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle();
+          $scaleDownLabel = $('div.ui-dialog div.autoscaler div.scale-down-policy div.slide-label').replaceWith($scaleDownLabel);
+        });
+
+        $('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.expand').click(function() { $('div.ui-dialog div.autoscaler div.scale-down-policy div.multi-edit div.data div.data-item').slideToggle(); });
+
+        $autoscalerDialog.dialog('option', 'position', 'center');
+        $autoscalerDialog.dialog('option', 'height', 'auto');
+      };
+
+      var $loading = $('<div>').addClass('loading-overlay').appendTo($autoscalerDialog);
+      $autoscalerDialog.dialog({
+        title: 'AutoScale Configuration Wizard',
+        width: 825,
+        height: 600,
+        draggable: true,
+        closeonEscape: false,
+        overflow:'auto',
+        open:function() {
+          $("button").each(function(){
+            $(this).attr("style", "left: 600px; position: relative; margin-right: 5px; ");
+          });
+        },
+        buttons: [
+          {
+            text: _l('label.cancel'),
+            'class': 'cancel',
+            click: function() {
+              $autoscalerDialog.dialog('destroy');
+              $('.overlay').remove();
+            }
+          },
+          {
+            text: _l('Apply'),
+            'class': 'ok',
+            click: function() {
+              var data = cloudStack.serializeForm($('.ui-dialog .autoscaler form'));
+
+              $loading.appendTo($autoscalerDialog);
+              cloudStack.autoscaler.actions.add({
+                formData: formData,
+                context: context,
+                data: data,
+                response: {
+                  success: function() {
+                    $loading.remove();
+                    $autoscalerDialog.dialog('destroy');
+                    $autoscalerDialog.closest(':ui-dialog').remove();
+                    $('.overlay').remove();
+                    cloudStack.dialog.notice({
+                      message: 'Autoscaler configured successfully.'
+                    });
+                  },
+                  error: function(message) {
+                    cloudStack.dialog.notice({ message: message });
+                    $loading.remove();
+                  }
+                }
+              });
+            }
+          }
+        ]
+      }).closest('.ui-dialog').overlay();
+
+      dataProvider({
+        context: context,
+        response: {
+          success: function(args) {
+            $loading.remove();
+            renderDialogContent(args);
+
+            if (args.data && args.data.isAdvanced) {
+              $autoscalerDialog.find('input[type=checkbox]').trigger('click');
+              $autoscalerDialog.find('input[type=checkbox]').attr('checked', 'checked');
+            }
+          }
+        }
+      });
+    };
+  };
+}(jQuery, cloudStack));

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/93e7b86c/ui/scripts/ui/widgets/multiEdit.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js
index 140b889..c139c42 100644
--- a/ui/scripts/ui/widgets/multiEdit.js
+++ b/ui/scripts/ui/widgets/multiEdit.js
@@ -128,13 +128,20 @@
               $td.attr('title', data[fieldName]);
             }
           } else if (field.select) {
-            $td.append($('<span>').html(_s(
-              // Get matching option text
-              $multi.find('select').filter(function() {
-                return $(this).attr('name') == fieldName;
-              }).find('option').filter(function() {
-                return $(this).val() == data[fieldName];
-              }).html())));
+            // Get matching option text
+            var $matchingSelect = $multi.find('select')
+                  .filter(function() {
+                    return $(this).attr('name') == fieldName;
+                  });
+            var $matchingOption = $matchingSelect.find('option')
+                  .filter(function() {
+                    return $(this).val() == data[fieldName];
+                  });
+
+            var matchingValue = $matchingOption.size() ?
+                  $matchingOption.html() : data[fieldName];
+            
+            $td.append($('<span>').html(_s(matchingValue)));
           } else if (field.addButton && !options.noSelect) {
             if (options.multipleAdd) {
               $addButton.click(function() {
@@ -173,9 +180,14 @@
                          _l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel));
             $button.click(function() {
               var $button = $(this);
+              var context = $.extend(true, {},
+                                     options.context ?
+                                     options.context : cloudStack.context, {
+                                       multiRules: [data]
+                                     });
 
               field.custom.action({
-                context: options.context ? options.context : cloudStack.context,
+                context: context,
                 data: $td.data('multi-custom-data'),
                 $item: $td,
                 response: {
@@ -754,7 +766,10 @@
         $('<div>').addClass('button add-vm custom-action')
           .html(_l(field.custom.buttonLabel))
           .click(function() {
+            var formData = getMultiData($multi);
+            
             field.custom.action({
+              formData: formData,
               context: context,
               data: $td.data('multi-custom-data'),
               response: {
@@ -947,7 +962,7 @@
     }
 
     // Get existing data
-    getData();
+    setTimeout(function() { getData(); });
 
     var fullRefreshEvent = function(event) {
       if ($multi.is(':visible')) {