mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1435 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1435 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // 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) {
 | |
|     /**
 | |
|      * Serialize form data as object
 | |
|      */
 | |
|     var getData = function($wizard, options) {
 | |
|         if (!options) options = {};
 | |
| 
 | |
|         var $forms = $wizard.find('form').filter(function() {
 | |
|             return !options.all ? !$(this).closest('.multi-edit').length : true;
 | |
|         });
 | |
|         var $physicalNetworkItems = $wizard.find(
 | |
|             '.steps .setup-physical-network .select-container.multi'
 | |
|         ).filter(':not(.disabled)');
 | |
|         var $publicTrafficItems = $wizard.find(
 | |
|             '.steps .setup-public-traffic .data-body .data-item');
 | |
|         var $storageTrafficItems = $wizard.find(
 | |
|             '.steps .setup-storage-traffic .data-body .data-item');
 | |
|         var groupedForms = {};
 | |
| 
 | |
|         if ($physicalNetworkItems.find('li.traffic-type-draggable.storage').length) {
 | |
|             $wizard.find('li.conditional.storage-traffic').show();
 | |
|         } else {
 | |
|             $wizard.find('li.conditional.storage-traffic').hide();
 | |
|         }
 | |
| 
 | |
|         if (options.all) {
 | |
|             return cloudStack.serializeForm($forms, {
 | |
|                 escapeSlashes: true
 | |
|             });
 | |
|         }
 | |
| 
 | |
|         // Group form fields together, by form ID
 | |
|         $forms.each(function() {
 | |
|             var $form = $(this);
 | |
|             var id = $form.attr('rel');
 | |
| 
 | |
|             if (!id) return true;
 | |
| 
 | |
|             groupedForms[id] = cloudStack.serializeForm($form, {
 | |
|                 escapeSlashes: true
 | |
|             });
 | |
| 
 | |
|             return true;
 | |
|         });
 | |
| 
 | |
|         // Get physical network data
 | |
|         groupedForms.physicalNetworks = $.map(
 | |
|             $physicalNetworkItems,
 | |
|             function(network) {
 | |
|                 var $network = $(network);
 | |
|                 var $guestForm = $wizard.find('form[guest-network-id=' + $network.index() + ']');
 | |
|                 var trafficTypeConfiguration = {};
 | |
| 
 | |
|                 $network.find('.traffic-type-draggable').each(function() {
 | |
|                     var $trafficType = $(this);
 | |
|                     var trafficTypeID = $trafficType.attr('traffic-type-id');
 | |
| 
 | |
| 
 | |
|                     trafficTypeConfiguration[trafficTypeID] = $trafficType.data('traffic-type-data');
 | |
|                 });
 | |
| 
 | |
|                 return {
 | |
|                     id: $network.index(),
 | |
|                     name: $network.find('.field.name input[type=text]').val(),
 | |
|                     isolationMethod: $network.find('.field.name select').val(),
 | |
| 
 | |
|                     // Traffic type list
 | |
|                     trafficTypes: $.map(
 | |
|                         $network.find('.traffic-type-draggable'),
 | |
|                         function(trafficType) {
 | |
|                             var $trafficType = $(trafficType);
 | |
| 
 | |
|                             return $trafficType.attr('traffic-type-id');
 | |
|                         }
 | |
|                     ),
 | |
| 
 | |
|                     // Traffic type configuration data
 | |
|                     trafficTypeConfiguration: trafficTypeConfiguration,
 | |
| 
 | |
|                     guestConfiguration: $guestForm.length ? cloudStack.serializeForm($guestForm) : null
 | |
|                 };
 | |
|             }
 | |
|         );
 | |
| 
 | |
|         // Get public traffic data (multi-edit)
 | |
|         groupedForms.publicTraffic = $.map(
 | |
|             $publicTrafficItems,
 | |
|             function(publicTrafficItem) {
 | |
|                 var $publicTrafficItem = $(publicTrafficItem);
 | |
|                 var publicTrafficData = {};
 | |
|                 var fields = [
 | |
|                     'gateway',
 | |
|                     'netmask',
 | |
|                     'vlanid',
 | |
|                     'startip',
 | |
|                     'endip'
 | |
|                 ];
 | |
| 
 | |
|                 $(fields).each(function() {
 | |
|                     publicTrafficData[this] =
 | |
|                         $publicTrafficItem.find('td.' + this + ' span').html();
 | |
|                 });
 | |
| 
 | |
|                 return publicTrafficData;
 | |
|             }
 | |
|         );
 | |
| 
 | |
|         // Get storage traffic data (multi-edit)
 | |
|         groupedForms.storageTraffic = $.map(
 | |
|             $storageTrafficItems,
 | |
|             function(storageTrafficItem) {
 | |
|                 var $storageTrafficItem = $(storageTrafficItem);
 | |
|                 var storageTrafficData = {};
 | |
|                 var fields = [
 | |
|                     'gateway',
 | |
|                     'netmask',
 | |
|                     'vlan',
 | |
|                     'startip',
 | |
|                     'endip'
 | |
|                 ];
 | |
| 
 | |
|                 $(fields).each(function() {
 | |
|                     storageTrafficData[this] =
 | |
|                         $storageTrafficItem.find('td.' + this + ' span').html();
 | |
|                 });
 | |
| 
 | |
|                 return storageTrafficData;
 | |
|             }
 | |
|         );
 | |
| 
 | |
|         // Hack to fix forward slash JS error
 | |
|         $.each(groupedForms, function(key1, value1) {
 | |
|             $.each(value1, function(key2, value2) {
 | |
|                 if (typeof value2 == 'string') {
 | |
|                     groupedForms[key1][key2] = value2.replace(/__forwardSlash__/g, '\/');
 | |
|                 }
 | |
|             });
 | |
|         });
 | |
| 
 | |
|         // Include zone network type
 | |
|         if (groupedForms.zone) {
 | |
|             groupedForms.zone.networkType = $forms.find('input[name=network-model]:checked').val();
 | |
| 
 | |
|             // Include zone isolation mode, supported for Advanced zones only
 | |
|             if (groupedForms.zone.networkType == 'Advanced') {
 | |
|                 groupedForms.zone.sgEnabled = $forms.find('input[name=zone-advanced-sg-enabled]')
 | |
|                     .is(':checked') ? true : false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return groupedForms;
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Handles validation for custom UI components
 | |
|      */
 | |
|     var customValidation = {
 | |
|         networkRanges: function($form) {
 | |
|             if ($form.closest('.multi-edit').find('.data-item').length) {
 | |
|                 return true;
 | |
|             }
 | |
| 
 | |
|             cloudStack.dialog.notice({
 | |
|                 message: _l('message.please.add.at.lease.one.traffic.range')
 | |
|             });
 | |
|             return false;
 | |
|         },
 | |
| 
 | |
|         physicalNetworks: function($form) {
 | |
|             var $enabledPhysicalNetworks = $form.filter(':not(.disabled)').filter(function() {
 | |
|                 return $(this).find('.traffic-type-draggable').length;
 | |
|             });
 | |
|             var $trafficTypes = $enabledPhysicalNetworks.find('.traffic-type-draggable');
 | |
|             var $configuredTrafficTypes = $trafficTypes.filter(function() {
 | |
|                 var $trafficType = $(this);
 | |
| 
 | |
|                 return ($trafficType.data('traffic-type-data') != null);
 | |
|             });
 | |
| 
 | |
|             if ($enabledPhysicalNetworks.length > 1 &&
 | |
|                 $configuredTrafficTypes.length != $trafficTypes.length) {
 | |
|                 cloudStack.dialog.notice({
 | |
|                     message: _l('message.configure.all.traffic.types')
 | |
|                 });
 | |
| 
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Determine if UI components in step should be custom-validated
 | |
|      * (i.e., not a standard form)
 | |
|      */
 | |
|     var checkCustomValidation = function($step) {
 | |
|         var $multiEditForm = $step.find('.multi-edit form');
 | |
|         var $physicalNetworks = $step.find('.select-container.multi');
 | |
|         var isCustomValidated;
 | |
| 
 | |
|         if ($multiEditForm.length) {
 | |
|             isCustomValidated = customValidation.networkRanges($multiEditForm);
 | |
|         } else if ($physicalNetworks.length) {
 | |
|             isCustomValidated = customValidation.physicalNetworks($physicalNetworks);
 | |
|         } else {
 | |
|             isCustomValidated = true;
 | |
|         }
 | |
| 
 | |
|         return isCustomValidated;
 | |
|     };
 | |
| 
 | |
|     var isAdvancedNetwork = function($wizard) {
 | |
|         return getData($wizard, {
 | |
|             all: true
 | |
|         })['network-model'] == 'Advanced';
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Setup physical network wizard UI
 | |
|      */
 | |
|     var physicalNetwork = {
 | |
|         init: function($wizard) {
 | |
|             var $existingPhysicalNetworks = physicalNetwork.getNetworks($wizard);
 | |
| 
 | |
|             // Initialize physical networks
 | |
|             if (!$existingPhysicalNetworks.length) {
 | |
|                 physicalNetwork.add($wizard);
 | |
|             } else if (!isAdvancedNetwork($wizard)) {
 | |
|                 $existingPhysicalNetworks.filter(':first').siblings().each(function() {
 | |
|                     physicalNetwork.remove($(this));
 | |
|                 });
 | |
|             }
 | |
| 
 | |
|             physicalNetwork.updateNetworks(physicalNetwork.getNetworks($wizard));
 | |
| 
 | |
|             $wizard.find('.traffic-types-drag-area ul li').removeClass('required disabled clone');
 | |
| 
 | |
|             // Setup clone traffic types
 | |
|             $(physicalNetwork.cloneTrafficTypes($wizard)).each(function() {
 | |
|                 var trafficTypeID = this;
 | |
| 
 | |
|                 $wizard.find('.traffic-types-drag-area ul li').filter(function() {
 | |
|                     return $(this).hasClass(trafficTypeID);
 | |
|                 }).addClass('clone');
 | |
|             });
 | |
| 
 | |
|             // Setup required traffic types
 | |
|             $(physicalNetwork.requiredTrafficTypes($wizard)).each(function() {
 | |
|                 var trafficTypeID = this;
 | |
|                 var $firstPhysicalNetwork = physicalNetwork.getNetworks($wizard).filter(':first');
 | |
| 
 | |
|                 // First physical network gets required traffic types
 | |
|                 physicalNetwork.assignTrafficType(trafficTypeID, $firstPhysicalNetwork);
 | |
| 
 | |
|                 $wizard.find('.traffic-types-drag-area ul li').filter(function() {
 | |
|                     return $(this).hasClass(trafficTypeID);
 | |
|                 }).addClass('required');
 | |
|             });
 | |
| 
 | |
|             // Setup disabled traffic types
 | |
|             $(physicalNetwork.disabledTrafficTypes($wizard)).each(function() {
 | |
|                 var trafficTypeID = this;
 | |
|                 var $trafficType = physicalNetwork.getTrafficType(this, $wizard);
 | |
| 
 | |
|                 physicalNetwork.unassignTrafficType($trafficType);
 | |
| 
 | |
|                 $wizard.find('.traffic-types-drag-area ul li').filter(function() {
 | |
|                     return $(this).hasClass(trafficTypeID);
 | |
|                 }).addClass('disabled');
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Traffic type edit dialog
 | |
|          */
 | |
|         editTrafficTypeDialog: function($trafficType) {
 | |
|             var trafficData = $trafficType.data('traffic-type-data') ?
 | |
|                 $trafficType.data('traffic-type-data') : {};
 | |
|             var hypervisor = getData($trafficType.closest('.zone-wizard')).zone.hypervisor;
 | |
|             var zoneType = getData($trafficType.closest('.zone-wizard')).zone.networkType;
 | |
|             var fields;
 | |
| 
 | |
|             if (hypervisor == 'VMware') {
 | |
|                 fields = {
 | |
|                     vSwitchName: {
 | |
|                         label: 'label.vswitch.name' ,
 | |
|                         defaultValue: trafficData.vSwitchName
 | |
|                     },
 | |
|                     vlanId: {
 | |
|                             label: 'label.vlan.id',
 | |
|                         defaultValue: trafficData.vlanId
 | |
|                     }
 | |
|                 };
 | |
| 
 | |
|                 if(zoneType == 'Advanced') {
 | |
|                     if(trafficData.vSwitchType == null) {
 | |
|                          var useDvs = false;
 | |
|                          $.ajax({
 | |
|                              url: createURL('listConfigurations'),
 | |
|                              data: {
 | |
|                                  name: 'vmware.use.dvswitch'
 | |
|                              },
 | |
|                              async: false,
 | |
|                              success: function(json) {
 | |
|                                  if (json.listconfigurationsresponse.configuration[0].value == 'true') {
 | |
|                                      useDvs = true;
 | |
|                                  }
 | |
|                              }
 | |
|                          });
 | |
|                          if (useDvs == true) {
 | |
|                              var useNexusDvs = false;
 | |
|                              $.ajax({
 | |
|                                  url: createURL('listConfigurations'),
 | |
|                                  data: {
 | |
|                                      name: 'vmware.use.nexus.vswitch'
 | |
|                                  },
 | |
|                                  async: false,
 | |
|                                  success: function(json) {
 | |
|                                      if (json.listconfigurationsresponse.configuration[0].value == 'true') {
 | |
|                                          useNexusDvs = true;
 | |
|                                      }
 | |
|                                  }
 | |
|                              });
 | |
|                              if (useNexusDvs == true) {
 | |
|                                  trafficData.vSwitchType = 'nexusdvs';
 | |
|                                  fields.vSwitchName.defaultValue = 'epp0';
 | |
|                              } else {
 | |
|                                  trafficData.vSwitchType = 'vmwaredvs';
 | |
|                                  fields.vSwitchName.defaultValue = 'dvSwitch0';
 | |
|                              }
 | |
|                          } else { //useDvs == false
 | |
|                              trafficData.vSwitchType = 'vmwaresvs';
 | |
|                              fields.vSwitchName.defaultValue = 'vSwitch0';
 | |
|                          }
 | |
|                     }
 | |
| 
 | |
|                     $.extend(fields, {
 | |
|                         vSwitchType: {
 | |
|                                 label: 'label.vSwitch.type',
 | |
|                             select: function (args) {
 | |
|                                 args.response.success({
 | |
|                                     data: [{
 | |
|                                         id: 'nexusdvs',
 | |
|                                         description: 'Cisco Nexus 1000v Distributed Virtual Switch'
 | |
|                                     }, {
 | |
|                                         id: 'vmwaresvs',
 | |
|                                         description: 'VMware vNetwork Standard Virtual Switch'
 | |
|                                     }, {
 | |
|                                         id: 'vmwaredvs',
 | |
|                                         description: 'VMware vNetwork Distributed Virtual Switch'
 | |
|                                     }]
 | |
|                                 });
 | |
|                             },
 | |
|                             defaultValue: trafficData.vSwitchType
 | |
|                         }
 | |
|                     });
 | |
|                 }
 | |
|             } else {
 | |
|                 fields = {
 | |
|                     label: {
 | |
|                         label: hypervisor + ' ' + _l('label.traffic.label'),
 | |
|                         defaultValue: trafficData.label
 | |
|                     }
 | |
|                 };
 | |
|             }
 | |
| 
 | |
|             cloudStack.dialog.createForm({
 | |
|                 form: {
 | |
|                     title: _l('label.edit.traffic.type'),
 | |
|                     desc: _l('message.edit.traffic.type'),
 | |
|                     fields: fields
 | |
|                 },
 | |
| 
 | |
|                 after: function(args) {
 | |
|                     $trafficType.data('traffic-type-data', args.data);
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get required traffic type IDs for proper validation
 | |
|          */
 | |
|         requiredTrafficTypes: function($wizard) {
 | |
|             return cloudStack.zoneWizard.requiredTrafficTypes({
 | |
|                 data: getData($wizard)
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get required traffic type IDs for proper validation
 | |
|          */
 | |
|         disabledTrafficTypes: function($wizard) {
 | |
|             return cloudStack.zoneWizard.disabledTrafficTypes({
 | |
|                 data: getData($wizard)
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get clone-type traffic type IDs for proper validation
 | |
|          */
 | |
|         cloneTrafficTypes: function($wizard) {
 | |
|             return cloudStack.zoneWizard.cloneTrafficTypes({
 | |
|                 data: getData($wizard)
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Physical network step: Renumber network form items
 | |
|          */
 | |
|         renumberFormItems: function($container) {
 | |
|             var $items = $container.find('.select-container.multi');
 | |
| 
 | |
|             $items.each(function() {
 | |
|                 var $item = $(this);
 | |
|                 var $networkName = $item.find('.field.name input[type=text]');
 | |
|                 var $networkId = $item.find('input[name=id]');
 | |
|                 var $networkTypes = $item.find('.field.network-types input');
 | |
|                 var index = $item.index();
 | |
| 
 | |
|                 $networkId.val(index);
 | |
|                 $networkName.attr('name', 'physicalNetworks[' + index + ']' + '.name');
 | |
|                 $networkTypes.val(index);
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get main physical network wizard step container
 | |
|          *
 | |
|          * @param $elem Any elem within the container
 | |
|          */
 | |
|         getMainContainer: function($elem) {
 | |
|             return $elem.closest('.steps .setup-physical-network');
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Returns traffic elem
 | |
|          *
 | |
|          * @param trafficTypeID ID of desired traffic type
 | |
|          */
 | |
|         getTrafficType: function(trafficTypeID, $container) {
 | |
|             var $trafficType = $container.find('li.traffic-type-draggable').filter(function() {
 | |
|                 return $(this).attr('traffic-type-id') == trafficTypeID;
 | |
|             });
 | |
| 
 | |
|             if (physicalNetwork.isTrafficTypeClone($trafficType) && !$container.closest('.select-container.multi').length) {
 | |
|                 // Get traffic type from original container
 | |
|                 return $trafficType.filter(function() {
 | |
|                     return $(this).closest(
 | |
|                         physicalNetwork.getOriginalTrafficContainer($trafficType)
 | |
|                     ).length;
 | |
|                 });
 | |
|             }
 | |
| 
 | |
|             return $trafficType;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get original drag container for traffic type elem
 | |
|          *
 | |
|          * @param $trafficType Traffic type elem
 | |
|          */
 | |
|         getOriginalTrafficContainer: function($trafficType) {
 | |
|             var $dragContainer = physicalNetwork.getMainContainer($trafficType)
 | |
|                 .find('.traffic-types-drag-area ul > li')
 | |
|                 .filter(function() {
 | |
|                     return $(this).hasClass($trafficType.attr('traffic-type-id'));
 | |
|                 })
 | |
|                 .find('ul');
 | |
| 
 | |
|             return $dragContainer;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Get all physical networks
 | |
|          *
 | |
|          * @param $container Physical network step - main container
 | |
|          */
 | |
|         getNetworks: function($container) {
 | |
|             return $container.find('.select-container.multi');
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Determine if traffic type is a 'cloned' type
 | |
|          *
 | |
|          * @param $trafficType
 | |
|          */
 | |
|         isTrafficTypeClone: function($trafficType) {
 | |
|             return physicalNetwork.getOriginalTrafficContainer($trafficType).parent().hasClass('clone');
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Assigns traffic type to specified physical network
 | |
|          *
 | |
|          * @param trafficTypeID ID of desired traffic type
 | |
|          * @param $physicalNetwork Physical network elem
 | |
|          */
 | |
|         assignTrafficType: function(trafficTypeID, $physicalNetwork, data) {
 | |
|             var $container = physicalNetwork.getMainContainer($physicalNetwork);
 | |
|             var $trafficType = physicalNetwork.getTrafficType(trafficTypeID, $container);
 | |
|             var $dropArea = $physicalNetwork.find('.drop-container ul');
 | |
| 
 | |
|             if ($physicalNetwork.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').length) return false;
 | |
| 
 | |
|             if (physicalNetwork.isTrafficTypeClone($trafficType)) {
 | |
|                 if (!physicalNetwork.getTrafficType(trafficTypeID, $physicalNetwork).length) {
 | |
|                     $trafficType = $trafficType.clone()
 | |
|                         .removeClass('disabled')
 | |
|                         .appendTo($dropArea)
 | |
|                         .draggable(physicalNetwork.draggableOptions($physicalNetwork.closest('.zone-wizard')));
 | |
|                 } else {
 | |
|                     return false;
 | |
|                 }
 | |
|             } else {
 | |
|                 $trafficType.appendTo($dropArea);
 | |
|             }
 | |
| 
 | |
|             if (data) {
 | |
|                 $trafficType.data('traffic-type-data', data);
 | |
|             }
 | |
| 
 | |
|             physicalNetwork.updateNetworks($.merge($physicalNetwork, $physicalNetwork.siblings()));
 | |
| 
 | |
|             return $trafficType;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Assigns traffic type to original drag container
 | |
|          *
 | |
|          * @param trafficTypeID ID of desired traffic type
 | |
|          * @param $container Physical network wizard step container
 | |
|          * @param $physicalNetwork (optional) Specific physical network to remove from -- only for clones
 | |
|          */
 | |
|         unassignTrafficType: function($trafficType) {
 | |
|             var $wizard = $trafficType.closest('.zone-wizard');
 | |
|             var $originalContainer = physicalNetwork.getOriginalTrafficContainer($trafficType);
 | |
|             var $physicalNetworks = physicalNetwork.getNetworks($wizard);
 | |
|             var trafficTypeID = $trafficType.attr('traffic-type-id');
 | |
| 
 | |
|             if (!physicalNetwork.isTrafficTypeClone($trafficType) &&
 | |
|                 $.inArray(trafficTypeID, physicalNetwork.requiredTrafficTypes($wizard)) == -1) {
 | |
|                 $trafficType.appendTo($originalContainer);
 | |
|             } else {
 | |
|                 physicalNetwork.assignTrafficType(
 | |
|                     trafficTypeID,
 | |
|                     $physicalNetworks.filter(':first')
 | |
|                 );
 | |
| 
 | |
|                 if (physicalNetwork.isTrafficTypeClone($trafficType) &&
 | |
|                     $physicalNetworks.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').length > 1) {
 | |
|                     $trafficType.remove();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return $trafficType;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Returns true if new physical network item needs to be added
 | |
|          */
 | |
|         needsNewNetwork: function($containers) {
 | |
|             // Basic zones do not have multiple physical networks
 | |
|             if (!isAdvancedNetwork($containers.closest('.zone-wizard')))
 | |
|                 return false;
 | |
| 
 | |
|             var $emptyContainers = $containers.filter(function() {
 | |
|                 return !$(this).find('li').length;
 | |
|             });
 | |
| 
 | |
|             return !$emptyContainers.length ? $containers.length : false;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Cleanup physical network containers
 | |
|          */
 | |
|         updateNetworks: function($containers) {
 | |
|             var $mainContainer = physicalNetwork.getMainContainer($containers);
 | |
|             var $allPhysicalNetworks = physicalNetwork.getNetworks($mainContainer);
 | |
|             var containerTotal = isAdvancedNetwork($containers.closest('.zone-wizard')) ?
 | |
|                 2 : 1;
 | |
| 
 | |
|             $allPhysicalNetworks.each(function() {
 | |
|                 var $ul = $(this).find('.drop-container ul');
 | |
| 
 | |
|                 if (!$(this).find('li').length) {
 | |
|                     $(this).addClass('disabled');
 | |
|                     $ul.fadeOut();
 | |
|                 } else {
 | |
|                     $(this).removeClass('disabled');
 | |
|                     $ul.show();
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             $containers.each(function() {
 | |
|                 var $currentContainer = $(this);
 | |
|                 if (!$currentContainer.find('li').length &&
 | |
|                     $containers.length > containerTotal) {
 | |
|                     $currentContainer.remove();
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             $containers = $containers.closest('.setup-physical-network')
 | |
|                 .find('.select-container.multi');
 | |
| 
 | |
|             if (physicalNetwork.needsNewNetwork($containers)) {
 | |
|                 physicalNetwork.add($mainContainer.parent());
 | |
|             }
 | |
| 
 | |
|             $containers.filter(':first').find('.remove.physical-network').remove();
 | |
| 
 | |
|             return $containers;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Default options for initializing traffic type draggables
 | |
|          */
 | |
|         draggableOptions: function($wizard) {
 | |
|             return {
 | |
|                 appendTo: $wizard,
 | |
|                 helper: 'clone',
 | |
| 
 | |
|                 // Events
 | |
|                 start: function(event, ui) {
 | |
|                     $(this).addClass('disabled');
 | |
|                 },
 | |
| 
 | |
|                 stop: function(event, ui) {
 | |
|                     $(this).removeClass('disabled');
 | |
|                 },
 | |
| 
 | |
|                 cancel: '.edit-traffic-type'
 | |
|             };
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Physical network step: Generate new network element
 | |
|          */
 | |
|         add: function($wizard) {
 | |
|             var $container = $wizard.find('.setup-physical-network .content.input-area form');
 | |
|             var $physicalNetworkItem = $('<div>').addClass('select-container multi');
 | |
|             var $deleteButton = $('<div>').addClass('button remove physical-network')
 | |
|                 .attr({
 | |
|                     title: _l('label.remove.this.physical.network')
 | |
|                 })
 | |
|                 .append('<span>').addClass('icon').html(' ');
 | |
|             var $icon = $('<div>').addClass('physical-network-icon');
 | |
| 
 | |
|             var $nameField = $('<div>').addClass('field name').append(
 | |
|                 $('<div>').addClass('name').append(
 | |
|                     $('<label>').html(_l('label.physical.network.name'))
 | |
|                 ),
 | |
|                 $('<div>').addClass('value').append(
 | |
|                     $('<input>').attr({
 | |
|                         type: 'text'
 | |
|                     }).addClass('required disallowSpecialCharacters')
 | |
|                 )
 | |
|             );
 | |
| 
 | |
| 
 | |
|             var ovsTunnelManager = false;
 | |
|             $.ajax({
 | |
|                 url: createURL('listConfigurations'),
 | |
|                 data: {
 | |
|                     name: 'sdn.ovs.controller'
 | |
|                 },
 | |
|                 dataType: "json",
 | |
|                 async: false,
 | |
|                 success: function(json) {
 | |
|                     var items = json.listconfigurationsresponse.configuration; //2 entries returned: 'sdn.ovs.controller', 'sdn.ovs.controller.default.label'
 | |
|                     $(items).each(function() {
 | |
|                         if (this.name == 'sdn.ovs.controller') {
 | |
|                             if (this.value == 'true' || this.value == true) {
 | |
|                                 ovsTunnelManager = true;
 | |
|                             }
 | |
|                             return false; //break each loop
 | |
|                         }
 | |
|                     });
 | |
|                 }
 | |
|             });
 | |
|             //when OVS tunnel manager is used
 | |
|             //if(ovsTunnelManager == true) {
 | |
|             //Advanced zone supports 2 isolation method(VLAN, GRE), so show dropdown including the 2 options
 | |
|             if ($wizard.find('.select-network-model input:radio[name=network-model]:checked').val() == 'Advanced') {
 | |
|                 $nameField.append(
 | |
|                     $('<div>').append(
 | |
|                         $('<span style=\"font-size:11px;padding-right:5px;padding-left:40px\">').html(_l('label.isolation.method')),
 | |
|                         $('<select>').append(
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'VLAN'
 | |
|                             }).html('VLAN'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'GRE'
 | |
|                             }).html('GRE'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'STT'
 | |
|                             }).html('STT'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'BCF_SEGMENT'
 | |
|                             }).html('BCF_SEGMENT'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'SSP'
 | |
|                             }).html('SSP'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'VXLAN'
 | |
|                             }).html('VXLAN'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'ODL'
 | |
|                             }).html('ODL'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'L3VPN'
 | |
|                             }).html('L3VPN'),
 | |
|                             $('<option>').attr({
 | |
|                                 value: 'VCS'
 | |
|                             }).html('VCS')
 | |
|                         )
 | |
|                     )
 | |
|                 );
 | |
|             }
 | |
|             //Basic zone supports only 1 isolation method (L3), so there is no point showing dropdown.
 | |
|             //            }
 | |
|             //when OVS tunnel manager is not used, isolationmethods parameter in createPhysicalNetwork API is ignored. So no showing dropdown.
 | |
|             //isolationmethods parameter has not been used by network gurus so far. By default(i.e. when OVS tunnel manager is not used), networks are isolated with VLANs in Advanced zone, with L3 in basic zone.
 | |
|             //No longer the case, as the Nicira stuff also depends on this now
 | |
| 
 | |
| 
 | |
|             var $dropContainer = $('<div>').addClass('drop-container').append(
 | |
|                 $('<span>').addClass('empty-message').html(
 | |
|                     'Drag and drop traffic types you would like to add here.'
 | |
|                 ),
 | |
|                 $('<ul>').hide()
 | |
|             ).droppable({
 | |
|                 over: function(event, ui) {
 | |
|                     var $ul = $(this).find('ul');
 | |
| 
 | |
|                     $ul.addClass('active');
 | |
| 
 | |
|                     if (!$ul.find('li').length) {
 | |
|                         $(this).closest('.select-container.multi').removeClass('disabled');
 | |
|                         $ul.fadeIn();
 | |
|                     }
 | |
|                 },
 | |
| 
 | |
|                 out: function(event, ui) {
 | |
|                     var $ul = $(this).find('ul');
 | |
| 
 | |
|                     $ul.removeClass('active');
 | |
|                     physicalNetwork.updateNetworks($(this).closest('.select-container.multi'));
 | |
|                 },
 | |
| 
 | |
|                 drop: function(event, ui) {
 | |
|                     var trafficTypeID = ui.draggable.attr('traffic-type-id');
 | |
|                     var $physicalNetwork = $(this).closest('.select-container.multi');
 | |
|                     var trafficTypeData = ui.draggable.data('traffic-type-data');
 | |
| 
 | |
|                     if (trafficTypeID == 'guest' &&
 | |
|                         ui.draggable.closest('.select-container.multi').length) {
 | |
|                         ui.draggable.remove();
 | |
|                     }
 | |
| 
 | |
|                     physicalNetwork.assignTrafficType(trafficTypeID, $physicalNetwork, trafficTypeData);
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             var $idField = $('<input>').attr({
 | |
|                 type: 'hidden',
 | |
|                 name: 'id',
 | |
|                 value: 0
 | |
|             });
 | |
| 
 | |
|             // Initialize new default network form elem
 | |
|             $physicalNetworkItem.append(
 | |
|                 $icon,
 | |
|                 $nameField,
 | |
|                 $idField,
 | |
|                 $dropContainer
 | |
|             );
 | |
| 
 | |
|             // Only advanced zones can remove physical network
 | |
|             if (isAdvancedNetwork($wizard)) {
 | |
|                 $physicalNetworkItem.prepend($deleteButton);
 | |
|             }
 | |
| 
 | |
|             $physicalNetworkItem.hide().appendTo($container).fadeIn('fast');
 | |
|             $physicalNetworkItem.find('.name input').val('Physical Network ' + parseInt($physicalNetworkItem.index() + 1));
 | |
|             physicalNetwork.renumberFormItems($container);
 | |
| 
 | |
|             // Remove network action
 | |
|             $physicalNetworkItem.find('.button.remove.physical-network').click(function() {
 | |
|                 physicalNetwork.remove($physicalNetworkItem);
 | |
|             });
 | |
| 
 | |
|             $physicalNetworkItem.addClass('disabled'); // Since there are no traffic types yet
 | |
| 
 | |
|             return $physicalNetworkItem;
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Physical network step: Remove specified network element
 | |
|          *
 | |
|          * @param $physicalNetworkItem Physical network container to remove
 | |
|          */
 | |
|         remove: function($physicalNetworkItem) {
 | |
|             var $container = $physicalNetworkItem.closest('.setup-physical-network .content.input-area form');
 | |
|             var $trafficTypes = $physicalNetworkItem.find('li.traffic-type-draggable');
 | |
| 
 | |
|             $trafficTypes.each(function() {
 | |
|                 var trafficTypeID = $(this).attr('traffic-type-id');
 | |
| 
 | |
|                 physicalNetwork.assignTrafficType(
 | |
|                     trafficTypeID,
 | |
|                     $physicalNetworkItem.prev()
 | |
|                 );
 | |
|             });
 | |
| 
 | |
|             $trafficTypes.filter('.clone').remove();
 | |
|             physicalNetwork.updateNetworks($physicalNetworkItem.parent().find('.multi'));
 | |
|             $container.validate('refresh');
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Configure guest traffic UI
 | |
|      */
 | |
|     var guestTraffic = {
 | |
|         init: function($wizard, args) {
 | |
|             var $physicalNetworks = physicalNetwork.getNetworks($wizard);
 | |
|             var $tabs = guestTraffic.makeTabs($physicalNetworks, args);
 | |
|             var $container = guestTraffic.getMainContainer($wizard);
 | |
| 
 | |
|             // Cleanup
 | |
|             guestTraffic.remove($wizard);
 | |
| 
 | |
|             $container.find('.content form').hide();
 | |
|             $tabs.appendTo($container.find('.content .select-container'));
 | |
|             var $subnav = $container.find('ul.subnav').remove(); // Fix to avoid subnav becoming tab ul
 | |
|             $container.tabs();
 | |
|             $container.prepend($subnav);
 | |
|             $container.find('.field').hide();
 | |
|             $container.find('[rel=vlanRange]').show();
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Cleanup
 | |
|          */
 | |
|         remove: function($wizard) {
 | |
|             var $container = guestTraffic.getMainContainer($wizard);
 | |
| 
 | |
|             // Cleanup
 | |
|             $container.tabs('destroy');
 | |
|             $container.find('.physical-network-item').remove();
 | |
|             $container.find('.content form').show();
 | |
|         },
 | |
| 
 | |
|         getMainContainer: function($wizard) {
 | |
|             return $wizard.find('.steps .setup-guest-traffic');
 | |
|         },
 | |
| 
 | |
|         makeTabs: function($physicalNetworks, args) {
 | |
|             var $tabs = $('<ul></ul>').addClass('physical-network-item');
 | |
|             var $content = $();
 | |
| 
 | |
|             // Only use networks w/ guest traffic type
 | |
|             $physicalNetworks = $physicalNetworks.filter(function() {
 | |
|                 return $(this).find('li.guest').length;
 | |
| 
 | |
|                 return true;
 | |
|             });
 | |
| 
 | |
|             $physicalNetworks.each(function() {
 | |
|                 var $network = $(this);
 | |
|                 var $form = makeForm(args, 'guestTraffic', {});
 | |
|                 var refID = $network.find('input[name=id]').val();
 | |
|                 var networkID = 'physical-network-' + refID;
 | |
| 
 | |
|                 $form.attr('guest-network-id', refID);
 | |
| 
 | |
|                 $tabs.append($('<li></li>').append(
 | |
|                     $('<a></a>')
 | |
|                     .attr({
 | |
|                         href: '#' + networkID
 | |
|                     })
 | |
|                     .html($network.find('.field.name input').val())
 | |
|                 ));
 | |
|                 $.merge(
 | |
|                     $content,
 | |
|                     $('<div></div>')
 | |
|                     .addClass('physical-network-item')
 | |
|                     .attr({
 | |
|                         id: networkID
 | |
|                     })
 | |
|                     .append($form)
 | |
|                 );
 | |
| 
 | |
|                 $form.validate();
 | |
|             });
 | |
| 
 | |
|             $tabs.find('li:first').addClass('first');
 | |
|             $tabs.find('li:last').addClass('last');
 | |
| 
 | |
|             return $.merge($tabs, $content);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Generate dynamic form, based on ID of form object given
 | |
|      */
 | |
|     var makeForm = function(args, id, formState) {
 | |
|         var form = cloudStack.dialog.createForm({
 | |
|             noDialog: true,
 | |
|             context: $.extend(true, {}, cloudStack.context, {
 | |
|                 zones: [formState]
 | |
|             }),
 | |
|             form: {
 | |
|                 title: '',
 | |
|                 desc: '',
 | |
|                 fields: args.forms[id].fields
 | |
|             },
 | |
|             after: function(args) {}
 | |
|         });
 | |
| 
 | |
|         var $form = form.$formContainer.find('form');
 | |
| 
 | |
|         // Cleanup form to follow zone wizard CSS naming
 | |
|         $form.attr('rel', id);
 | |
|         $form.find('input[type=submit]').remove();
 | |
|         $form.find('.form-item').addClass('field').removeClass('form-item');
 | |
|         $form.find('label.error').hide();
 | |
|         $form.find('.form-item .name').each(function() {
 | |
|             $(this).html($(this).find('label'));
 | |
|         });
 | |
|         $form.find('label[for]').each(function() {
 | |
|             var forAttr = $(this).attr('for');
 | |
|             $form.find('#' + forAttr).attr('id', id + '_' + forAttr);
 | |
|             $(this).attr('for', id + '_' + forAttr)
 | |
|         });
 | |
| 
 | |
|         $form.find('select, input').change(function() {
 | |
|             cloudStack.evenOdd($form, '.field:visible', {
 | |
|                 even: function($row) {
 | |
|                     $row.removeClass('odd');
 | |
|                 },
 | |
|                 odd: function($row) {
 | |
|                     $row.addClass('odd');
 | |
|                 }
 | |
|             });
 | |
|         });
 | |
| 
 | |
|         return $form;
 | |
|     };
 | |
| 
 | |
|     cloudStack.uiCustom.zoneWizard = function(args) {
 | |
|         return function() {
 | |
|             var $wizard = $('#template').find('div.zone-wizard').clone();
 | |
|             var $progress = $wizard.find('div.progress ul li');
 | |
|             var $steps = $wizard.find('div.steps').children().hide().filter(':not(.disabled)');
 | |
| 
 | |
|             $wizard.data('startfn', null);
 | |
| 
 | |
|             // Close wizard
 | |
|             var close = function() {
 | |
|                 $wizard.dialog('destroy');
 | |
|                 $('div.overlay').fadeOut(function() {
 | |
|                     $('div.overlay').remove();
 | |
|                 });
 | |
|             };
 | |
| 
 | |
|             // Save and close wizard
 | |
|             var completeAction = function() {
 | |
|                 var $launchStep = $wizard.find('.steps .review');
 | |
|                 var data = getData($wizard);
 | |
|                 var enableZoneAction = args.enableZoneAction;
 | |
| 
 | |
|                 // Convert last step to launch appearance
 | |
|                 $launchStep.find('.main-desc').hide();
 | |
|                 $launchStep.find('.main-desc.launch').show();
 | |
|                 $launchStep.find('.launch-container').show();
 | |
|                 $launchStep.find('ul').html('');
 | |
|                 $wizard.find('.buttons').hide();
 | |
|                 $wizard.find('.button.previous').remove();
 | |
| 
 | |
|                 var makeMessage = function(message, isError) {
 | |
|                     var $li = $('<li>')
 | |
|                         .addClass(!isError ? 'loading' : 'info')
 | |
|                         .append(
 | |
|                             $('<span>').addClass('icon').html(' '),
 | |
|                             $('<span>').addClass('text').html(message)
 | |
|                     );
 | |
|                     var $launchContainer = $launchStep.find('.launch-container');
 | |
| 
 | |
|                     $launchStep.find('ul').append($li);
 | |
|                     $li.prev().removeClass('loading');
 | |
|                     $launchContainer.scrollTop($launchContainer.height());
 | |
| 
 | |
|                     if (isError) {
 | |
|                         $li.prev().addClass('error');
 | |
|                     }
 | |
| 
 | |
|                 };
 | |
| 
 | |
|                 args.action({
 | |
|                     data: data,
 | |
|                     wizard: $wizard,
 | |
|                     startFn: $wizard.data('startfn'),
 | |
|                     uiSteps: $.map(
 | |
|                         $wizard.find('.steps > div'),
 | |
|                         function(step) {
 | |
|                             return $(step).attr('zone-wizard-step-id');
 | |
|                         }
 | |
|                     ),
 | |
|                     response: {
 | |
|                         success: function(args) {
 | |
|                             $launchStep.find('ul li').removeClass('loading');
 | |
| 
 | |
|                             var closeWindow = function() {
 | |
|                                 close();
 | |
|                                 $(window).trigger('cloudStack.fullRefresh');
 | |
|                             };
 | |
| 
 | |
|                             var enableZone = function() {
 | |
|                                 makeMessage(_l('message.enabling.zone'));
 | |
| 
 | |
|                                 enableZoneAction({
 | |
|                                     formData: data,
 | |
|                                     data: data,
 | |
|                                     launchData: args.data,
 | |
|                                     response: {
 | |
|                                         success: function(args) {
 | |
|                                             closeWindow();
 | |
|                                         },
 | |
| 
 | |
|                                         error: function(message) {
 | |
|                                             cloudStack.dialog.notice({
 | |
|                                                 message: _l('error.could.not.enable.zone') + ':</br>' + message
 | |
|                                             });
 | |
|                                         }
 | |
|                                     }
 | |
|                                 });
 | |
|                             };
 | |
| 
 | |
|                             cloudStack.dialog.confirm({
 | |
|                                 message: _l('message.zone.creation.complete.would.you.like.to.enable.this.zone'),
 | |
|                                 action: function() {
 | |
|                                     enableZone();
 | |
|                                 },
 | |
|                                 cancelAction: function() {
 | |
|                                     closeWindow();
 | |
|                                 }
 | |
|                             });
 | |
|                         },
 | |
|                         error: function(stepID, message, start) {
 | |
|                             var goNextOverride = function(event) {
 | |
|                                 $(this).unbind('click', goNextOverride);
 | |
|                                 showStep(stepID, false, {
 | |
|                                     nextStep: 'launch'
 | |
|                                 });
 | |
| 
 | |
|                                 return false;
 | |
|                             };
 | |
| 
 | |
|                             $wizard.find('.buttons').show();
 | |
|                             $wizard.find('.buttons .button.next')
 | |
|                                 .removeClass('final')
 | |
|                                 .html('<span>Fix errors</span>')
 | |
|                                 .click(goNextOverride);
 | |
|                             makeMessage(_l('error.something.went.wrong.please.correct.the.following') + ':<br/>' + message, true);
 | |
|                             $wizard.data('startfn', start);
 | |
|                         },
 | |
|                         message: makeMessage
 | |
|                     }
 | |
|                 });
 | |
|             };
 | |
| 
 | |
|             // Go to specified step in wizard,
 | |
|             // updating nav items and diagram
 | |
|             var showStep = function(index, goBack, options) {
 | |
|                 if (!options) options = {};
 | |
| 
 | |
|                 if (typeof index == 'string') {
 | |
|                     index = $wizard.find('[zone-wizard-step-id=' + index + ']').index() + 1;
 | |
|                 }
 | |
| 
 | |
|                 var targetIndex = index - 1;
 | |
| 
 | |
|                 if (index <= 1) targetIndex = 0;
 | |
|                 if (targetIndex == $steps.length) {
 | |
|                     completeAction();
 | |
|                 }
 | |
| 
 | |
|                 $steps.hide();
 | |
|                 $wizard.find('.buttons').show();
 | |
| 
 | |
|                 var $targetStep = $($steps[targetIndex]).show();
 | |
|                 var $uiCustom = $targetStep.find('[ui-custom]');
 | |
|                 var formState = getData($wizard, {
 | |
|                     all: true
 | |
|                 });
 | |
|                 var groupedFormState = getData($wizard);
 | |
|                 var formID = $targetStep.attr('zone-wizard-form');
 | |
|                 var stepPreFilter = cloudStack.zoneWizard.preFilters[
 | |
|                     $targetStep.attr('zone-wizard-prefilter')
 | |
|                 ];
 | |
| 
 | |
|                 // Bypass step check
 | |
|                 if (stepPreFilter && !stepPreFilter({
 | |
|                     data: formState,
 | |
|                     groupedData: groupedFormState
 | |
|                 })) {
 | |
|                     return showStep(!goBack ? index + 1 : index - 1,
 | |
|                         goBack
 | |
|                     );
 | |
|                 }
 | |
| 
 | |
|                 if (formID) {
 | |
|                     if (!$targetStep.find('form').length) {
 | |
|                         makeForm(args, formID, formState).appendTo($targetStep.find('.content.input-area .select-container'));
 | |
| 
 | |
|                         setTimeout(function() {
 | |
|                             cloudStack.evenOdd($targetStep, '.field:visible', {
 | |
|                                 even: function() {},
 | |
|                                 odd: function($row) {
 | |
|                                     $row.addClass('odd');
 | |
|                                 }
 | |
|                             });
 | |
|                         }, 50);
 | |
|                     } else {
 | |
|                         // Always re-activate selects
 | |
|                         $targetStep.find('form select').each(function() {
 | |
|                             var $select = $(this);
 | |
|                             var selectFn = $select.data('dialog-select-fn');
 | |
|                             var originalVal = $select.val();
 | |
| 
 | |
|                             if (selectFn) {
 | |
|                                 $select.html('');
 | |
|                                 selectFn({
 | |
|                                     context: {
 | |
|                                         zones: [formState]
 | |
|                                     }
 | |
|                                 });
 | |
|                                 $select.val(originalVal);
 | |
|                                 $select.trigger('change');
 | |
|                             }
 | |
|                         });
 | |
|                     }
 | |
| 
 | |
|                     if (args.forms[formID].preFilter) {
 | |
|                         var preFilter = args.forms[formID].preFilter({
 | |
|                             $form: $targetStep.find('form'),
 | |
|                             data: formState
 | |
|                         });
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // Custom UI manipulations for specific steps
 | |
|                 switch ($targetStep.attr('zone-wizard-step-id')) {
 | |
|                     case 'configureGuestTraffic':
 | |
|                         if (formState['network-model'] == 'Advanced' && formState['zone-advanced-sg-enabled'] == undefined) {
 | |
|                             guestTraffic.init($wizard, args); //initialize multiple tabs (tabs is as many as Guest Traffic types in multiple physical networks in Advanced Zone without SG)
 | |
|                         } else {
 | |
|                             guestTraffic.remove($wizard);
 | |
|                         }
 | |
|                         break;
 | |
| 
 | |
|                     case 'setupPhysicalNetwork':
 | |
|                         if(!goBack) {
 | |
|                             physicalNetwork.init($wizard);
 | |
|                         }
 | |
|                 }
 | |
| 
 | |
|                 if ($uiCustom.length) {
 | |
|                     $uiCustom.each(function() {
 | |
|                         var $item = $(this);
 | |
|                         var id = $item.attr('ui-custom');
 | |
| 
 | |
|                         $item.replaceWith(
 | |
|                             args.customUI[id]({
 | |
|                                 data: formState,
 | |
|                                 context: cloudStack.context
 | |
|                             })
 | |
|                         )
 | |
|                     });
 | |
|                 }
 | |
| 
 | |
|                 if (!targetIndex) {
 | |
|                     $wizard.find('.button.previous').hide();
 | |
|                 } else {
 | |
|                     $wizard.find('.button.previous').show();
 | |
|                 }
 | |
| 
 | |
|                 var $nextButton = $wizard.find('.button.next');
 | |
|                 $nextButton.find('span').html(_l('label.next'));
 | |
|                 $nextButton.removeClass('final post-launch');
 | |
| 
 | |
|                 // Show launch button if last step
 | |
|                 if ($targetStep.index() == $steps.length - 1 || options.nextStep) {
 | |
|                     $nextButton.find('span').html(options.nextStep ? _l('label.save.changes') : _l('label.launch.zone'));
 | |
|                     $nextButton.addClass('final');
 | |
| 
 | |
|                     if (options.nextStep) {
 | |
|                         $nextButton.addClass('post-launch');
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // Update progress bar
 | |
|                 var $targetProgress = $progress.removeClass('active').filter(function() {
 | |
|                     return $(this).index() <= targetIndex;
 | |
|                 }).toggleClass('active');
 | |
| 
 | |
|                 setTimeout(function() {
 | |
|                     if (!$targetStep.find('input[type=radio]:checked').length) {
 | |
|                         $targetStep.find('input[type=radio]:first').click();
 | |
|                     }
 | |
|                 }, 50);
 | |
| 
 | |
|                 $targetStep.find('form').validate();
 | |
|             };
 | |
| 
 | |
|             // Events
 | |
|             $wizard.find('select').change(function(event) {
 | |
|                 // Conditional selects (on step 4 mainly)
 | |
|                 var $target = $(this);
 | |
|                 var $tagged = $wizard.find('.conditional.vlan-type-tagged');
 | |
|                 var $untagged = $wizard.find('.conditional.vlan-type-untagged');
 | |
|                 var $accountSpecific = $wizard.find('.field.conditional.ip-scope-account-specific');
 | |
| 
 | |
|                 // VLAN - tagged
 | |
|                 if ($target.is('[name=vlan-type]')) {
 | |
|                     $tagged.hide();
 | |
|                     $untagged.hide();
 | |
|                     $accountSpecific.hide();
 | |
| 
 | |
|                     if ($target.val() == 'tagged') {
 | |
|                         $untagged.hide();
 | |
|                         $tagged.show();
 | |
|                     } else if ($target.val() == 'untagged') {
 | |
|                         $tagged.hide();
 | |
|                         $untagged.show();
 | |
|                     }
 | |
| 
 | |
|                     $.merge($tagged, $untagged).find('select:visible').trigger('change');
 | |
| 
 | |
|                     cloudStack.evenOdd($wizard, '.field:visible', {
 | |
|                         even: function($elem) {
 | |
|                             $elem.removeClass('odd');
 | |
|                             $elem.addClass('even');
 | |
|                         },
 | |
|                         odd: function($elem) {
 | |
|                             $elem.removeClass('even');
 | |
|                             $elem.addClass('odd');
 | |
|                         }
 | |
|                     });
 | |
| 
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // IP Scope - acct. specific
 | |
|                 if ($target.is('select.ip-scope')) {
 | |
|                     $accountSpecific.hide();
 | |
|                     if ($target.val() == 'account-specific') $accountSpecific.show();
 | |
| 
 | |
|                     cloudStack.evenOdd($wizard, '.field:visible', {
 | |
|                         even: function($elem) {
 | |
|                             $elem.removeClass('odd');
 | |
|                             $elem.addClass('even');
 | |
|                         },
 | |
|                         odd: function($elem) {
 | |
|                             $elem.removeClass('even');
 | |
|                             $elem.addClass('odd');
 | |
|                         }
 | |
|                     });
 | |
|                 }
 | |
| 
 | |
|                 return true;
 | |
|             });
 | |
| 
 | |
|             $wizard.click(function(event) {
 | |
|                 var $target = $(event.target);
 | |
| 
 | |
|                 // Radio button
 | |
|                 if ($target.is('[type=radio]')) {
 | |
| 
 | |
|                     if ($target.attr('name') == 'network-model') {
 | |
|                         var $inputs = $wizard.find('.isolation-mode').find('input[name=isolation-mode]').attr({
 | |
|                             disabled: 'disabled'
 | |
|                         });
 | |
| 
 | |
|                         var $selectArea = $target.closest('.select-area');
 | |
| 
 | |
|                         if ($target.val() == 'Advanced') {
 | |
|                             $inputs.attr('disabled', false);
 | |
|                             $selectArea.removeClass('disabled')
 | |
|                                 .find('.isolation-mode input').attr('disabled', false);
 | |
|                         } else if ($target.val() == 'Basic') {
 | |
|                             $selectArea.siblings('.advanced-zone').addClass('disabled')
 | |
|                                 .find('.isolation-mode input').attr('disabled', 'disabled');
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // Checkbox
 | |
|                 if ($target.is('[type=checkbox]:checked')) {
 | |
|                     $('div.conditional.' + $target.attr('name')).hide();
 | |
| 
 | |
|                     return true;
 | |
|                 } else if ($target.is('[type=checkbox]:unchecked')) {
 | |
|                     $('div.conditional.' + $target.attr('name')).show();
 | |
| 
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // Next button
 | |
|                 if ($target.closest('div.button.next').length) {
 | |
|                     var $step = $steps.filter(':visible');
 | |
|                     // Validation
 | |
|                     var $form = $('form:visible').filter(function() {
 | |
|                         // Don't include multi-edit (validation happens separately)
 | |
|                         return !$(this).closest('.multi-edit').length;
 | |
|                     });
 | |
| 
 | |
|                     // Handle validation for custom UI components
 | |
|                     var isCustomValidated = checkCustomValidation($step);
 | |
|                     if (($form.length && !$form.valid()) || !isCustomValidated) {
 | |
|                         if (($form && $form.find('.error:visible').length) || !isCustomValidated)
 | |
|                             return false;
 | |
|                     }
 | |
| 
 | |
|                     //when hypervisor is BareMetal (begin)
 | |
|                     var data = getData($wizard);
 | |
|                     if (('zone' in data) && (data.zone.hypervisor == 'BareMetal')) {
 | |
|                         if ($('.zone-wizard:visible').find('#add_zone_guest_traffic_desc:visible').length > 0) { //$steps.filter(':visible').index() == 6
 | |
|                             showStep('launch');
 | |
|                             completeAction();
 | |
|                             return false;
 | |
|                         }
 | |
|                     }
 | |
|                     //when hypervisor is BareMetal (end)
 | |
| 
 | |
|                     if (!$target.closest('.button.next.final').length)
 | |
|                         showStep($steps.filter(':visible').index() + 2);
 | |
|                     else {
 | |
|                         if ($target.closest('.button.next.final.post-launch').length) {
 | |
|                             showStep('launch');
 | |
|                         }
 | |
| 
 | |
|                         completeAction();
 | |
|                     }
 | |
| 
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 // Previous button
 | |
|                 if ($target.closest('div.button.previous').length) {
 | |
|                     showStep($steps.filter(':visible').index(), true);
 | |
| 
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 // Close button
 | |
|                 if ($target.closest('div.button.cancel').length) {
 | |
|                     close();
 | |
| 
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 // Edit link
 | |
|                 if ($target.closest('div.edit').length) {
 | |
|                     var $edit = $target.closest('div.edit');
 | |
| 
 | |
|                     showStep($edit.find('a').attr('href'));
 | |
| 
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 // Edit traffic type button
 | |
|                 var $editTrafficTypeButton = $target.closest('.drop-container .traffic-type-draggable .edit-traffic-type');
 | |
|                 var $trafficType = $editTrafficTypeButton.closest('.traffic-type-draggable');
 | |
| 
 | |
|                 if ($editTrafficTypeButton.length) {
 | |
|                     physicalNetwork.editTrafficTypeDialog($trafficType);
 | |
| 
 | |
|                     return false;
 | |
|                 }
 | |
| 
 | |
|                 return true;
 | |
|             });
 | |
| 
 | |
|             // Add/remove network action
 | |
|             $wizard.find('.button.add.new-physical-network').click(function() {
 | |
|                 addPhysicalNetwork($wizard);
 | |
|             });
 | |
| 
 | |
|             // Traffic type draggables
 | |
|             $wizard.find('.traffic-type-draggable').draggable(physicalNetwork.draggableOptions($wizard));
 | |
| 
 | |
|             // For removing traffic types from physical network
 | |
|             $wizard.find('.traffic-types-drag-area').droppable({
 | |
|                 drop: function(event, ui) {
 | |
|                     physicalNetwork.unassignTrafficType(ui.draggable);
 | |
| 
 | |
|                     return true;
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             showStep(1);
 | |
| 
 | |
|             var $dialog = $wizard.dialog({
 | |
|                 title: _l('label.installWizard.addZone.title'),
 | |
|                 closeOnEscape: false,
 | |
|                 width: 750,
 | |
|                 height: 665,
 | |
|                 resizable: false
 | |
|             });
 | |
|             
 | |
|             return cloudStack.applyDefaultZindexAndOverlayOnJqueryDialogAndRemoveCloseButton($dialog);
 | |
|         };
 | |
|     };
 | |
| })(jQuery, cloudStack);
 |