diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 6699d163d97..66f43b185a2 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -48,7 +48,7 @@ item.issystem == true ) { return []; } - + if(item.networkOfferingConserveMode == false) { /* (1) If IP is SourceNat, no StaticNat/VPN/PortForwarding/LoadBalancer can be enabled/added. @@ -117,14 +117,13 @@ disallowedActions.push('disableStaticNAT'); } - if ($.inArray('Vpn', $.map(args.context.networks[0].service, - function(service) { return service.name; })) > -1) { + if(item.networkOfferingHavingVpnService == true) { if (item.vpnenabled) { disallowedActions.push('enableVPN'); } else { disallowedActions.push('disableVPN'); } - } else { + } else { //item.networkOfferingHavingVpnService == false disallowedActions.push('disableVPN'); disallowedActions.push('enableVPN'); } @@ -157,6 +156,8 @@ } }; + var networkOfferingObjs = []; + cloudStack.sections.network = { title: 'label.network', id: 'network', @@ -177,7 +178,7 @@ } }); - var sectionsToShow = ['networks', 'vpc']; + var sectionsToShow = ['networks', 'vpc', 'vpnCustomerGateway']; if(havingSecurityGroupNetwork == true) sectionsToShow.push('securityGroups'); @@ -262,9 +263,9 @@ state: 'Enabled' }, success: function(json) { - var networkOfferings = json.listnetworkofferingsresponse.networkoffering; + networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; args.response.success({ - data: $.map(networkOfferings, function(zone) { + data: $.map(networkOfferingObjs, function(zone) { return { id: zone.id, description: zone.name @@ -275,24 +276,74 @@ }); } }, + vpcid: { + label: 'VPC', + dependsOn: 'networkOfferingId', + select: function(args) { + var networkOfferingObj; + $(networkOfferingObjs).each(function(key, value) { + if(value.id == args.networkOfferingId) { + networkOfferingObj = value; + return false; //break each loop + } + }); + if(networkOfferingObj.forvpc == true) { + args.$select.closest('.form-item').css('display', 'inline-block'); + $.ajax({ + url: createURL('listVPCs'), + data: { + listAll: true + }, + success: function(json) { + var items = json.listvpcsresponse.vpc; + var data; + if(items != null && items.length > 0) { + data = $.map(items, function(item) { + return { + id: item.id, + description: item.name + } + }); + } + args.response.success({ data: data }); + } + }); + } + else { + args.$select.closest('.form-item').hide(); + args.response.success({ data: null }); + } + } + }, guestGateway: { label: 'label.guest.gateway' }, guestNetmask: { label: 'label.guest.netmask' } } }, action: function(args) { - var array1 = []; - array1.push("&zoneId=" + args.data.zoneId); - array1.push("&name=" + todb(args.data.name)); - array1.push("&displayText=" + todb(args.data.displayText)); - array1.push("&networkOfferingId=" + args.data.networkOfferingId); - - if(args.data.guestGateway != null && args.data.guestGateway.length > 0) - array1.push("&gateway=" + args.data.guestGateway); - if(args.data.guestNetmask != null && args.data.guestNetmask.length > 0) - array1.push("&netmask=" + args.data.guestNetmask); - + var dataObj = { + zoneId: args.data.zoneId, + name: args.data.name, + displayText: args.data.displayText, + networkOfferingId: args.data.networkOfferingId + }; + if(args.data.guestGateway != null && args.data.guestGateway.length > 0) { + $.extend(dataObj, { + gateway: args.data.guestGateway + }); + } + if(args.data.guestNetmask != null && args.data.guestNetmask.length > 0) { + $.extend(dataObj, { + netmask: args.data.guestNetmask + }); + } + if(args.$form.find('.form-item[rel=vpcid]').css("display") != "none") { + $.extend(dataObj, { + vpcid: args.data.vpcid + }); + } $.ajax({ - url: createURL('createNetwork' + array1.join("")), + url: createURL('createNetwork'), + data: dataObj, success: function(json) { args.response.success({ data: json.createnetworkresponse.network @@ -754,7 +805,17 @@ }, domain: { label: 'label.domain' }, - account: { label: 'label.account' } + account: { label: 'label.account' }, + + vpcid: { + label: 'VPC ID', + converter: function(args) { + if(args != null) + return args; + else + return 'N/A'; + } + } } ], dataProvider: function(args) { @@ -786,15 +847,23 @@ context: context, listView: $.extend(true, {}, cloudStack.sections.instances, { listView: { - dataProvider: function(args) { - $.ajax({ + dataProvider: function(args) { + var networkid; + if('vpc' in args.context) + networkid = args.context.multiData.tier; + else + networkid = args.context.ipAddresses[0].associatednetworkid; + + var data = { + page: args.page, + pageSize: pageSize, + networkid: networkid, + listAll: true + }; + + $.ajax({ url: createURL('listVirtualMachines'), - data: { - page: args.page, - pageSize: pageSize, - networkid: args.context.networks[0].id, - listAll: true - }, + data: data, dataType: 'json', async: true, success: function(data) { @@ -848,29 +917,37 @@ }, add: { label: 'label.add.vms', - action: function(args) { - var openFirewall = false; + action: function(args) { var data = { algorithm: args.data.algorithm, name: args.data.name, privateport: args.data.privateport, - publicport: args.data.publicport + publicport: args.data.publicport, + openfirewall: false, + domainid: g_domainid, + account: g_account }; + + if('vpc' in args.context) { //from VPC section + if(args.data.tier == null) { + args.response.error('Tier is required'); + return; + } + $.extend(data, { + networkid: args.data.tier + }); + } + else { //from Guest Network section + $.extend(data, { + networkid: args.context.networks[0].id + }); + } + var stickyData = $.extend(true, {}, args.data.sticky); - - var apiCmd = "createLoadBalancerRule"; - //if(args.context.networks[0].type == "Shared") - apiCmd += "&domainid=" + g_domainid + "&account=" + g_account; - //else //args.context.networks[0].type == "Isolated" - //apiCmd += "&account=" + args.context.users[0].account; - //apiCmd += '&domainid=' + args.context.users[0].domainid; - + $.ajax({ - url: createURL(apiCmd), - data: $.extend(data, { - openfirewall: openFirewall, - networkid: args.context.networks[0].id - }), + url: createURL('createLoadBalancerRule'), + data: data, dataType: 'json', async: true, success: function(data) { @@ -987,18 +1064,48 @@ actions: { add: { label: 'label.acquire.new.ip', - addRow: 'true', - action: function(args) { - var apiCmd = "associateIpAddress"; - if(args.context.networks[0].type == "Shared" && !args.context.projects) - apiCmd += "&domainid=" + g_domainid + "&account=" + g_account; + addRow: 'true', + preFilter: function(args) { + if('networks' in args.context) { //from Guest Network section + if(args.context.networks[0].vpcid == null) //if it's a non-VPC network, show Acquire IP button + return true; + else //if it's a VPC network, hide Acquire IP button + return false; + } + else { //from VPC section + return true; //show Acquire IP button + } + }, + messages: { + confirm: function(args) { + return 'message.acquire.new.ip'; + }, + notification: function(args) { + return 'label.acquire.new.ip'; + } + }, + action: function(args) { + var dataObj = {}; + if('vpc' in args.context) { //from VPC section + $.extend(dataObj, { + vpcid: args.context.vpc[0].id + }); + } + else if('networks' in args.context) { //from Guest Network section + $.extend(dataObj, { + networkid: args.context.networks[0].id + }); + + if(args.context.networks[0].type == "Shared" && !args.context.projects) { + $.extend(dataObj, { + domainid: g_domainid, + account: g_account + }); + } + } $.ajax({ - url: createURL(apiCmd), - data: { - networkId: args.context.networks[0].id - }, - dataType: 'json', - async: true, + url: createURL('associateIpAddress'), + data: dataObj, success: function(data) { args.response.success({ _custom: { @@ -1022,15 +1129,6 @@ }); }, - messages: { - confirm: function(args) { - return 'message.acquire.new.ip'; - }, - notification: function(args) { - return 'label.acquire.new.ip'; - } - }, - notification: { poll: pollAsyncJobResult } @@ -1069,6 +1167,13 @@ } } } + + if("vpc" in args.context) { + $.extend(data, { + vpcid: args.context.vpc[0].id + }); + } + $.ajax({ url: createURL("listPublicIpAddresses&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), data: data, @@ -1076,14 +1181,10 @@ async: true, success: function(json) { var items = json.listpublicipaddressesresponse.publicipaddress; - var processedItems = 0; - - if (!items) { - args.response.success({ - data: [] - }); - return; - } + + $(items).each(function() { + getExtaPropertiesForIpObj(this, args); + }); args.response.success({ actionFilter: actionFilters.ipAddress, @@ -1234,41 +1335,76 @@ 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; + if ('vpc' in args.context) { //from VPC section + args.$tierSelect.show(); //show tier dropdown - if (enableTiers) { - args.$tierSelect.show(); - args.response.success({ - data: [ - { id: '1', description: 'VPC 1' }, - { id: '2', description: 'VPC 2' } - ] + $.ajax({ //populate tier dropdown + url: createURL("listNetworks"), + async: false, + data: { + vpcid: args.context.vpc[0].id, + listAll: true, + supportedservices: 'StaticNat' + }, + success: function(json) { + var networks = json.listnetworksresponse.network; + var items = [{ id: -1, description: '' }]; + $(networks).each(function(){ + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({ data: items }); + } }); } + else { //from Guest Network section + args.$tierSelect.hide(); + } + + args.$tierSelect.change(function() { + args.$tierSelect.closest('.list-view').listView('refresh'); + }); }, listView: $.extend(true, {}, cloudStack.sections.instances, { listView: { dataProvider: function(args) { + var $listView = args.$listView; var data = { page: args.page, - pageSize: pageSize, - networkid: args.context.networks[0].id, + pageSize: pageSize, listAll: true }; + // See if tier is selected + var $tierSelect = $listView.find('.tier-select select'); + + if ($tierSelect.size() && $tierSelect.val() != '-1') { + data.networkid = $tierSelect.val(); + } + else { + args.response.success({ data: null }); + return; + } + + if('vpc' in args.context) { + $.extend(data, { + vpcid: args.context.vpc[0].id + }); + } + else if('networks' in args.context) { + $.extend(data, { + networkid: args.context.networks[0].id + }); + } + if (!args.context.projects) { $.extend(data, { account: args.context.ipAddresses[0].account, domainid: args.context.ipAddresses[0].domainid }); } - + $.ajax({ url: createURL('listVirtualMachines'), data: data, @@ -1294,13 +1430,25 @@ } } }), - action: function(args) { + action: function(args) { + var data = { + ipaddressid: args.context.ipAddresses[0].id, + virtualmachineid: args.context.instances[0].id + }; + + if('vpc' in args.context) { + if(args.tierID == '-1') { + args.response.error('Tier is required'); + return; + } + $.extend(data, { + networkid: args.tierID + }); + } + $.ajax({ url: createURL('enableStaticNat'), - data: { - ipaddressid: args.context.ipAddresses[0].id, - virtualmachineid: args.context.instances[0].id - }, + data: data, dataType: 'json', async: true, success: function(data) { @@ -1480,46 +1628,19 @@ $.ajax({ url: createURL('listPublicIpAddresses'), data: { - id: args.context.ipAddresses[0].id + id: args.context.ipAddresses[0].id, + listAll: true }, 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 - }); - } - }); - } - }); + success: function(json) { + var ipObj = json.listpublicipaddressesresponse.publicipaddress[0]; + getExtaPropertiesForIpObj(ipObj, args); + + args.response.success({ + actionFilter: actionFilters.ipAddress, + data: ipObj + }); }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); @@ -1531,38 +1652,79 @@ ipRules: { //Configuration tab title: 'label.configuration', custom: cloudStack.ipRules({ - preFilter: function(args) { + preFilter: function(args) { var disallowedActions = []; if (args.context.ipAddresses[0].isstaticnat) disallowedActions.push("nonStaticNATChart"); //tell ipRules widget to show staticNAT chart instead of non-staticNAT chart. - - var networkOfferingHavingFirewallService = false; - var networkOfferingHavingPortForwardingService = false; - var networkOfferingHavingLbService = false; - $.ajax({ - url: createURL("listNetworkOfferings&id=" + args.context.networks[0].networkofferingid), - dataType: "json", - async: false, - success: function(json) { - var networkoffering = json.listnetworkofferingsresponse.networkoffering[0]; - $(networkoffering.service).each(function(){ - var thisService = this; - if(thisService.name == "Firewall") - networkOfferingHavingFirewallService = true; - if(thisService.name == "PortForwarding") - networkOfferingHavingPortForwardingService = true; - if(thisService.name == "Lb") - networkOfferingHavingLbService = true; - }); - } - }); + var havingFirewallService = false; + var havingPortForwardingService = false; + var havingLbService = false; + var havingVpnService = false; + + if('networks' in args.context && args.context.networks[0].vpcid == null) { //a non-VPC network from Guest Network section + $.ajax({ + url: createURL("listNetworkOfferings&id=" + args.context.networks[0].networkofferingid), + dataType: "json", + async: false, + success: function(json) { + var networkoffering = json.listnetworkofferingsresponse.networkoffering[0]; + $(networkoffering.service).each(function(){ + var thisService = this; + if(thisService.name == "Firewall") + havingFirewallService = true; + if(thisService.name == "PortForwarding") + havingPortForwardingService = true; + if(thisService.name == "Lb") + havingLbService = true; + if(thisService.name == "Vpn") + havingVpnService = true; + }); + } + }); + } + else { //a VPC network from Guest Network section or from VPC section + havingFirewallService = false; //firewall is not supported in IP from VPC section (because ACL has already supported in tier from VPC section) + havingVpnService = false; //VPN is not supported in IP from VPC section + + if(args.context.ipAddresses[0].associatednetworkid == null) { //IP is not associated with any tier yet + havingPortForwardingService = true; + havingLbService = true; + } + else { //IP is associated with a tier + $.ajax({ + url: createURL("listNetworks&id=" + args.context.ipAddresses[0].associatednetworkid), + async: false, + success: function(json) { + var networkObj = json.listnetworksresponse.network[0]; + $.ajax({ + url: createURL("listNetworkOfferings&id=" + networkObj.networkofferingid), + async: false, + success: function(json) { + var networkoffering = json.listnetworkofferingsresponse.networkoffering[0]; + $(networkoffering.service).each(function(){ + var thisService = this; + if(thisService.name == "PortForwarding") + havingPortForwardingService = true; + if(thisService.name == "Lb") + havingLbService = true; + }); + } + }); + } + }); + } + } 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){ + if(havingFirewallService == false) { //firewall is not supported in IP from VPC section (because ACL has already supported in tier from VPC section) + disallowedActions.push("firewall"); + } + disallowedActions.push("portForwarding"); disallowedActions.push("loadBalancing"); } @@ -1570,16 +1732,23 @@ /* (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. + 2. If VPN service is supported (i.e. IP comes from Guest Network section, not from VPC section), 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 + else { //args.context.ipAddresses[0].issourcenat == false + if(havingFirewallService == false) + disallowedActions.push("firewall"); + if(havingPortForwardingService == false) + disallowedActions.push("portForwarding"); + if(havingLbService == false) + disallowedActions.push("loadBalancing"); + 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. + if (havingVpnService && args.context.ipAddresses[0].vpnenabled) { //2. If VPN service is supported (i.e. IP comes from Guest Network section, not from VPC section), once VPN is enabled, hide StaticNat/PortForwarding/LoadBalancer. disallowedActions.push("portForwarding"); disallowedActions.push("loadBalancing"); } @@ -1620,14 +1789,7 @@ }); } } - - if(networkOfferingHavingFirewallService == false) - disallowedActions.push("firewall"); - if(networkOfferingHavingPortForwardingService == false) - disallowedActions.push("portForwarding"); - if(networkOfferingHavingLbService == false) - disallowedActions.push("loadBalancing"); - + return disallowedActions; }, @@ -1772,15 +1934,17 @@ $.ajax({ url: createURL('listPublicIpAddresses'), data: { - id: args.context.ipAddresses[0].id + id: args.context.ipAddresses[0].id, + listAll: true }, dataType: 'json', async: true, - success: function(data) { - var ipAddress = data.listpublicipaddressesresponse.publicipaddress[0]; - + success: function(data) { + var ipObj = data.listpublicipaddressesresponse.publicipaddress[0]; + getExtaPropertiesForIpObj(ipObj, args); + args.response.success({ - data: ipAddress + data: ipObj }); }, error: function(data) { @@ -1924,10 +2088,17 @@ dataProvider: function(args) { var itemData = $.isArray(args.context.multiRule) && args.context.multiRule[0]['_itemData'] ? args.context.multiRule[0]['_itemData'] : []; + + var networkid; + if('vpc' in args.context) + networkid = args.context.multiData.tier; + else + networkid = args.context.ipAddresses[0].associatednetworkid; + var data = { page: args.page, pageSize: pageSize, - networkid: args.context.ipAddresses[0].associatednetworkid, + networkid: networkid, listAll: true }; @@ -1971,15 +2142,36 @@ headerFields: { tier: { label: 'Tier', - select: function(args) { - args.response.success({ - data: [ - { id: '', name: '', description: 'None' }, - { id: '1', name: 'tier1', description: 'tier1' }, - { id: '2', name: 'tier2', description: 'tier2' }, - { id: '3', name: 'tier3', description: 'tier3' } - ] - }); + select: function(args) { + if('vpc' in args.context) { + var data = { + listAll: true, + supportedservices: 'Lb' + }; + if(args.context.ipAddresses[0].associatednetworkid == null) { + $.extend(data, { + vpcid: args.context.vpc[0].id + }); + } + else { + $.extend(data, { + id: args.context.ipAddresses[0].associatednetworkid + }); + } + + $.ajax({ + url: createURL("listNetworks"), + data: data, + success: function(json) { + var networks = json.listnetworksresponse.network; + var items = []; + $(networks).each(function(){ + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({ data: items }); + } + }); + } } } }, @@ -2016,28 +2208,33 @@ }, add: { label: 'label.add.vms', - action: function(args) { - var openFirewall = false; + action: function(args) { + var networkid; + if('vpc' in args.context) { //from VPC section + if(args.data.tier == null) { + args.response.error('Tier is required'); + return; + } + networkid = args.data.tier; + } + else if('networks' in args.context) { //from Guest Network section + networkid = args.context.networks[0].id; + } var data = { algorithm: args.data.algorithm, name: args.data.name, privateport: args.data.privateport, - publicport: args.data.publicport + publicport: args.data.publicport, + openfirewall: false, + networkid: networkid, + publicipid: args.context.ipAddresses[0].id }; - var stickyData = $.extend(true, {}, args.data.sticky); - - var apiCmd = "createLoadBalancerRule"; - //if(args.context.networks[0].type == "Shared") - //apiCmd += "&domainid=" + g_domainid + "&account=" + g_account; - //else //args.context.networks[0].type == "Isolated" - apiCmd += "&publicipid=" + args.context.ipAddresses[0].id; + + var stickyData = $.extend(true, {}, args.data.sticky); $.ajax({ - url: createURL(apiCmd), - data: $.extend(data, { - openfirewall: openFirewall, - networkid: args.context.networks[0].id - }), + url: createURL('createLoadBalancerRule'), + data: data, dataType: 'json', async: true, success: function(data) { @@ -2311,15 +2508,36 @@ } }); - // Check if tiers are present; hide/show header drop-down - var hasTiers = false; - var $headerFields = $multi.find('.header-fields'); - - if (hasTiers) { - $headerFields.hide(); - } else { - $headerFields.show(); - } + // Check if tiers are present; hide/show header drop-down (begin) *** + //dataProvider() is called when a LB rule is added in multiEdit. However, adding a LB rule might change parent object (IP Address object). So, we have to force to refresh args.context.ipAddresses[0] here + $.ajax({ + url: createURL('listPublicIpAddresses'), + data: { + id: args.context.ipAddresses[0].id, + listAll: true + }, + success: function(json) { + var ipObj = json.listpublicipaddressesresponse.publicipaddress[0]; + getExtaPropertiesForIpObj(ipObj, args); + + args.context.ipAddresses.shift(); //remove the first element in args.context.ipAddresses + args.context.ipAddresses.push(ipObj); + + var $headerFields = $multi.find('.header-fields'); + if ('vpc' in args.context) { + if(args.context.ipAddresses[0].associatednetworkid == null) { + $headerFields.show(); + } + else { + $headerFields.hide(); + } + } + else if('networks' in args.context){ + $headerFields.hide(); + } + } + }); + // Check if tiers are present; hide/show header drop-down (end) *** } }, @@ -2329,25 +2547,51 @@ tier: { label: 'Tier', select: function(args) { - args.response.success({ - data: [ - { id: '', name: '', description: 'None' }, - { id: '1', name: 'tier1', description: 'tier1' }, - { id: '2', name: 'tier2', description: 'tier2' }, - { id: '3', name: 'tier3', description: 'tier3' } - ] - }); + if('vpc' in args.context) { + var data = { + listAll: true, + supportedservices: 'PortForwarding' + }; + if(args.context.ipAddresses[0].associatednetworkid == null) { + $.extend(data, { + vpcid: args.context.vpc[0].id + }); + } + else { + $.extend(data, { + id: args.context.ipAddresses[0].associatednetworkid + }); + } + $.ajax({ + url: createURL("listNetworks"), + data: data, + success: function(json) { + var networks = json.listnetworksresponse.network; + var items = []; + $(networks).each(function(){ + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({ data: items }); + } + }); + } } } }, listView: $.extend(true, {}, cloudStack.sections.instances, { listView: { dataProvider: function(args) { - var data = { + var networkid; + if('vpc' in args.context) + networkid = args.context.multiData.tier; + else + networkid = args.context.ipAddresses[0].associatednetworkid; + + var data = { page: args.page, pageSize: pageSize, listAll: true, - networkid: args.context.ipAddresses[0].associatednetworkid + networkid: networkid }; if (!args.context.projects) { @@ -2413,19 +2657,34 @@ }, add: { label: 'label.add.vm', - action: function(args) { - var openFirewall = false; - + action: function(args) { + var data = { + ipaddressid: args.context.ipAddresses[0].id, + privateport: args.data.privateport, + publicport: args.data.publicport, + protocol: args.data.protocol, + virtualmachineid: args.itemData[0].id, + openfirewall: false + }; + + if('vpc' in args.context) { //from VPC section + if(args.data.tier == null) { + args.response.error('Tier is required'); + return; + } + $.extend(data, { + networkid: args.data.tier + }); + } + else { //from Guest Network section + $.extend(data, { + networkid: args.context.networks[0].id + }); + } + $.ajax({ url: createURL('createPortForwardingRule'), - - data: $.extend(args.data, { - openfirewall: openFirewall, - ipaddressid: args.context.ipAddresses[0].id, - virtualmachineid: args.itemData[0].id - }), - dataType: 'json', - async: true, + data: data, success: function(data) { args.response.success({ _custom: { @@ -2528,16 +2787,37 @@ } }); }); - - // Check if tiers are present; hide/show header drop-down - var hasTiers = false; - var $headerFields = $multi.find('.header-fields'); - - if (hasTiers) { - $headerFields.hide(); - } else { - $headerFields.show(); - } + + // Check if tiers are present; hide/show header drop-down (begin) *** + //dataProvider() is called when a PF rule is added in multiEdit. However, adding a LB rule might change parent object (IP Address object). So, we have to force to refresh args.context.ipAddresses[0] here + $.ajax({ + url: createURL('listPublicIpAddresses'), + data: { + id: args.context.ipAddresses[0].id, + listAll: true + }, + success: function(json) { + var ipObj = json.listpublicipaddressesresponse.publicipaddress[0]; + getExtaPropertiesForIpObj(ipObj, args); + + args.context.ipAddresses.shift(); //remove the first element in args.context.ipAddresses + args.context.ipAddresses.push(ipObj); + + var $headerFields = $multi.find('.header-fields'); + if ('vpc' in args.context) { + if(args.context.ipAddresses[0].associatednetworkid == null) { + $headerFields.show(); + } + else { + $headerFields.hide(); + } + } + else if('networks' in args.context){ + $headerFields.hide(); + } + } + }); + // Check if tiers are present; hide/show header drop-down (end) *** }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); @@ -3188,84 +3468,660 @@ id: 'vpc', label: 'VPC', fields: { - name: { label: 'Name' }, - zone: { label: 'Zone' }, - cidr: { label: 'CIDR' } + name: { label: 'label.name' }, + displaytext: { label: 'label.description' }, + zonename: { label: 'label.zone' }, + cidr: { label: 'label.cidr' } }, - dataProvider: function(args) { - args.response.success({ - data: [ - { - name: 'VPC 1', - zone: 'San Jose', - cidr: '0.0.0.0/0', - networkdomain: 'testdomain', - accountdomain: 'testdomain' - }, - { - name: 'VPC 2', - zone: 'San Jose', - cidr: '0.0.0.0/0', - networkdomain: 'testdomain', - accountdomain: 'testdomain' - }, - { - name: 'VPC 3', - zone: 'Cupertino', - cidr: '0.0.0.0/0', - networkdomain: 'testdomain', - accountdomain: 'testdomain' - }, - { - name: 'VPC 4', - zone: 'San Jose', - cidr: '0.0.0.0/0', - networkdomain: 'testdomain', - accountdomain: 'testdomain' - } - ] - }); + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + + $.ajax({ + url: createURL("listVPCs&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var items = json.listvpcsresponse.vpc; + args.response.success({data:items}); + } + }); }, actions: { add: { - label: 'Add VPC', + label: 'Add VPC', + messages: { + notification: function(args) { + return 'Add VPC'; + } + }, createForm: { - title: 'Add new VPC', + title: 'Add VPC', + messages: { + notification: function(args) { + return 'Add VPC'; + } + }, fields: { - name: { label: 'Name', validation: { required: true } }, - zone: { + name: { + label: 'label.name', + validation: { required: true } + }, + displaytext: { + label: 'label.description', + validation: { required: true } + }, + zoneid: { label: 'Zone', validation: { required: true }, select: function(args) { - args.response.success({ - data: [ - { id: 'zone1', description: 'Zone 1' }, - { id: 'zone2', description: 'Zone 2' }, - { id: 'zone3', description: 'Zone 3' } - ] + var data = { listAll: true }; + $.ajax({ + url: createURL('listZones'), + data: data, + success: function(json) { + var zones = json.listzonesresponse.zone; + var advZones = $.grep(zones, function(zone) { + return zone.networktype == 'Advanced'; + }); + args.response.success({ + data: $.map(advZones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } }); } - } + }, + cidr: { + label: 'label.cidr', + validation: { required: true } + }, + networkdomain: { + label: 'label.network.domain' + } } + }, + action: function(args) { + var defaultvpcofferingid; + $.ajax({ + url: createURL("listVPCOfferings"), + dataType: "json", + data: { + isdefault: true + }, + async: false, + success: function(json) { + defaultvpcofferingid = json.listvpcofferingsresponse.vpcoffering[0].id; + } + }); + + var dataObj = { + name: args.data.name, + displaytext: args.data.displaytext, + zoneid: args.data.zoneid, + cidr: args.data.cidr, + vpcofferingid: defaultvpcofferingid + }; + + if(args.data.networkdomain != null && args.data.networkdomain.length > 0) + $.extend(dataObj, { networkdomain: args.data.networkdomain }); + + $.ajax({ + url: createURL("createVPC"), + dataType: "json", + data: dataObj, + async: true, + success: function(json) { + var jid = json.createvpcresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpc; + } + } + } + ); + } + }); }, - messages: { - notification: function(args) { return 'Add new VPC'; } - }, - action: function(args) { - args.response.success(); - }, - notification: { poll: function(args) { args.complete(); } } + + notification: { + poll: pollAsyncJobResult + } + }, - editVpc: { - label: 'Edit VPC', + configureVpc: { + label: 'Configure VPC', + textLabel: 'label.configure', action: { custom: cloudStack.uiCustom.vpc(cloudStack.vpc) } } + }, + + detailView: { + name: 'label.details', + actions: { + configureVpc: { + label: 'Edit VPC', + textLabel: 'label.configure', + action: { + custom: cloudStack.uiCustom.vpc(cloudStack.vpc) + }, + messages: { notification: function() { return ''; } } + }, + + edit: { + label: 'label.edit', + action: function(args) { + $.ajax({ + url: createURL('updateVPC'), + data: { + id: args.context.vpc[0].id, + name: args.data.name, + displaytext: args.data.displaytext + }, + success: function(json) { + var jid = json.updatevpcresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpc; + } + } + } + ); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + restart: { + label: 'restart VPC', + messages: { + confirm: function(args) { + return 'Please confirm that you want to restart the VPC'; + }, + notification: function(args) { + return 'restart VPC'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("restartVPC"), + data: { + id: args.context.vpc[0].id + }, + success: function(json) { + var jid = json.restartvpcresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpc; + } + } + } + ); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + remove: { + label: 'remove VPC', + messages: { + confirm: function(args) { + return 'Please confirm that you want to delete the VPC'; + }, + notification: function(args) { + return 'remove VPC'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteVPC"), + data: { + id: args.context.vpc[0].id + }, + success: function(json) { + var jid = json.deletevpcresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name', isEditable: true } + }, + { + displaytext: { label: 'label.description', isEditable: true }, + zonename: { label: 'label.zone' }, + cidr: { label: 'label.cidr' }, + networkdomain: { label: 'label.network.domain' }, + state: { label: 'label.state' }, + id: { label: 'label.id' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listVPCs"), + dataType: "json", + data: { + id: args.context.vpc[0].id + }, + async: true, + success: function(json) { + var item = json.listvpcsresponse.vpc[0]; + args.response.success({data: item}); + } + }); + } + } + } + } + } + }, + + vpnCustomerGateway: { + type: 'select', + title: 'VPN Customer Gateway', + listView: { + id: 'vpnCustomerGateway', + label: 'VPN Customer Gateway', + fields: { + gateway: { label: 'label.gateway' }, + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' } + }, + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + + $.ajax({ + url: createURL("listVpnCustomerGateways&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var items = json.listvpncustomergatewaysresponse.vpncustomergateway; + args.response.success({data: items}); + } + }); + }, + + actions: { + add: { + label: 'add VPN Customer Gateway', + messages: { + notification: function(args) { + return 'add VPN Customer Gateway'; + } + }, + createForm: { + title: 'add VPN Customer Gateway', + fields: { + gateway: { + label: 'label.gateway', + validation: { required: true } + }, + cidrlist: { + label: 'CIDR list', + validation: { required: true } + }, + ipsecpsk: { + label: 'IPsec Preshared-Key', + validation: { required: true } + }, + ikepolicy: { + label: 'IKE policy', + select: function(args) { + var items = []; + items.push({id: '3des-md5', description: '3des-md5'}); + items.push({id: 'aes-md5', description: 'aes-md5'}); + items.push({id: 'aes128-md5', description: 'aes128-md5'}); + items.push({id: 'des-md5', description: 'des-md5'}); + items.push({id: '3des-sha1', description: '3des-sha1'}); + items.push({id: 'aes-sha1', description: 'aes-sha1'}); + items.push({id: 'aes128-sha1', description: 'aes128-sha1'}); + items.push({id: 'des-sha1', description: 'des-sha1'}); + args.response.success({data: items}); + } + }, + esppolicy: { + label: 'ESP policy', + select: function(args) { + var items = []; + items.push({id: '3des-md5', description: '3des-md5'}); + items.push({id: 'aes-md5', description: 'aes-md5'}); + items.push({id: 'aes128-md5', description: 'aes128-md5'}); + + items.push({id: '3des-sha1', description: '3des-sha1'}); + items.push({id: 'aes-sha1', description: 'aes-sha1'}); + items.push({id: 'aes128-sha1', description: 'aes128-sha1'}); + args.response.success({data: items}); + } + }, + lifetime: { + label: 'Lifetime (second)', + defaultValue: '86400', + validation: { required: false, number: true } + } + } + }, + action: function(args) { + $.ajax({ + url: createURL('createVpnCustomerGateway'), + data: { + gateway: args.data.gateway, + cidrlist: args.data.cidrlist, + ipsecpsk: args.data.ipsecpsk, + ikepolicy: args.data.ikepolicy, + esppolicy: args.data.esppolicy, + lifetime: args.data.lifetime + }, + dataType: 'json', + success: function(json) { + var jid = json.createvpncustomergatewayresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpncustomergateway; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + detailView: { + name: 'label.details', + actions: { + add: { + addRow: 'false', + label: 'Create VPN Connection', + messages: { + confirm: function(args) { + return 'Are you sure you want to create VPN connection ?'; + }, + notification: function(args) { + return 'Create VPN Connection'; + } + }, + createForm: { + title: 'Create VPN Connection', + fields: { + zoneid: { + label: 'Zone', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL('listZones'), + data: { + available: true + }, + success: function(json) { + var zones = json.listzonesresponse.zone; + args.response.success({ + data: $.map(zones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + }); + } + }, + vpcid: { + label: 'VPC', + validation: { required: true }, + dependsOn: 'zoneid', + select: function(args) { + $.ajax({ + url: createURL('listVPCs'), + data: { + zoneid: args.zoneid, + listAll: true + }, + success: function(json) { + var items = json.listvpcsresponse.vpc; + var data; + if(items != null && items.length > 0) { + data = $.map(items, function(item) { + return { + id: item.id, + description: item.name + } + }); + } + args.response.success({ data: data }); + } + }); + } + } + } + }, + action: function(args) { + var vpngatewayid = null; + $.ajax({ + url: createURL('listVpnGateways'), + data: { + vpcid: args.data.vpcid + }, + async: false, + success: function(json) { + var items = json.listvpngatewaysresponse.vpngateway; + if(items != null && items.length > 0) { + vpngatewayid = items[0].id; + } + } + }); + + if(vpngatewayid == null) { + args.response.error('The selected VPC does not have a VPN gateway. Please create a VPN gateway for the VPC first.'); + return; + } + + $.ajax({ + url: createURL('createVpnConnection'), + data: { + s2svpngatewayid: vpngatewayid, + s2scustomergatewayid: args.context.vpnCustomerGateway[0].id + }, + success: function(json) { + var jid = json.createvpnconnectionresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + remove: { + label: 'delete VPN Customer Gateway', + messages: { + confirm: function(args) { + return 'Please confirm that you want to delete this VPN Customer Gateway'; + }, + notification: function(args) { + return 'delete VPN Customer Gateway'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteVpnCustomerGateway"), + data: { + id: args.context.vpnCustomerGateway[0].id + }, + success: function(json) { + var jid = json.deletecustomergatewayresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + tabs: { + details: { + title: 'label.details', + fields: [ + { + gateway: { label: 'label.gateway' } + }, + { + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' }, + id: { label: 'label.id' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listVpnCustomerGateways"), + data: { + id: args.context.vpnCustomerGateway[0].id + }, + success: function(json) { + var item = json.listvpncustomergatewaysresponse.vpncustomergateway[0]; + args.response.success({data: item}); + } + }); + } + } + } } } } } }; - + + function getExtaPropertiesForIpObj(ipObj, args){ + if('networks' in args.context) { //from Guest Network section + //get ipObj.networkOfferingConserveMode and ipObj.networkOfferingHavingVpnService from guest network's network offering + $.ajax({ + url: createURL('listNetworkOfferings'), + data: { + id: args.context.networks[0].networkofferingid + }, + async: false, + success: function(json) { + var networkOfferingObj = json.listnetworkofferingsresponse.networkoffering[0]; + ipObj.networkOfferingConserveMode = networkOfferingObj.conservemode; + + $(networkOfferingObj.service).each(function(){ + var thisService = this; + if(thisService.name == "Vpn") + ipObj.networkOfferingHavingVpnService = true; + }); + + if(ipObj.networkOfferingHavingVpnService == true) { + $.ajax({ + url: createURL('listRemoteAccessVpns'), + data: { + listAll: true, + publicipid: ipObj.id + }, + async: false, + success: function(vpnResponse) { + var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count; + if (isVPNEnabled) { + ipObj.vpnenabled = true; + ipObj.remoteaccessvpn = vpnResponse.listremoteaccessvpnsresponse.remoteaccessvpn[0]; + }; + } + }); + } + } + }); + } + else { //from VPC section + ipObj.networkOfferingConserveMode = false; //conserve mode of IP in VPC is always off, so hardcode it as false + ipObj.networkOfferingHavingVpnService = false; //VPN is not supported in IP in VPC, so hardcode it as false + } + } + })(cloudStack, jQuery); + diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 0b0e738bf0e..11999fba9c0 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -14,242 +14,150 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + (function($, cloudStack) { - var aclMultiEdit = { - noSelect: true, - fields: { - 'cidrlist': { edit: true, label: 'Source CIDR' }, - 'protocol': { - label: 'Protocol', - select: function(args) { - args.$select.change(function() { - var $inputs = args.$form.find('input'); - var $icmpFields = $inputs.filter(function() { - var name = $(this).attr('name'); + var aclMultiEdit = { + noSelect: true, + fields: { + 'cidrlist': { edit: true, label: 'label.cidr.list' }, + 'protocol': { + label: 'label.protocol', + select: function(args) { + args.$select.change(function() { + var $inputs = args.$form.find('input'); + var $icmpFields = $inputs.filter(function() { + var name = $(this).attr('name'); - return $.inArray(name, [ - 'icmptype', - 'icmpcode' - ]) > -1; - }); - var $otherFields = $inputs.filter(function() { - var name = $(this).attr('name'); + return $.inArray(name, [ + 'icmptype', + 'icmpcode' + ]) > -1; + }); + var $otherFields = $inputs.filter(function() { + var name = $(this).attr('name'); - return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist'; - }); + return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist'; + }); - if ($(this).val() == 'icmp') { - $icmpFields.attr('disabled', false); - $otherFields.attr('disabled', 'disabled'); - } else { - $otherFields.attr('disabled', false); - $icmpFields.attr('disabled', 'disabled'); - } - }); + if ($(this).val() == 'icmp') { + $icmpFields.show(); + $icmpFields.attr('disabled', false); + $otherFields.attr('disabled', 'disabled'); + $otherFields.hide(); + $otherFields.parent().find('label.error').hide(); + } else { + $otherFields.show(); + $otherFields.parent().find('label.error').hide(); + $otherFields.attr('disabled', false); + $icmpFields.attr('disabled', 'disabled'); + $icmpFields.hide(); + $icmpFields.parent().find('label.error').hide(); + } + }); - args.response.success({ - data: [ - { name: 'tcp', description: 'TCP' }, - { name: 'udp', description: 'UDP' }, - { name: 'icmp', description: 'ICMP' } - ] - }); - } - }, - 'startport': { edit: true, label: 'Start Port' }, - 'endport': { edit: true, label: 'End Port' }, - 'icmptype': { edit: true, label: 'ICMP Type', isDisabled: true }, - 'icmpcode': { edit: true, label: 'ICMP Code', isDisabled: true }, - 'add-rule': { - label: 'Add', - addButton: true - } - }, + args.response.success({ + data: [ + { name: 'tcp', description: 'TCP' }, + { name: 'udp', description: 'UDP' }, + { name: 'icmp', description: 'ICMP' } + ] + }); + } + }, + 'startport': { edit: true, label: 'label.start.port' }, + 'endport': { edit: true, label: 'label.end.port' }, + 'icmptype': { edit: true, label: 'ICMP.type', isDisabled: true }, + 'icmpcode': { edit: true, label: 'ICMP.code', isDisabled: true }, + 'traffictype' : { + label: 'Traffic type', + select: function(args) { + args.response.success({ + data: [ + { name: 'Ingress', description: 'Ingress' }, + { name: 'Egress', description: 'Egress' } + ] + }); + } + }, + 'add-rule': { + label: 'label.add.rule', + addButton: true + } + }, add: { label: 'Add', - action: function(args) { - setTimeout(function() { - args.response.success({ - notification: { - label: 'Add ACL rule', - poll: function(args) { args.complete(); } - } - }); - }, 500); + action: function(args) { + $.ajax({ + url: createURL('createNetworkACL'), + data: $.extend(args.data, { + networkid: args.context.networks[0].id + }), + dataType: 'json', + success: function(data) { + args.response.success({ + _custom: { + jobId: data.createnetworkaclresponse.jobid + }, + notification: { + label: 'Add ACL', + poll: pollAsyncJobResult + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); } }, actions: { destroy: { - label: 'Remove Rule', - action: function(args) { - setTimeout(function() { - args.response.success({ - notification: { - label: 'Remove ACL rule', - poll: function(args) { args.complete(); } - } - }); - }, 500); + label: 'Remove ACL', + action: function(args) { + $.ajax({ + url: createURL('deleteNetworkACL'), + data: { + id: args.context.multiRule[0].id + }, + dataType: 'json', + async: true, + success: function(data) { + var jobID = data.deletenetworkaclresponse.jobid; + args.response.success({ + _custom: { + jobId: jobID + }, + notification: { + label: 'Remove ACL', + poll: pollAsyncJobResult + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); } } }, - dataProvider: function(args) { - setTimeout(function() { - args.response.success({ - data: [ - { - "id": 11, - "protocol": "icmp", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/0", - "icmptype": 2, - "icmpcode": 22 - }, - { - "id": 10, - "protocol": "udp", - "startport": "500", - "endport": "10000", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 9, - "protocol": "tcp", - "startport": "20", - "endport": "200", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 11, - "protocol": "icmp", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/0", - "icmptype": 2, - "icmpcode": 22 - }, - { - "id": 10, - "protocol": "udp", - "startport": "500", - "endport": "10000", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 9, - "protocol": "tcp", - "startport": "20", - "endport": "200", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 11, - "protocol": "icmp", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/0", - "icmptype": 2, - "icmpcode": 22 - }, - { - "id": 10, - "protocol": "udp", - "startport": "500", - "endport": "10000", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 9, - "protocol": "tcp", - "startport": "20", - "endport": "200", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 11, - "protocol": "icmp", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/0", - "icmptype": 2, - "icmpcode": 22 - }, - { - "id": 10, - "protocol": "udp", - "startport": "500", - "endport": "10000", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 9, - "protocol": "tcp", - "startport": "20", - "endport": "200", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 11, - "protocol": "icmp", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/0", - "icmptype": 2, - "icmpcode": 22 - }, - { - "id": 10, - "protocol": "udp", - "startport": "500", - "endport": "10000", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - }, - { - "id": 9, - "protocol": "tcp", - "startport": "20", - "endport": "200", - "ipaddressid": 4, - "ipaddress": "10.223.71.23", - "state": "Active", - "cidrlist": "0.0.0.0/24" - } - ] - }); - }, 100); + dataProvider: function(args) { + $.ajax({ + url: createURL('listNetworkACLs'), + data: { + listAll: true, + networkid: args.context.networks[0].id + }, + dataType: 'json', + async: true, + success: function(json) { + args.response.success({ + data: json.listnetworkaclsresponse.networkacl + }); + }, + error: function(XMLHttpResponse) { + args.response.error(parseXMLHttpResponse(XMLHttpResponse)); + } + }); } }; @@ -278,143 +186,1540 @@ }, // List view actions - actions: { - restart: { - label: 'Restart instance', - action: function(args) { - setTimeout(function() { - args.response.success({ - data: { - state: 'Restarting' - } - }); - }, 1000); - }, - messages: { - confirm: function(args) { - return 'Are you sure you want to restart ' + args.name + '?'; - }, - notification: function(args) { - return 'Rebooting VM: ' + args.name; - } - }, - notification: { - poll: function(args) { args.complete(); } - } - }, - stop: { - label: 'Stop instance', - action: function(args) { - setTimeout(function() { - args.response.success({ - data: { state: 'Stopping' } - }); - }, 500); - }, - messages: { - confirm: function(args) { - return 'Are you sure you want to shutdown ' + args.name + '?'; - }, - notification: function(args) { - return 'Rebooting VM: ' + args.name; - } - }, - notification: { - poll: function(args) { args.complete(); } - } - }, - start: { - label: 'Start instance', - action: function(args) { - setTimeout(function() { - args.response.success({ - data: { state: 'Starting' } - }); - }, 500); - }, - messages: { - confirm: function(args) { - return 'Are you sure you want to start ' + args.name + '?'; - }, - notification: function(args) { - return 'Starting VM: ' + args.name; - } - }, - notification: { - poll: function(args) { args.complete(); } - } - }, - destroy: { - label: 'Destroy instance', - messages: { - confirm: function(args) { - return 'Are you sure you want to destroy ' + args.name + '?'; - }, - notification: function(args) { - return 'Destroyed VM: ' + args.name; - } - }, - action: function(args) { - setTimeout(function() { - args.response.success({ data: { state: 'Destroying' }}); - }, 200); - }, - notification: { - poll: function(args) { args.complete(); } - } - } + actions: { + start: { + label: 'label.action.start.instance' , + action: function(args) { + $.ajax({ + url: createURL("startVirtualMachine&id=" + args.context.vpcTierInstances[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.startvirtualmachineresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return cloudStack.actionFilter.vmActionFilter; + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.action.start.instance'; + }, + notification: function(args) { + return 'label.action.start.instance'; + }, + complete: function(args) { + if(args.password != null) { + alert('Password of the VM is ' + args.password); + } + return 'label.action.start.instance'; + } + }, + notification: { + poll: pollAsyncJobResult + } + }, + stop: { + label: 'label.action.stop.instance', + addRow: 'false', + createForm: { + title: 'label.action.stop.instance', + desc: 'message.action.stop.instance', + fields: { + forced: { + label: 'force.stop', + isBoolean: true, + isChecked: false + } + } + }, + action: function(args) { + var array1 = []; + array1.push("&forced=" + (args.data.forced == "on")); + $.ajax({ + url: createURL("stopVirtualMachine&id=" + args.context.vpcTierInstances[0].id + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var jid = json.stopvirtualmachineresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return cloudStack.actionFilter.vmActionFilter; + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.action.stop.instance'; + }, + + notification: function(args) { + return 'label.action.stop.instance'; + } + }, + notification: { + poll: pollAsyncJobResult + } + }, + restart: { + label: 'instances.actions.reboot.label', + action: function(args) { + $.ajax({ + url: createURL("rebootVirtualMachine&id=" + args.context.vpcTierInstances[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.rebootvirtualmachineresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return cloudStack.actionFilter.vmActionFilter; + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'message.action.reboot.instance'; + }, + notification: function(args) { + return 'instances.actions.reboot.label'; + } + }, + notification: { + poll: pollAsyncJobResult + } + }, + destroy: { + label: 'label.action.destroy.instance', + messages: { + confirm: function(args) { + return 'message.action.destroy.instance'; + }, + notification: function(args) { + return 'label.action.destroy.instance'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("destroyVirtualMachine&id=" + args.context.vpcTierInstances[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.destroyvirtualmachineresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return cloudStack.actionFilter.vmActionFilter; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + restore: { + label: 'label.action.restore.instance', + messages: { + confirm: function(args) { + return 'message.action.restore.instance'; + }, + notification: function(args) { + return 'label.action.restore.instance'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("recoverVirtualMachine&id=" + args.context.vpcTierInstances[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.recovervirtualmachineresponse.virtualmachine; + args.response.success({data:item}); + } + }); + } + } }, - dataProvider: function(args) { + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.kind != null) { + switch(args.filterBy.kind) { + case "all": + array1.push("&listAll=true"); + break; + case "mine": + if (!args.context.projects) array1.push("&domainid=" + g_domainid + "&account=" + g_account); + break; + case "running": + array1.push("&listAll=true&state=Running"); + break; + case "stopped": + array1.push("&listAll=true&state=Stopped"); + break; + case "destroyed": + array1.push("&listAll=true&state=Destroyed"); + break; + } + } + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + $.ajax({ - url: createURL('listVirtualMachines'), + url: createURL('listVirtualMachines' + array1.join("")), + data: { + networkid: args.context.networks[0].id + }, success: function(json) { - args.response.success({ data: json.listvirtualmachinesresponse.virtualmachine }); + args.response.success({ + data: json.listvirtualmachinesresponse.virtualmachine, + actionFilter: cloudStack.actionFilter.vmActionFilter + }); } }); } } }, - siteToSiteVPN: { - listView: function() { - return cloudStack.sections.network.sections.siteToSiteVpn; - } + ipAddresses: { + listView: function() { + return cloudStack.sections.network.sections.ipAddresses; + } + }, + gateways: { + listView: function() { + return { + listView: { + id: 'vpcGateways', + fields: { + ipaddress: { label: 'label.ip.address', validation: { required: true }}, + gateway: { label: 'label.gateway', validation: { required: true }}, + netmask: { label: 'label.netmask', validation: { required: true }}, + vlan: { label: 'label.vlan', validation: { required: true }} + }, + actions: { + add: { + label: 'Add new gateway', + preFilter: function(args) { + if(isAdmin()) + return true; + else + return false; + }, + messages: { + notification: function(args) { + return 'Add new gateway'; + } + }, + createForm: { + title: 'Add new gateway', + desc: 'Please specify the information to add a new gateway to this VPC.', + fields: { + ipaddress: { label: 'label.ip.address', validation: { required: true }}, + gateway: { label: 'label.gateway', validation: { required: true }}, + netmask: { label: 'label.netmask', validation: { required: true }}, + vlan: { label: 'label.vlan', validation: { required: true }} + } + }, + action: function(args) { + $.ajax({ + url: createURL('createPrivateGateway'), + data: { + vpcid: args.context.vpc[0].id, + ipaddress: args.data.ipaddress, + gateway: args.data.gateway, + netmask: args.data.netmask, + vlan: args.data.vlan + }, + success: function(json) { + var jid = json.createprivategatewayresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.privategateway; + } + } + } + ); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listPrivateGateways'), + data: { + vpcid: args.context.vpc[0].id, + listAll: true + }, + success: function(json) { + var items = json.listprivategatewaysresponse.privategateway; + args.response.success({ data: items }); + } + }); + }, + detailView: { + name: 'Gateway details', + actions: { + remove: { + label: 'delete gateway', + messages: { + confirm: function(args) { + return 'Please confirm you want to delete the gateway'; + }, + notification: function(args) { + return 'delete gateway'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deletePrivateGateway&id=" + args.context.vpcGateways[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.deleteprivategatewayresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + ipaddress: { label: 'label.ip.address' } + }, + { + gateway: { label: 'label.gateway' }, + netmask: { label: 'label.netmask'}, + vlan: { label: 'label.vlan' }, + state: { label: 'label.state' }, + id: { label: 'label.id' }, + zonename: { label: 'label.zone' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listPrivateGateways'), + data: { + id: args.context.vpcGateways[0].id, + listAll: true + }, + success: function(json) { + var item = json.listprivategatewaysresponse.privategateway[0]; + args.response.success({ + data: item, + actionFilter: function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("remove"); + } + return allowedActions; + } + }); + } + }); + } + }, + staticRoutes: { + title: 'Static Routes', + custom: function(args) { + return $('
').multiEdit({ + noSelect: true, + context: args.context, + fields: { + cidr: { edit: true, label: 'label.cidr' }, + 'add-rule': { + label: 'Add route', + addButton: true + } + }, + add: { + label: 'Add', + action: function(args) { + $.ajax({ + url: createURL('createStaticRoute'), + data: { + gatewayid: args.context.vpcGateways[0].id, + cidr: args.data.cidr + }, + success: function(data) { + args.response.success({ + _custom: { + jobId: data.createstaticrouteresponse.jobid + }, + notification: { + label: 'Add static route', + poll: pollAsyncJobResult + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + }, + actions: { + destroy: { + label: 'Remove static route', + action: function(args) { + $.ajax({ + url: createURL('deleteStaticRoute'), + data: { + id: args.context.multiRule[0].id + }, + dataType: 'json', + async: true, + success: function(data) { + var jobID = data.deletestaticrouteresponse.jobid; + + args.response.success({ + _custom: { + jobId: jobID + }, + notification: { + label: 'Remove static route', + poll: pollAsyncJobResult + } + }); + } + }); + } + } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listStaticRoutes'), + data: { + gatewayid: args.context.vpcGateways[0].id + }, + success: function(json) { + var items = json.liststaticroutesresponse.staticroute; + args.response.success({ data: items }); + } + }); + } + }); + } + } + } + } + } + }; + } + }, + siteToSiteVPN: { + title: 'site-to-site VPN', + id: 'siteToSiteVpn', + sectionSelect: { + preFilter: function(args) { + return ["vpnGateway", "vpnConnection"]; + }, + label: 'label.select-view' + }, + sections: { + vpnGateway: { + type: 'select', + title: 'VPN Gateway', + listView: { + id: 'vpnGateway', + label: 'VPN Gateway', + fields: { + publicip: { label: 'label.ip.address' }, + account: { label: 'label.account' }, + domain: { label: 'label.domain' } + }, + + actions: { + add: { + label: 'Add VPN Gateway', + messages: { + notification: function(args) { + return 'Add VPN Gateway'; + } + }, + createForm: { + title: 'Add VPN Gateway', + desc: 'Please confirm that you want to add a VPN Gateway', + fields: {} + }, + action: function(args) { + $.ajax({ + url: createURL("createVpnGateway"), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var jid = json.createvpngatewayresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpngateway; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + $.ajax({ + url: createURL("listVpnGateways&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + data: { + vpcid: args.context.vpc[0].id + }, + async: false, + success: function(json) { + var items = json.listvpngatewaysresponse.vpngateway; + args.response.success({data: items}); + } + }); + }, + detailView: { + name: 'label.details', + actions: { + remove: { + label: 'delete VPN Gateway', + messages: { + confirm: function(args) { + return 'Please confirm that you want to delete this VPN Gateway'; + }, + notification: function(args) { + return 'delete VPN Gateway'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteVpnGateway"), + data: { + id: args.context.vpnGateway[0].id + }, + success: function(json) { + var jid = json.deletevpngatewayresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + publicip: { label: 'label.ip.address' } + }, + { + id: { label: 'label.id' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listVpnGateways"), + data: { + id: args.context.vpnGateway[0].id + }, + async: true, + success: function(json) { + var item = json.listvpngatewaysresponse.vpngateway[0]; + args.response.success({data: item}); + } + }); + } + } + } + } + } + }, + vpnConnection: { + type: 'select', + title: 'VPN Connection', + listView: { + id: 'vpnConnection', + label: 'VPN Connection', + fields: { + publicip: { label: 'label.ip.address' }, + gateway: { label: 'label.gateway' }, + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' }, + ikepolicy: { label: 'IKE policy' }, + esppolicy: { label: 'ESP policy' } + }, + dataProvider: function(args) { + var array1 = []; + if(args.filterBy != null) { + if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) { + switch(args.filterBy.search.by) { + case "name": + if(args.filterBy.search.value.length > 0) + array1.push("&keyword=" + args.filterBy.search.value); + break; + } + } + } + $.ajax({ + url: createURL("listVpnConnections&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var items = json.listvpnconnectionsresponse.vpnconnection; + args.response.success({data:items}); + } + }); + }, + + detailView: { + name: 'label.details', + tabs: { + details: { + title: 'label.details', + fields: [ + { + id: { label: 'label.id' }, + + //s2svpngatewayid: { label: 'VPN gateway ID' }, + publicip: { label: 'label.ip.address' }, + + //s2scustomergatewayid: { label: 'Customer gateway ID' }, + gateway: { label: 'label.gateway' }, + cidrlist: { label: 'CIDR list' }, + ipsecpsk: { label: 'IPsec Preshared-Key' }, + ikepolicy: { label: 'IKE policy' }, + esppolicy: { label: 'ESP policy' }, + lifetime: { label: 'Lifetime (second)' }, + + created: { label: 'label.date', converter: cloudStack.converters.toLocalDate } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL("listVpnConnections&id=" + args.context.vpnConnection[0].id), + dataType: "json", + async: true, + success: function(json) { + var item = json.listvpnconnectionsresponse.vpnconnection[0]; + args.response.success({data: item}); + } + }); + } + } + }, + actions: { + restart: { + label: 'Reset VPN connection', + messages: { + confirm: function(args) { + return 'Please confirm that you want to reset VPN connection' ; + }, + notification: function(args) { + return 'Reset VPN connection'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("resetVpnConnection"), + data: { + id: args.context.vpnConnection[0].id + }, + dataType: "json", + async: true, + success: function(json) { + var jid = json.resetvpnconnectionresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpnconnection; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + remove: { + label: 'delete VPN connection', + messages: { + confirm: function(args) { + return 'Please confirm that you want to delete VPN connection'; + }, + notification: function(args) { + return 'delete VPN connection'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteVpnConnection"), + dataType: "json", + data: { + id: args.context.vpnConnection[0].id + }, + async: true, + success: function(json) { + var jid = json.deletevpnconnectionresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpnconnection; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + } + } + } + } + } }, + tiers: { + detailView: { //duplicate from cloudStack.sections.network.sections.networks.listView.detailView (begin) + name: 'Guest network details', + + //comment out until JS error "$browser is undefined" is fixed + /* + viewAll: { + path: 'network.ipAddresses', + label: 'label.menu.ipaddresses', + preFilter: function(args) { + if (args.context.networks[0].state == 'Destroyed') + return false; + + var services = args.context.networks[0].service; + if(services == null) + return false; + + if(args.context.networks[0].type == "Isolated") { + for(var i=0; i < services.length; i++) { + var service = services[i]; + if(service.name == "SourceNat") { + return true; + } + } + } + else if(args.context.networks[0].type == "Shared") { + var havingSecurityGroupService = false; + var havingElasticIpCapability = false; + var havingElasticLbCapability = false; + + for(var i=0; i < services.length; i++) { + var service = services[i]; + if(service.name == "SecurityGroup") { + havingSecurityGroupService = true; + } + else if(service.name == "StaticNat") { + $(service.capability).each(function(){ + if(this.name == "ElasticIp" && this.value == "true") { + havingElasticIpCapability = true; + return false; //break $.each() loop + } + }); + } + else if(service.name == "Lb") { + $(service.capability).each(function(){ + if(this.name == "ElasticLb" && this.value == "true") { + havingElasticLbCapability = true; + return false; //break $.each() loop + } + }); + } + } + + if(havingSecurityGroupService == true && havingElasticIpCapability == true && havingElasticLbCapability == true) + return true; + else + return false; + } + + return false; + } + }, + */ + + actions: { + edit: { + label: 'label.edit', + messages: { + notification: function(args) { + return 'label.edit.network.details'; + } + }, + action: function(args) { + var array1 = []; + array1.push("&name=" + todb(args.data.name)); + array1.push("&displaytext=" + todb(args.data.displaytext)); + + //args.data.networkdomain is null when networkdomain field is hidden + if(args.data.networkdomain != null && args.data.networkdomain != args.context.networks[0].networkdomain) + array1.push("&networkdomain=" + todb(args.data.networkdomain)); + + //args.data.networkofferingid is null when networkofferingid field is hidden + if(args.data.networkofferingid != null && args.data.networkofferingid != args.context.networks[0].networkofferingid) { + array1.push("&networkofferingid=" + todb(args.data.networkofferingid)); + + if(args.context.networks[0].type == "Isolated") { //Isolated network + cloudStack.dialog.confirm({ + message: 'Do you want to keep the current guest network CIDR unchanged?', + action: function() { //"Yes" button is clicked + array1.push("&changecidr=false"); + $.ajax({ + url: createURL("updateNetwork&id=" + args.context.networks[0].id + array1.join("")), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.network; + return {data: item}; + } + } + } + ); + } + }); + }, + cancelAction: function() { //"Cancel" button is clicked + array1.push("&changecidr=true"); + $.ajax({ + url: createURL("updateNetwork&id=" + args.context.networks[0].id + array1.join("")), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.network; + return {data: item}; + } + } + } + ); + } + }); + } + }); + return; + } + } + + $.ajax({ + url: createURL("updateNetwork&id=" + args.context.networks[0].id + array1.join("")), + dataType: "json", + success: function(json) { + var jid = json.updatenetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.network; + return {data: item}; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + 'restart': { + label: 'label.restart.network', + 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: { + cleanup: { + label: 'label.clean.up', + isBoolean: true + } + } + }, + messages: { + notification: function(args) { + return 'label.restart.network'; + } + }, + action: function(args) { + var array1 = []; + array1.push("&cleanup=" + (args.data.cleanup == "on")); + $.ajax({ + url: createURL("restartNetwork&id=" + args.context.networks[0].id + array1.join("")), + dataType: "json", + async: true, + success: function(json) { + var jid = json.restartnetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.network; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + }, + + remove: { + label: 'label.action.delete.network', + messages: { + confirm: function(args) { + return 'message.action.delete.network'; + }, + notification: function(args) { + return 'label.action.delete.network'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteNetwork&id=" + args.context.networks[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.deletenetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + tabFilter: function(args) { + var networkOfferingHavingELB = false; + $.ajax({ + url: createURL("listNetworkOfferings&id=" + args.context.networks[0].networkofferingid), + dataType: "json", + async: false, + success: function(json) { + var networkoffering = json.listnetworkofferingsresponse.networkoffering[0]; + $(networkoffering.service).each(function(){ + var thisService = this; + if(thisService.name == "Lb") { + $(thisService.capability).each(function(){ + if(this.name == "ElasticLb" && this.value == "true") { + networkOfferingHavingELB = true; + return false; //break $.each() loop + } + }); + return false; //break $.each() loop + } + }); + } + }); + + var hiddenTabs = []; + if(networkOfferingHavingELB == false) + hiddenTabs.push("addloadBalancer"); + return hiddenTabs; + }, + + isMaximized: true, + tabs: { + details: { + title: 'label.details', + preFilter: function(args) { + var hiddenFields = []; + var zone; + + $.ajax({ + url: createURL('listZones'), + data: { + id: args.context.networks[0].zoneid + }, + async: false, + success: function(json) { + zone = json.listzonesresponse.zone[0]; + } + }); + + if(zone.networktype == "Basic") { + hiddenFields.push("account"); + hiddenFields.push("gateway"); + hiddenFields.push("vlan"); + hiddenFields.push("cidr"); + //hiddenFields.push("netmask"); + } + + if(args.context.networks[0].type == "Isolated") { + hiddenFields.push("networkofferingdisplaytext"); + hiddenFields.push("networkdomaintext"); + hiddenFields.push("gateway"); + hiddenFields.push("networkofferingname"); + //hiddenFields.push("netmask"); + } + else { //selectedGuestNetworkObj.type == "Shared" + hiddenFields.push("networkofferingid"); + hiddenFields.push("networkdomain"); + } + return hiddenFields; + }, + fields: [ + { + name: { + label: 'label.name', + isEditable: true + } + }, + { + id: { label: 'label.id' }, + zonename: { label: 'label.zone' }, + displaytext: { + label: 'label.description', + isEditable: true + }, + type: { + label: 'label.type' + }, + state: { + label: 'label.state' + }, + restartrequired: { + label: 'label.restart.required', + converter: function(booleanValue) { + if(booleanValue == true) + return "Yes"; + else if(booleanValue == false) + return "No"; + } + }, + vlan: { label: 'VLAN ID' }, + + networkofferingname: { label: 'label.network.offering' }, + + networkofferingid: { + label: 'label.network.offering', + isEditable: true, + select: function(args){ + if (args.context.networks[0].state == 'Destroyed') { + args.response.success({ data: [] }); + return; + } + + var items = []; + $.ajax({ + url: createURL("listNetworkOfferings&networkid=" + args.context.networks[0].id), + dataType: "json", + async: false, + success: function(json) { + var networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; + $(networkOfferingObjs).each(function() { + items.push({id: this.id, description: this.displaytext}); + }); + } + }); + $.ajax({ + url: createURL("listNetworkOfferings&id=" + args.context.networks[0].networkofferingid), //include currently selected network offeirng to dropdown + dataType: "json", + async: false, + success: function(json) { + var networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; + $(networkOfferingObjs).each(function() { + items.push({id: this.id, description: this.displaytext}); + }); + } + }); + args.response.success({data: items}); + } + }, + + gateway: { label: 'label.gateway' }, + + //netmask: { label: 'Netmask' }, + cidr: { label: 'CIDR' }, + + networkdomaintext: { + label: 'label.network.domain.text' + }, + networkdomain: { + label: 'label.network.domain', + isEditable: true + }, + + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + } + ], + 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 + } + ); + } + }); + } + }, + + addloadBalancer: { + title: 'label.add.load.balancer', + custom: function(args) { + var context = args.context; + + return $('
').multiEdit( + { + context: context, + listView: $.extend(true, {}, cloudStack.sections.instances, { + listView: { + dataProvider: function(args) { + var networkid; + if('vpc' in args.context) + networkid = args.context.multiData.tier; + else + networkid = args.context.ipAddresses[0].associatednetworkid; + + var data = { + page: args.page, + pageSize: pageSize, + networkid: networkid, + listAll: true + }; + + $.ajax({ + url: createURL('listVirtualMachines'), + data: data, + dataType: 'json', + async: true, + success: function(data) { + args.response.success({ + data: $.grep( + data.listvirtualmachinesresponse.virtualmachine ? + data.listvirtualmachinesresponse.virtualmachine : [], + function(instance) { + return $.inArray(instance.state, [ + 'Destroyed' + ]) == -1; + } + ) + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + } + }), + multipleAdd: true, + fields: { + 'name': { edit: true, label: 'label.name' }, + 'publicport': { edit: true, label: 'label.public.port' }, + 'privateport': { edit: true, label: 'label.private.port' }, + 'algorithm': { + label: 'label.algorithm', + select: function(args) { + args.response.success({ + data: [ + { name: 'roundrobin', description: _l('label.round.robin') }, + { name: 'leastconn', description: _l('label.least.connections') }, + { name: 'source', description: _l('label.source') } + ] + }); + } + }, + 'sticky': { + label: 'label.stickiness', + custom: { + buttonLabel: 'label.configure', + action: cloudStack.lbStickyPolicy.dialog() + } + }, + 'add-vm': { + label: 'label.add.vms', + addButton: true + } + }, + add: { + label: 'label.add.vms', + action: function(args) { + var data = { + algorithm: args.data.algorithm, + name: args.data.name, + privateport: args.data.privateport, + publicport: args.data.publicport, + openfirewall: false, + domainid: g_domainid, + account: g_account + }; + + if('vpc' in args.context) { //from VPC section + if(args.data.tier == null) { + args.response.error('Tier is required'); + return; + } + $.extend(data, { + networkid: args.data.tier + }); + } + else { //from Guest Network section + $.extend(data, { + networkid: args.context.networks[0].id + }); + } + + var stickyData = $.extend(true, {}, args.data.sticky); + + $.ajax({ + url: createURL('createLoadBalancerRule'), + data: data, + dataType: 'json', + async: true, + success: function(data) { + var itemData = args.itemData; + var jobID = data.createloadbalancerruleresponse.jobid; + + $.ajax({ + url: createURL('assignToLoadBalancerRule'), + data: { + id: data.createloadbalancerruleresponse.id, + virtualmachineids: $.map(itemData, function(elem) { + return elem.id; + }).join(',') + }, + dataType: 'json', + async: true, + success: function(data) { + var lbCreationComplete = false; + + args.response.success({ + _custom: { + jobId: jobID + }, + notification: { + label: 'label.add.load.balancer', + poll: function(args) { + var complete = args.complete; + var error = args.error; + + pollAsyncJobResult({ + _custom: args._custom, + complete: function(args) { + if (lbCreationComplete) { + return; + } + + lbCreationComplete = true; + cloudStack.dialog.notice({ + message: _l('message.add.load.balancer.under.ip') + + args.data.loadbalancer.publicip + }); + + if (stickyData && + stickyData.methodname && + stickyData.methodname != 'None') { + cloudStack.lbStickyPolicy.actions.add( + args.data.loadbalancer.id, + stickyData, + complete, // Complete + complete // Error + ); + } else { + complete(); + } + }, + error: error + }); + } + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + }, + dataProvider: function(args) { + args.response.success({ //no LB listing in AddLoadBalancer tab + data: [] + }); + } + } + ); + } + } + } + }, //duplicate from cloudStack.sections.network.sections.networks.listView.detailView (begin) + actionPreFilter: function(args) { - var tier = args.context.tiers[0]; + var tier = args.context.networks[0]; var state = tier.state; return state == 'Running' ? ['start'] : ['stop']; }, - actions: { - // Add new tier + actions: { add: { - label: 'Add new tier to VPC', - action: function(args) { - setTimeout(function() { - args.response.success({ - data: { - name: args.data.name, - cidr: args.data.cidr, - state: 'Stopped' - } - }); - }, 500); - }, - - createForm: { - title: 'Add new tier', - desc: 'Please fill in the following to add a new VPC tier.', - fields: { - name: { label: 'label.name', validation: { required: true } }, - cidr: { label: 'label.cidr', validation: { required: true } } - } - }, - - notification: { - poll: function(args) { args.complete(); } - } - }, + label: 'Add new tier', + createForm: { + title: 'Add new tier', + fields: { + name: { label: 'label.name', + validation: { required: true } + }, + networkOfferingId: { + label: 'label.network.offering', + validation: { required: true }, + dependsOn: 'zoneId', + select: function(args) { + var networkSupportingLbExists = false; + $.ajax({ + url: createURL('listNetworks'), + data: { + vpcid: args.context.vpc[0].id, + supportedservices: 'LB' + }, + success: function(json) { + var networkSupportingLbExists; + if(json.listnetworksresponse.network != null && json.listnetworksresponse.network.length > 0) + networkSupportingLbExists = true; + else + networkSupportingLbExists = false; + + $.ajax({ + url: createURL('listNetworkOfferings'), + data: { + forvpc: true, + zoneid: args.zoneId, + guestiptype: 'Isolated', + supportedServices: 'SourceNat', + specifyvlan: false, + state: 'Enabled' + }, + success: function(json) { + var networkOfferings = json.listnetworkofferingsresponse.networkoffering; + + var items; + if(networkSupportingLbExists == true) { + items = $.grep(networkOfferings, function(networkOffering) { + var includingLbService = false; + $(networkOffering.service).each(function(){ + var thisService = this; + if(thisService.name == "Lb") { + includingLbService = true; + return false; //break $.each() loop + } + }); + return !includingLbService; + }); + } + else { + items = networkOfferings; + } + + args.response.success({ + data: $.map(items, function(item) { + return { + id: item.id, + description: item.name + }; + }) + }); + } + }); + } + }); + } + }, + gateway: { + label: 'label.gateway', + validation: { required: true } + }, + netmask: { + label: 'label.netmask', + validation: { required: true } + } + } + }, + action: function(args) { + var dataObj = { + vpcid: args.context.vpc[0].id, + zoneId: args.context.vpc[0].zoneid, + networkOfferingId: args.data.networkOfferingId, + name: args.data.name, + displayText: args.data.name, + gateway: args.data.gateway, + netmask: args.data.netmask + }; + + $.ajax({ + url: createURL('createNetwork'), + dataType: 'json', + data: dataObj, + success: function(json) { + args.response.success({ + data: json.createnetworkresponse.network + }); + }, + error: function(XMLHttpResponse) { + args.response.error(parseXMLHttpResponse(XMLHttpResponse)); + } + }); + }, + messages: { + notification: function() { return 'Add new tier'; } + } + }, + + /* start: { label: 'Start tier', shortLabel: 'Start', @@ -425,6 +1730,9 @@ poll: function(args) { args.complete({ data: { state: 'Running' } }); } } }, + */ + + /* stop: { label: 'Stop tier', shortLabel: 'Stop', @@ -435,61 +1743,86 @@ poll: function(args) { args.complete({ data: { state: 'Stopped' } }); } } }, + */ + addVM: { label: 'Add VM to tier', shortLabel: 'Add VM', - action: cloudStack.uiCustom.instanceWizard( - cloudStack.instanceWizard + action: cloudStack.uiCustom.instanceWizard( + $.extend(true, {}, cloudStack.instanceWizard, { + pluginForm: { + name: 'vpcTierInstanceWizard' + } + }) ), notification: { poll: pollAsyncJobResult } }, + acl: { label: 'Configure ACL for tier', shortLabel: 'ACL', multiEdit: aclMultiEdit }, + remove: { label: 'Remove tier', - action: function(args) { - args.response.success(); + action: function(args) { + $.ajax({ + url: createURL('deleteNetwork'), + dataType: "json", + data: { + id: args.context.networks[0].id + }, + success: function(json) { + var jid = json.deletenetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid + } + } + ); + } + }); }, notification: { - poll: function(args) { args.complete(); } + poll: pollAsyncJobResult } } }, // Get tiers - dataProvider: function(args) { - var tiers = [ // Dummy content - { - id: 1, - name: 'web', - cidr: '192.168.0.0/24', - state: 'Running', - virtualMachines: [ - { name: 'i-2-VM' }, - { name: 'i-3-VM' } - ] - }, - { - id: 2, - name: 'app', - state: 'Stopped', - cidr: '10.0.0.0/24', - virtualMachines: [] - } - ]; - - setTimeout(function() { - args.response.success({ - data: { - tiers: tiers - } - }); - }, 1000); + dataProvider: function(args) { + $.ajax({ + url: createURL("listNetworks"), + dataType: "json", + data: { + vpcid: args.context.vpc[0].id, + listAll: true + }, + async: true, + success: function(json) { + var networks = json.listnetworksresponse.network; + if(networks != null && networks.length > 0) { + for(var i = 0; i < networks.length; i++) { + $.ajax({ + url: createURL("listVirtualMachines"), + dataType: "json", + data: { + networkid: networks[i].id, + listAll: true + }, + async: false, + success: function(json) { + networks[i].virtualMachines = json.listvirtualmachinesresponse.virtualmachine; + } + }); + } + } + args.response.success({ tiers: networks }); + } + }); } } };