// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. (function($, cloudStack) { var assignVMAction = function() { return { label: 'label.assign.vms', messages: { notification: function(args) { return 'label.assign.vms'; } }, needsRefresh: true, listView: $.extend(true, {}, cloudStack.sections.instances.listView, { type: 'checkbox', filters: false, multiSelect: false, subselect: { isMultiple: true, label: 'label.use.vm.ip', dataProvider: function(args) { var instance = args.context.instances[0]; var network = args.context.networks[0]; $.ajax({ url: createURL('listNics'), data: { virtualmachineid: instance.id, nicId: instance.nic[0].id }, success: function(json) { var nic = json.listnicsresponse.nic[0]; var primaryIp = nic.ipaddress; var secondaryIps = nic.secondaryip ? nic.secondaryip : []; var ipSelection = []; var existingIps = $(args.context.subItemData).map( function(index, item) { return item.itemIp; } ); // Add primary IP as default if ($.inArray(primaryIp, existingIps) == -1) { ipSelection.push({ id: primaryIp, description: primaryIp + ' (Primary)' }); } // Add secondary IPs $(secondaryIps).map(function(index, secondaryIp) { if ($.inArray(secondaryIp.ipaddress, existingIps) == -1) { ipSelection.push({ id: secondaryIp.ipaddress, description: secondaryIp.ipaddress }); } }); args.response.success({ data: ipSelection }); } }); } }, dataProvider: function(args) { var assignedInstances; $.ajax({ url: createURL('listLoadBalancers'), data: { id: args.context.internalLoadBalancers[0].id }, async: false, success: function(json) { assignedInstances = json.listloadbalancersresponse.loadbalancer[0].loadbalancerinstance; if (assignedInstances == null) assignedInstances = []; } }); $.ajax({ url: createURL('listVirtualMachines'), data: { networkid: args.context.networks[0].id, listAll: true }, success: function(json) { var instances = json.listvirtualmachinesresponse.virtualmachine; // Pre-select existing instances in LB rule $(instances).map(function(index, instance) { instance._isSelected = $.grep(assignedInstances, function(assignedInstance) { return assignedInstance.id == instance.id; } ).length ? true : false; }); //remove assigned VMs (i.e. instance._isSelected == true) var items = []; if (instances != null) { for (var i = 0; i < instances.length; i++) { if (instances[i]._isSelected == true) continue; else items.push(instances[i]); } } args.response.success({ data: items }); } }); } }), action: function(args) { /* * path 1: Network > VPC (list) > click "Configure" > pick an internal LB tier > click "Internal LB" (list) > click on a grid row (Details tab) > click "Assign VMs" tab > click Assign VMs" button on top of list * path 2: Network > VPC (list) > click "Configure" > pick an internal LB tier > click "Internal LB" (list) > "QuickView" on a grid row > click "Assign VMs" button in QuickView */ var $rows = $(':ui-dialog .list-view tbody tr'); var vms = args.context.instances; // Assign subselect values $(vms).each(function() { var vm = this; var $vmRow = $rows.filter(function() { return $(this).data('json-obj') === vm; }); $.extend(vm, { _subselect: $vmRow.find('.subselect select').val() }); }); var inputData = { id: args.context.internalLoadBalancers[0].id }; /* * e.g. first VM(xxx) has two IPs(10.1.1.~), second VM(yyy) has three IPs(10.2.2.~): * vmidipmap[0].vmid=xxx vmidipmap[0].vmip=10.1.1.11 * vmidipmap[1].vmid=xxx vmidipmap[1].vmip=10.1.1.12 * vmidipmap[2].vmid=yyy vmidipmap[2].vmip=10.2.2.77 * vmidipmap[3].vmid=yyy vmidipmap[3].vmip=10.2.2.78 * vmidipmap[4].vmid=yyy vmidipmap[4].vmip=10.2.2.79 */ var selectedVMs = vms; if (selectedVMs != null) { var vmidipmapIndex = 0; for (var vmIndex = 0; vmIndex < selectedVMs.length; vmIndex++) { var selectedIPs = selectedVMs[vmIndex]._subselect; for (var ipIndex = 0; ipIndex < selectedIPs.length; ipIndex++) { inputData['vmidipmap[' + vmidipmapIndex + '].vmid'] = selectedVMs[vmIndex].id; inputData['vmidipmap[' + vmidipmapIndex + '].vmip'] = selectedIPs[ipIndex]; vmidipmapIndex++; } } } $.ajax({ url: createURL('assignToLoadBalancerRule'), data: inputData, dataType: 'json', async: true, success: function(data) { var jid = data.assigntoloadbalancerruleresponse.jobid; args.response.success({ _custom: { jobId: jid } }); } }); }, notification: { poll: pollAsyncJobResult } }; }; var aclMultiEdit = { noSelect: true, reorder: { moveDrag: { action: function(args) { var rule = args.context.multiRule[0]; var number = 0; var prevItem = args.prevItem ? args.prevItem.number : null; var nextItem = args.nextItem ? args.nextItem.number : null; if (!nextItem) { // Last item number = prevItem + 100; } else { if (nextItem - prevItem <= 10) { number = nextItem - parseInt(((nextItem - prevItem) / 2)); } else { number = nextItem > 1 ? nextItem - 10 : 1; } } $.ajax({ url: createURL('updateNetworkACLItem'), data: { id: rule.id, number: number }, success: function(json) { var pollTimer = setInterval(function() { pollAsyncJobResult({ _custom: { jobId: json.createnetworkaclresponse.jobid }, complete: function() { clearInterval(pollTimer); args.response.success(); }, error: function(errorMsg) { clearInterval(pollTimer); args.response.error(errorMsg); } }); }, 1000); } }); } } }, fields: { 'number': { label: 'label.rule.number', edit: true, isEditable: true }, 'cidrlist': { edit: true, label: 'label.cidr', isEditable: true }, action: { label: 'label.action', isEditable: true, select: function(args) { args.response.success({ data: [{ name: 'Allow', description: 'Allow' }, { name: 'Deny', description: 'Deny' }] }); } }, 'protocol': { label: 'label.protocol', isEditable: true, select: function(args) { var isEditDialog = args.type === 'createForm'; args.$select.change(function() { var $inputs, $icmpFields, $otherFields, $portFields, $protocolFields, $protocolinput; // // Editing existing rules in createForm dialog // if (isEditDialog) { $inputs = args.$form.find('.form-item'); $icmpFields = $inputs.filter(function() { var name = $(this).attr('rel'); return $.inArray(name, [ 'icmptype', 'icmpcode' ]) > -1; }); $otherFields = $inputs.filter(function() { var name = $(this).attr('rel'); return name != 'protocolnumber' && name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist' && name != 'number'; }); $portFields = $inputs.filter(function() { var name = $(this).attr('rel'); return $.inArray(name, [ 'startport', 'endport' ]) > -1; }); $protocolFields = $inputs.filter(function() { var name = $(this).attr('rel'); return $.inArray(name, ['protocolnumber']) > -1; }); if ($(this).val() == 'protocolnumber') { $icmpFields.show(); $portFields.show(); $protocolFields.show(); $portFields.show(); } else if ($(this).val() == 'icmp') { $icmpFields.show(); $protocolFields.hide(); $portFields.hide(); } else if ($(this).val() == 'all') { $portFields.hide(); } else { $otherFields.show(); $icmpFields.hide(); $protocolFields.hide(); } } else { // // Add new form // $inputs = args.$form.find('input'); $icmpFields = $inputs.filter(function() { var name = $(this).attr('name'); return $.inArray(name, [ 'icmptype', 'icmpcode' ]) > -1; }); $otherFields = $inputs.filter(function() { var name = $(this).attr('name'); return name != 'protocolnumber' && name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist' && name != 'number'; }); $portFields = $inputs.filter(function() { var name = $(this).attr('name'); return $.inArray(name, [ 'startport', 'endport' ]) > -1; }); $protocolinput = args.$form.find('td input'); $protocolFields = $protocolinput.filter(function() { var name = $(this).attr('name'); return $.inArray(name, ['protocolnumber']) > -1; }); if ($(this).val() == 'protocolnumber') { $icmpFields.show(); $otherFields.hide(); $protocolFields.show().addClass('required'); $inputs.filter('[name=startport],[name=endport]').show().attr('disabled', false); } else if ($(this).val() == 'icmp') { $icmpFields.show(); $icmpFields.attr('disabled', false); $protocolFields.hide().removeClass('required'); $otherFields.attr('disabled', 'disabled'); $otherFields.hide(); $otherFields.parent().find('label.error').hide(); } else if ($(this).val() == 'all') { $portFields.attr('disabled', 'disabled'); $portFields.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(); $protocolFields.hide().removeClass('required'); } } }); args.response.success({ data: [{ name: 'tcp', description: 'TCP' }, { name: 'udp', description: 'UDP' }, { name: 'icmp', description: 'ICMP' }, { name: 'all', description: 'ALL' }, { name: 'protocolnumber', description: 'Protocol Number' } ] }); setTimeout(function() { args.$select.trigger('change'); }, 100); } }, 'protocolnumber': { label: 'label.protocol.number', edit: true, isEditable: true }, 'startport': { edit: true, label: 'label.start.port', isOptional: true, isEditable: true }, 'endport': { edit: true, label: 'label.end.port', isOptional: true, isEditable: true }, 'networkid': { label: 'label.select.tier', select: function(args) { var data = { listAll: true, vpcid: args.context.vpc[0].id }; // Only show selected tier, if viewing from detail view if (args.context.networks && args.context.networks[0] && args.context.networks[0].vpcid) { $.extend(data, { id: args.context.networks[0].id }); } // Ajax Call to display the Tiers $.ajax({ url: createURL('listNetworks'), data: data, success: function(json) { var networks = json.listnetworksresponse.network; args.response.success({ data: $(networks).map(function(index, network) { return { name: network.id, description: network.name }; }) }); } }); } }, 'icmptype': { edit: true, label: 'ICMP.type', isDisabled: true, desc: 'Please specify -1 if you want to allow all ICMP types', defaultValue: '-1', isEditable: true }, 'icmpcode': { edit: true, label: 'ICMP.code', isDisabled: true, desc: 'Please specify -1 if you want to allow all ICMP codes', defaultValue: '-1', isEditable: true }, 'traffictype': { label: 'label.traffic.type', isEditable: true, select: function(args) { args.response.success({ data: [{ name: 'Ingress', description: 'Ingress' }, { name: 'Egress', description: 'Egress' }] }); } }, 'add-rule': { label: 'label.add.rule', addButton: true } }, tags: cloudStack.api.tags({ resourceType: 'NetworkACL', contextId: 'multiRule' }), add: { label: 'label.add', action: function(args) { var $multi = args.$multi; //Support for Protocol Number between 0 to 255 if (args.data.protocol === 'protocolnumber') { $.extend(args.data, { protocol: args.data.protocolnumber }); delete args.data.protocolnumber; delete args.data.icmptype; delete args.data.icmpcode; } else { delete args.data.protocolnumber; } if ((args.data.protocol == 'tcp' || args.data.protocol == 'udp') && (args.data.startport == "" || args.data.startport == undefined)) { cloudStack.dialog.notice({ message: _l('Start Port or End Port value should not be blank') }); $(window).trigger('cloudStack.fullRefresh'); } else if ((args.data.protocol == 'tcp' || args.data.protocol == 'udp') && (args.data.endport == "" || args.data.endport == undefined)) { cloudStack.dialog.notice({ message: _l('Start Port or End Port value should not be blank') }); $(window).trigger('cloudStack.fullRefresh'); } else { $.ajax({ url: createURL('createNetworkACL'), data: $.extend(args.data, { aclid: args.context.aclLists[0].id }), dataType: 'json', success: function(data) { args.response.success({ _custom: { jobId: data.createnetworkaclresponse.jobid, getUpdatedItem: function(json) { $(window).trigger('cloudStack.fullRefresh'); return data; } }, notification: { label: 'label.add.ACL', poll: pollAsyncJobResult } }); }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); } }); } } }, actions: { edit: { label: 'label.edit', action: function(args) { var data = { id: args.context.multiRule[0].id, cidrlist: args.data.cidrlist, number: args.data.number, protocol: args.data.protocol, traffictype: args.data.traffictype, action: args.data.action }; if (data.protocol === 'tcp' || data.protocol === 'udp') { $.extend(data, { startport: args.data.startport, endport: args.data.endport }); } else if (data.protocol === 'icmp') { $.extend(data, { icmptype: args.data.icmptype, icmpcode: args.data.icmpcode }); } else if (data.protocol === 'protocolnumber') { $.extend(data, { protocol: args.data.protocolnumber, startport: args.data.startport, endport: args.data.endport }); delete args.data.protocolnumber; } $.ajax({ url: createURL('updateNetworkACLItem'), data: data, success: function(json) { args.response.success({ _custom: { jobId: json.createnetworkaclresponse.jobid }, // API response obj name needs to be fixed notification: { label: 'label.edit.acl.rule', poll: pollAsyncJobResult } }); }, error: function(error) { args.response.error(parseXMLHttpResponse(error)); } }); } }, destroy: { label: '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, getUpdatedItem: function() { $(window).trigger('cloudStack.fullRefresh'); } }, notification: { label: 'label.remove.ACL', poll: pollAsyncJobResult } }); }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); } }); } } }, dataProvider: function(args) { var $multi = args.$multi; var data = { vpcid: args.context.vpc[0].id, listAll: true }; if (!$multi.data('acl-rules')) { $multi.data('acl-rules', []); } if (args.context.networks && args.context.networks[0] && args.context.networks[0].vpcid) { data.networkid = args.context.networks[0].id; $.ajax({ url: createURL('listNetworkACLs'), data: data, dataType: 'json', async: true, success: function(json) { args.response.success({ data: $(json.listnetworkaclsresponse.networkacl).map(function(index, acl) { return $.extend(acl, { networkid: args.context.networks[0].name }); }) }); }, error: function(XMLHttpResponse) { args.response.error(parseXMLHttpResponse(XMLHttpResponse)); } }); } else { args.response.success({ data: $multi.data('acl-rules') }); } } }; cloudStack.vpc = { // nTier sections sections: { tierVMs: function() { var list = $.extend(true, {}, cloudStack.sections.instances); list.listView.actions.add.action.custom = cloudStack.uiCustom.instanceWizard( $.extend(true, {}, cloudStack.instanceWizard, { pluginForm: { name: 'vpcTierInstanceWizard' } }) ); return list; }, tierPortForwarders: function() { return cloudStack.vpc.ipAddresses.listView(); }, tierStaticNATs: function() { return cloudStack.vpc.staticNatIpAddresses.listView(); }, // Internal load balancers internalLoadBalancers: { title: 'label.internal.lb', listView: { id: 'internalLoadBalancers', fields: { name: { label: 'label.name' }, sourceipaddress: { label: 'label.source.ip.address' }, sourceport: { label: 'label.source.port' }, instanceport: { label: 'label.instance.port' }, algorithm: { label: 'label.algorithm' } }, dataProvider: function(args) { $.ajax({ url: createURL('listLoadBalancers'), data: { networkid: args.context.networks[0].id }, success: function(json) { var items = json.listloadbalancersresponse.loadbalancer; if (items != null) { for (var i = 0; i < items.length; i++) { var item = items[i]; //there is only one element in loadbalancerrul array property. item.sourceport = item.loadbalancerrule[0].sourceport; item.instanceport = item.loadbalancerrule[0].instanceport; } } args.response.success({ data: items }); } }); }, actions: { add: { label: 'label.add.internal.lb', createForm: { title: 'label.add.internal.lb', fields: { name: { label: 'label.name', validation: { required: true } }, description: { label: 'label.description', validation: { required: false } }, sourceipaddress: { label: 'label.source.ip.address', validation: { required: false } }, sourceport: { label: 'label.source.port', validation: { required: true } }, instanceport: { label: 'label.instance.port', validation: { required: true } }, algorithm: { label: 'label.algorithm', validation: { required: true }, select: function(args) { args.response.success({ data: [{ id: 'source', description: _l('label.lb.algorithm.source') }, { id: 'roundrobin', description: _l('label.lb.algorithm.roundrobin') }, { id: 'leastconn', description: _l('label.lb.algorithm.leastconn') }] }); } } } }, messages: { notification: function(args) { return 'label.add.internal.lb'; } }, action: function(args) { var data = { name: args.data.name, sourceport: args.data.sourceport, instanceport: args.data.instanceport, algorithm: args.data.algorithm, networkid: args.context.networks[0].id, sourceipaddressnetworkid: args.context.networks[0].id, scheme: 'Internal' }; if (args.data.description != null && args.data.description.length > 0) { $.extend(data, { description: args.data.description }); } if (args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0) { $.extend(data, { sourceipaddress: args.data.sourceipaddress }); } $.ajax({ url: createURL('createLoadBalancer'), data: data, success: function(json) { var jid = json.createloadbalancerresponse.jobid; args.response.success({ _custom: { jobId: jid, getUpdatedItem: function(json) { return json.queryasyncjobresultresponse.jobresult.loadbalancer; } } }); } }); }, notification: { poll: pollAsyncJobResult } } }, detailView: { isMaximized: true, name: 'label.internal.lb.details', actions: { assignVMs: assignVMAction(), remove: { label: 'label.delete.internal.lb', messages: { confirm: function(args) { return 'message.confirm.delete.internal.lb'; }, notification: function(args) { return 'label.delete.internal.lb'; } }, action: function(args) { var data = { id: args.context.internalLoadBalancers[0].id }; $.ajax({ url: createURL('deleteLoadBalancer'), data: data, async: true, success: function(json) { var jid = json.deleteloadbalancerresponse.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' } }, { id: { label: 'label.id' }, description: { label: 'label.description' }, sourceipaddress: { label: 'label.source.ip.address' }, sourceport: { label: 'label.source.port' }, instanceport: { label: 'label.instance.port' }, algorithm: { label: 'label.algorithm' }, loadbalancerinstance: { label: 'label.assigned.vms', converter: function(objArray) { var s = ''; if (objArray != null) { for (var i = 0; i < objArray.length; i++) { if (i > 0) { s += ', '; } s += objArray[i].name + ' (' + objArray[i].ipaddress + ')'; } } return s; } } }], dataProvider: function(args) { $.ajax({ url: createURL('listLoadBalancers'), data: { id: args.context.internalLoadBalancers[0].id }, success: function(json) { var item = json.listloadbalancersresponse.loadbalancer[0]; //remove Rules tab and add sourceport, instanceport at Details tab because there is only one element in loadbalancerrul array property. item.sourceport = item.loadbalancerrule[0].sourceport; item.instanceport = item.loadbalancerrule[0].instanceport; args.response.success({ data: item }); } }); } }, /* rules: { title: 'label.rules', multiple: true, fields: [ { sourceport: { label: 'Source Port' }, instanceport: { label: 'Instance Port' } } ], dataProvider: function(args) { $.ajax({ url: createURL('listLoadBalancers'), data: { id: args.context.internalLoadBalancers[0].id }, success: function(json) { var item = json.listloadbalancersresponse.loadbalancer[0]; args.response.success({ data: item.loadbalancerrule }); } }); } }, */ assignedVms: { title: 'label.assigned.vms', listView: { id: 'assignedVms', fields: { name: { label: 'label.name' }, ipaddress: { label: 'label.ip.address' } }, dataProvider: function(args) { $.ajax({ url: createURL('listLoadBalancers'), data: { id: args.context.internalLoadBalancers[0].id }, success: function(json) { var item = json.listloadbalancersresponse.loadbalancer[0]; args.response.success({ data: item.loadbalancerinstance }); } }); }, actions: { add: assignVMAction() }, detailView: { actions: { remove: { label: 'label.remove.vm.load.balancer', addRow: 'false', messages: { confirm: function(args) { return 'message.confirm.remove.load.balancer'; }, notification: function(args) { return 'label.remove.vm.load.balancer'; } }, action: function(args) { $.ajax({ url: createURL('removeFromLoadBalancerRule'), data: { id: args.context.internalLoadBalancers[0].id, virtualmachineids: args.context.assignedVms[0].id }, success: function(json) { var jid = json.removefromloadbalancerruleresponse.jobid; args.response.success({ _custom: { jobId: jid } }); } }); }, notification: { poll: pollAsyncJobResult } } }, tabs: { details: { title: 'label.details', fields: [{ name: { label: 'label.name' } }, { ipaddress: { label: 'label.ip.address' } }], dataProvider: function(args) { setTimeout(function() { args.response.success({ data: args.context.assignedVms[0] }); }); } } } } } } } } } }, publicLbIps: { title: 'label.public.ip', listView: { id: 'publicLbIps', fields: { ipaddress: { label: 'label.ips', converter: function(text, item) { if (item.issourcenat) { return text + ' [' + _l('label.source.nat') + ']'; } return text; } }, zonename: { label: 'label.zone' }, virtualmachinedisplayname: { label: 'label.vm.name' }, state: { converter: function(str) { // For localization return str; }, label: 'label.state', indicator: { 'Allocated': 'on', 'Released': 'off' } } }, dataProvider: function(args) { $.ajax({ url: createURL('listPublicIpAddresses'), async: false, data: { associatednetworkid: args.context.networks[0].id, forloadbalancing: true }, success: function(json) { var items = json.listpublicipaddressesresponse.publicipaddress; args.response.success({ data: items }); } }); } } }, // Private gateways privateGateways: function() { return cloudStack.vpc.gateways.listView() }, // Public IP Addresses publicIPs: function() { return cloudStack.vpc.ipAddresses.listView() }, // Network ACL lists networkACLLists: { listView: { id: 'aclLists', fields: { name: { label: 'label.name' }, description: { label: 'label.description' }, id: { label: 'label.id' } }, dataProvider: function(args) { var data = { vpcid: args.context.vpc[0].id }; listViewDataProvider(args, data); $.ajax({ url: createURL('listNetworkACLLists'), data: data, success: function(json) { var items = json.listnetworkacllistsresponse.networkacllist; args.response.success({ data: items }); } }); }, actions: { add: { label: 'label.add.acl.list', createForm: { label: 'label.add.acl.list', fields: { name: { label: 'label.add.list.name', validation: { required: true } }, description: { label: 'label.description', validation: { required: true } } } }, messages: { notification: function(args) { return 'label.add.network.acl.list'; } }, action: function(args) { var data = { name: args.data.name, description: args.data.description }; $.ajax({ url: createURL('createNetworkACLList&vpcid=' + args.context.vpc[0].id), data: data, success: function(json) { args.response.success({ _custom: { jobId: json.createnetworkacllistresponse.jobid, getUpdatedItem: function(json) { return json.queryasyncjobresultresponse.jobresult.networkacllist; } } }); } }); }, notification: { poll: pollAsyncJobResult } } }, detailView: { isMaximized: true, actions: { remove: { label: 'label.delete.acl.list', messages: { confirm: function(args) { return 'message.confirm.delete.acl.list'; }, notification: function(args) { return 'label.delete.acl.list'; } }, action: function(args) { $.ajax({ url: createURL('deleteNetworkACLList&id=' + args.context.aclLists[0].id), success: function(json) { var jid = json.deletenetworkacllistresponse.jobid; args.response.success({ _custom: { jobId: jid, getUpdatedItem: function() { $(window).trigger('cloudStack.fullRefresh'); } } }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }, notification: { poll: pollAsyncJobResult } } }, tabs: { details: { title: 'label.details', fields: [{ name: { label: 'label.name', isEditable: true }, description: { label: 'label.description' }, id: { label: 'label.id' } }], dataProvider: function(args) { var items = args.context.aclLists[0]; setTimeout(function() { args.response.success({ data: items, actionFilter: function(args) { var allowedActions = []; if (items.vpcid != null) { allowedActions.push("remove"); } return allowedActions; } }); }); } }, aclRules: { title: 'label.acl.list.rules', custom: function(args) { return $('
').multiEdit($.extend(true, {}, aclMultiEdit, { context: args.context, fields: { networkid: false }, dataProvider: function(args) { $.ajax({ url: createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), success: function(json) { var items = json.listnetworkaclsresponse.networkacl.sort(function(a, b) { return a.number >= b.number; }).map(function(acl) { if (parseInt(acl.protocol)) { // protocol number acl.protocolnumber = acl.protocol; acl.protocol = "protocolnumber"; } return acl; }); args.response.success({ data: items /* { cidrlist: '10.1.1.0/24', protocol: 'TCP', startport: 22, endport: 22, networkid: 0, traffictype: 'Egress' }, { cidrlist: '10.2.1.0/24', protocol: 'UDP', startport: 56, endport: 72, networkid: 0, trafficType: 'Ingress' } ]*/ }); } }); } })); } } } } } }, siteToSiteVPNs: function() { return $.extend(true, {}, cloudStack.vpc.siteToSiteVPN, { // siteToSiteVPN is multi-section so doesn't have an explicit // 'listView' block // // -- use this as a flag for VPC chart to render as a list view listView: true, before: { messages: { confirm: 'Please confirm that you would like to create a site-to-site VPN gateway for this VPC.', notification: 'Create site-to-site VPN gateway' }, check: function(args) { var items; $.ajax({ url: createURL('listVpnGateways&listAll=true'), data: { vpcid: args.context.vpc[0].id }, success: function(json) { var items = json.listvpngatewaysresponse.vpngateway; args.response.success(items && items.length); } }); }, action: function(args) { $.ajax({ url: createURL("createVpnGateway"), data: { vpcid: args.context.vpc[0].id }, success: function(json) { var jid = json.createvpngatewayresponse.jobid; var pollTimer = setInterval(function() { pollAsyncJobResult({ _custom: { jobId: jid }, complete: function() { clearInterval(pollTimer); args.response.success(); } }); }, g_queryAsyncJobResultInterval); } }); } } }); } }, routerDetailView: function() { return { title: 'label.VPC.router.details', updateContext: function(args) { var router; $.ajax({ url: createURL("listRouters&listAll=true&vpcid=" + args.context.vpc[0].id), dataType: "json", async: false, success: function(json) { router = json.listroutersresponse.router[0]; } }); return { routers: [router] }; }, actions: cloudStack.sections.system.subsections.virtualRouters .listView.detailView.actions, tabs: { routerDetails: cloudStack.sections.network.sections.vpc .listView.detailView.tabs.router } }; }, vmListView: { id: 'vpcTierInstances', listView: { filters: { all: { label: 'label.menu.all.instances' }, running: { label: 'label.menu.running.instances' }, stopped: { label: 'label.menu.stopped.instances' }, destroyed: { label: 'label.menu.destroyed.instances' } }, fields: { name: { label: 'label.name', editable: true }, account: { label: 'label.account' }, zonename: { label: 'label.zone' }, state: { label: 'label.status', indicator: { 'Running': 'on', 'Stopped': 'off', 'Destroyed': 'off' } } }, // List view actions 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) { cloudStack.dialog.notice({ message: '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 }); } }); } }, viewConsole: { label: 'label.view.console', action: { externalLink: { url: function(args) { return clientConsoleUrl + '?cmd=access&vm=' + args.context.vpcTierInstances[0].id; }, title: function(args) { return args.context.vpcTierInstances[0].id.substr(0, 8); //title in window.open() can't have space nor longer than 8 characters. Otherwise, IE browser will have error. }, width: 820, height: 640 } } } }, 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' + array1.join("")), data: { networkid: args.context.networks[0].id }, success: function(json) { args.response.success({ data: json.listvirtualmachinesresponse.virtualmachine, actionFilter: cloudStack.actionFilter.vmActionFilter }); } }); } } }, ipAddresses: { listView: function() { var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); listView.listView.fields = { ipaddress: listView.listView.fields.ipaddress, zonename: listView.listView.fields.zonename, associatednetworkname: { label: 'label.network.name' }, state: listView.listView.fields.state }; return listView; } }, staticNatIpAddresses: { listView: function() { var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); listView.listView.fields = { ipaddress: listView.listView.fields.ipaddress, zonename: listView.listView.fields.zonename, associatednetworkname: { label: 'label.network.name' }, state: listView.listView.fields.state }; listView.listView.dataProvider = function(args) { $.ajax({ url: createURL('listPublicIpAddresses'), data: { associatednetworkid: args.context.networks[0].id, isstaticnat: true, listall: true }, success: function(json) { args.response.success({ data: json.listpublicipaddressesresponse.publicipaddress }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }; return listView; } }, acl: { multiEdit: aclMultiEdit, listView: { listView: { id: 'networks', fields: { tierName: { label: 'label.tier' }, aclTotal: { label: 'label.network.ACL.total' } }, dataProvider: function(args) { $.ajax({ url: createURL('listNetworks'), data: { listAll: true, vpcid: args.context.vpc[0].id }, success: function(json) { var networks = json.listnetworksresponse.network ? json.listnetworksresponse.network : []; args.response.success({ data: $.map(networks, function(tier) { var aclTotal = 0; // Get ACL total $.ajax({ url: createURL('listNetworkACLs'), async: false, data: { listAll: true, networkid: tier.id }, success: function(json) { aclTotal = json.listnetworkaclsresponse.networkacl ? json.listnetworkaclsresponse.networkacl.length : 0; } }); return $.extend(tier, { tierName: tier.name, aclTotal: aclTotal }); }) }); } }); } } } }, gateways: { add: { preCheck: function(args) { if (isAdmin()) { //root-admin var items; $.ajax({ url: createURL('listPrivateGateways'), async: false, data: { vpcid: args.context.vpc[0].id, listAll: true }, success: function(json) { items = json.listprivategatewaysresponse.privategateway; } }); if (items && items.length) { return true; //show private gateway listView } else { return false; //show create private gateway dialog } } else { //regular-user, domain-admin return true; //show private gateway listView instead of create private gateway dialog because only root-admin is allowed to create private gateway } }, label: 'label.add.new.gateway', messages: { notification: function(args) { return 'label.add.new.gateway'; } }, createForm: { title: 'label.add.new.gateway', desc: 'message.add.new.gateway.to.vpc', fields: { physicalnetworkid: { docID: 'helpVPCGatewayPhysicalNetwork', label: 'label.physical.network', select: function(args) { $.ajax({ url: createURL("listPhysicalNetworks"), data: { zoneid: args.context.vpc[0].zoneid }, success: function(json) { var objs = json.listphysicalnetworksresponse.physicalnetwork; var items = []; $(objs).each(function() { items.push({ id: this.id, description: this.name }); }); args.response.success({ data: items }); } }); } }, vlan: { label: 'label.vlan', validation: { required: true }, docID: 'helpVPCGatewayVLAN' }, ipaddress: { label: 'label.ip.address', validation: { required: true }, docID: 'helpVPCGatewayIP' }, gateway: { label: 'label.gateway', validation: { required: true }, docID: 'helpVPCGatewayGateway' }, netmask: { label: 'label.netmask', validation: { required: true }, docID: 'helpVPCGatewayNetmask' }, sourceNat: { label: 'label.source.nat', isBoolean: true, isChecked: false }, aclid: { label: 'label.acl', select: function(args) { $.ajax({ url: createURL('listNetworkACLLists'), dataType: 'json', async: true, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var items = []; $(objs).each(function() { if (this.name == "default_deny") items.unshift({ id: this.id, description: this.name }); else items.push({ id: this.id, description: this.name }); }); args.response.success({ data: items }); } }); } } } }, action: function(args) { var array1 = []; if (args.$form.find('.form-item[rel=sourceNat]').find('input[type=checkbox]').is(':Checked') == true) { array1.push("&sourcenatsupported=true"); } else array1.push("&sourcenatsupported=false"); $.ajax({ url: createURL('createPrivateGateway' + array1.join("")), data: { physicalnetworkid: args.data.physicalnetworkid, vpcid: args.context.vpc[0].id, ipaddress: args.data.ipaddress, gateway: args.data.gateway, netmask: args.data.netmask, vlan: args.data.vlan, aclid: args.data.aclid }, 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 } }, 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: 'label.add.private.gateway', preFilter: function(args) { if (isAdmin() || isDomainAdmin()) return true; else return false; }, createForm: { title: 'label.add.new.gateway', desc: 'message.add.new.gateway.to.vpc', fields: { physicalnetworkid: { docID: 'helpVPCGatewayPhysicalNetwork', label: 'label.physical.network', select: function(args) { $.ajax({ url: createURL("listPhysicalNetworks"), data: { zoneid: args.context.vpc[0].zoneid }, success: function(json) { var objs = json.listphysicalnetworksresponse.physicalnetwork; var items = []; $(objs).each(function() { items.push({ id: this.id, description: this.name }); }); args.response.success({ data: items }); } }); } }, vlan: { label: 'label.vlan', validation: { required: true }, docID: 'helpVPCGatewayVLAN' }, ipaddress: { label: 'label.ip.address', validation: { required: true }, docID: 'helpVPCGatewayIP' }, gateway: { label: 'label.gateway', validation: { required: true }, docID: 'helpVPCGatewayGateway' }, netmask: { label: 'label.netmask', validation: { required: true }, docID: 'helpVPCGatewayNetmask' }, sourceNat: { label: 'label.source.nat', isBoolean: true, isChecked: false }, aclid: { label: 'label.acl', select: function(args) { $.ajax({ url: createURL('listNetworkACLLists'), data: { vpcid: args.context.vpc[0].id }, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var items = []; $(objs).each(function() { if (this.name == "default_deny") items.unshift({ id: this.id, description: this.name }); else items.push({ id: this.id, description: this.name }); }); args.response.success({ data: items }); } }); } } } }, action: function(args) { var array1 = []; if (args.$form.find('.form-item[rel=sourceNat]').find('input[type=checkbox]').is(':Checked') == true) { array1.push("&sourcenatsupported=true"); } else array1.push("&sourcenatsupported=false"); $.ajax({ url: createURL('createPrivateGateway' + array1.join("")), data: { physicalnetworkid: args.data.physicalnetworkid, vpcid: args.context.vpc[0].id, ipaddress: args.data.ipaddress, gateway: args.data.gateway, netmask: args.data.netmask, vlan: args.data.vlan, aclid: args.data.aclid }, 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: 'label.details', actions: { remove: { label: 'label.delete.gateway', messages: { confirm: function(args) { return 'message.delete.gateway'; }, notification: function(args) { return 'label.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 } }, replaceACL: { label: 'label.replace.acl', createForm: { title: 'label.replace.acl', label: 'label.replace.acl', fields: { aclid: { label: 'label.acl', select: function(args) { $.ajax({ url: createURL('listNetworkACLLists'), data: { vpcid: args.context.vpc[0].id }, dataType: 'json', async: true, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var items = []; $(objs).each(function() { if (this.id == args.context.vpcGateways[0].aclid) { return true; } items.push({ id: this.id, description: this.name }); return true; }); args.response.success({ data: items }); } }); } } } }, action: function(args) { $.ajax({ url: createURL("replaceNetworkACLList&gatewayid=" + args.context.vpcGateways[0].id + "&aclid=" + args.data.aclid), dataType: "json", success: function(json) { var jid = json.replacenetworkacllistresponse.jobid; args.response.success( { _custom: { jobId: jid, getUpdatedItem: function(json) { var item = json.queryasyncjobresultresponse.jobresult.aclid; return { aclid: args.data.aclid }; } } } ) }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }, notification: { poll: pollAsyncJobResult }, messages: { confirm: function(args) { return 'message.confirm.replace.acl.new.one'; }, notification: function(args) { return 'label.acl.replaced'; } } } }, 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' }, sourcenatsupported: { label: 'label.source.nat.supported', converter: function(str) { return str ? 'Yes' : 'No'; } }, aclName: { label: 'label.acl.name' }, aclid: { label: 'label.acl.id' } }], 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]; // Get ACL name $.ajax({ url: createURL('listNetworkACLLists'), async: false, data: { vpcid: args.context.vpc[0].id }, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var acl = $.grep(objs, function(obj) { return obj.id === args.context.vpcGateways[0].aclid; }); item.aclName = acl[0] ? acl[0].name : 'None'; } }); args.response.success({ data: item, actionFilter: function(args) { var allowedActions = []; if (isAdmin()) { allowedActions.push("remove"); allowedActions.push("replaceACL"); } return allowedActions; } }); } }); } }, staticRoutes: { title: 'label.static.routes', custom: function(args) { return $('
').multiEdit({ noSelect: true, context: args.context, fields: { cidr: { edit: true, label: 'label.CIDR.of.destination.network' }, 'add-rule': { label: 'label.add.route', addButton: true } }, tags: cloudStack.api.tags({ resourceType: 'StaticRoute', contextId: 'multiRule' }), add: { label: '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: 'label.add.static.route', poll: pollAsyncJobResult } }); }, error: function(data) { args.response.error(parseXMLHttpResponse(data)); } }); } }, actions: { destroy: { label: '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: 'label.remove.static.route', poll: pollAsyncJobResult } }); } }); } } }, dataProvider: function(args) { $.ajax({ url: createURL('listStaticRoutes'), data: { gatewayid: args.context.vpcGateways[0].id, listAll: true }, success: function(json) { var items = json.liststaticroutesresponse.staticroute; args.response.success({ data: items }); } }); } }); } } } } } }; } }, siteToSiteVPN: { title: 'label.site.to.site.VPN', id: 'siteToSiteVpn', sectionSelect: { preFilter: function(args) { return ["vpnGateway", "vpnConnection"]; }, label: 'label.select-view' }, // This is a custom add function -- does not show in list view add: { // Check if VPN gateways exist // -- if false, don't show list view preCheck: function(args) { var items; $.ajax({ url: createURL('listVpnGateways&listAll=true'), data: { vpcid: args.context.vpc[0].id }, async: false, success: function(json) { items = json.listvpngatewaysresponse.vpngateway; } }); if (items && items.length) { return true; } return false; }, label: 'label.add.VPN.gateway', messages: { notification: function(args) { return 'label.add.VPN.gateway'; } }, createForm: { title: 'label.add.VPN.gateway', desc: 'message.add.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 } }, sections: { vpnGateway: { type: 'select', title: 'label.VPN.gateway', listView: { id: 'vpnGateway', label: 'label.VPN.gateway', fields: { publicip: { label: 'label.ip.address' }, account: { label: 'label.account' }, domain: { label: 'label.domain' } }, 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: 'label.delete.VPN.gateway', messages: { confirm: function(args) { return 'message.delete.VPN.gateway'; }, notification: function(args) { return 'label.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: { listAll: true, 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: 'label.VPN.connection', listView: { id: 'vpnConnection', label: 'label.VPN.connection', fields: { publicip: { label: 'label.ip.address' }, gateway: { label: 'label.gateway' }, state: { label: 'label.state', indicator: { 'Connected': 'on', 'Disconnected': 'off', 'Error': 'off' } }, ipsecpsk: { label: 'label.IPsec.preshared.key' }, ikepolicy: { label: 'label.IKE.policy' }, esppolicy: { label: '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 }); } }); }, actions: { add: { label: 'label.create.VPN.connection', messages: { notification: function(args) { return 'label.create.VPN.connection'; } }, createForm: { title: 'label.create.VPN.connection', fields: { vpncustomergatewayid: { label: 'label.VPN.customer.gateway', validation: { required: true }, select: function(args) { $.ajax({ url: createURL("listVpnCustomerGateways"), data: { listAll: true }, success: function(json) { var items = json.listvpncustomergatewaysresponse.vpncustomergateway ? json.listvpncustomergatewaysresponse.vpncustomergateway : []; args.response.success({ data: $.map(items, function(item) { return { id: item.id, description: item.name }; }) }); } }); } }, passive: { label: 'label.passive', isBoolean: true, isChecked: false } } }, action: function(args) { var vpngatewayid = null; $.ajax({ url: createURL('listVpnGateways'), data: { listAll: true, vpcid: args.context.vpc[0].id }, 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.data.vpncustomergatewayid, passive: (args.data.passive == 'on'? true: false) }, success: function(json) { var jid = json.createvpnconnectionresponse.jobid; args.response.success({ _custom: { jobId: jid, getUpdatedItem: function(json) { return json.queryasyncjobresultresponse.jobresult.vpnconnection; } } }); }, error: function(xmlHttpResponse) { args.response.error(parseXMLHttpResponse(xmlHttpResponse)); } }); }, notification: { poll: pollAsyncJobResult } } }, detailView: { name: 'label.details', tabs: { details: { title: 'label.details', fields: [{ id: { label: 'label.id' }, passive: { label: 'label.passive', converter: cloudStack.converters.toBooleanText }, publicip: { label: 'label.ip.address' }, gateway: { label: 'label.gateway' }, cidrlist: { label: 'label.CIDR.list' }, ipsecpsk: { label: 'label.IPsec.preshared.key' }, ikepolicy: { label: 'label.IKE.policy' }, esppolicy: { label: 'label.ESP.policy' }, ikelifetime: { label: 'label.IKE.lifetime' }, esplifetime: { label: 'label.ESP.lifetime' }, dpd: { label: 'label.dead.peer.detection', converter: function(str) { return str ? 'Yes' : 'No'; } }, forceencap: { label: 'label.vpn.force.encapsulation', converter: function(str) { return str ? 'Yes' : 'No'; } }, state: { label: 'label.state' }, 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: 'label.reset.VPN.connection', messages: { confirm: function(args) { return 'message.reset.VPN.connection'; }, notification: function(args) { return 'label.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: 'label.delete.VPN.connection', messages: { confirm: function(args) { return 'message.delete.VPN.connection'; }, notification: function(args) { return 'label.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', viewAll: { path: 'network.ipAddresses', label: 'label.menu.ipaddresses', preFilter: function(args) { return false; /// Disabled 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: 'message.confirm.current.guest.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 }; } } }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }, 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 }; } } }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); } }); 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 }; } } }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }, 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 } }, replaceacllist: { label: 'label.replace.acl.list', createForm: { title: 'label.replace.acl.list', label: 'label.replace.acl.list', fields: { aclid: { label: 'label.acl', select: function(args) { $.ajax({ url: createURL('listNetworkACLLists&vpcid=' + args.context.vpc[0].id), dataType: 'json', async: true, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var items = []; $(objs).each(function() { if (this.id == args.context.networks[0].aclid) { return true; } items.push({ id: this.id, description: this.name }); return true; }); args.response.success({ data: items }); } }); } } } }, action: function(args) { $.ajax({ url: createURL("replaceNetworkACLList&networkid=" + args.context.networks[0].id + "&aclid=" + args.data.aclid), dataType: "json", success: function(json) { var jid = json.replacenetworkacllistresponse.jobid; args.response.success({ _custom: { jobId: jid, getUpdatedItem: function(json) { var network = args.context.networks[0]; network.aclid = args.data.aclid; return { aclid: args.data.aclid }; } } }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); }, notification: { poll: pollAsyncJobResult }, messages: { confirm: function(args) { return 'message.confirm.replace.acl.new.one'; }, notification: function(args) { return 'label.acl.replaced'; } } } }, tabFilter: function(args) { var hiddenTabs = ['ipAddresses', 'acl']; // Disable IP address tab; it is redundant with 'view all' button var networkOfferingHavingELB = false; var services = args.context.networks[0].service; if(services != null) { for(var i = 0; i < services.length; i++) { if (services[i].name == "Lb") { var capabilities = services[i].capability; if(capabilities != null) { for(var k = 0; k < capabilities.length; k++) { if(capabilities[k].name == "ElasticLb") { networkOfferingHavingELB = true; break; } } } break; } } } if (networkOfferingHavingELB == false) { hiddenTabs.push("addloadBalancer"); } return hiddenTabs; }, isMaximized: true, tabs: { details: { title: 'label.network.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' }, ispersistent: { label: 'label.persistent', converter: cloudStack.converters.toBooleanText }, restartrequired: { label: 'label.restart.required', converter: function(booleanValue) { if (booleanValue == true) return "Yes"; else if (booleanValue == false) return "No"; } }, vlan: { label: '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 }); }); } }); //include currently selected network offeirng to dropdown items.push({ id: args.context.networks[0].networkofferingid, description: args.context.networks[0].networkofferingdisplaytext }); args.response.success({ data: items }); } }, gateway: { label: 'label.gateway' }, //netmask: { label: 'Netmask' }, cidr: { label: 'label.cidr' }, networkdomaintext: { label: 'label.network.domain.text' }, networkdomain: { label: 'label.network.domain', isEditable: true }, aclname: { label: 'label.acl.name' }, //aclid:{label:'ACL id'}, 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]; if (jsonObj.aclid != null) { $.ajax({ url: createURL("listNetworkACLLists&id=" + jsonObj.aclid), dataType: "json", success: function(json) { var aclObj = json.listnetworkacllistsresponse.networkacllist[0]; args.response.success({ actionFilter: cloudStack.actionFilter.guestNetwork, data: $.extend(jsonObj, { aclname: aclObj.name }) }); }, error: function(json) { args.response.error(parseXMLHttpResponse(json)); } }); } else { args.response.success({ actionFilter: cloudStack.actionFilter.guestNetwork, data: $.extend(jsonObj, { aclname: 'None' }) }); } } }); } }, acl: { title: 'label.network.ACL', custom: function(args) { // Widget renders ACL multi-edit, overriding this fn return $('
'); } }, ipAddresses: { title: 'label.menu.ipaddresses', custom: function(args) { // Widget renders IP addresses, overriding this fn return $('
'); } }, 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.lb.algorithm.roundrobin') }, { name: 'leastconn', description: _l('label.lb.algorithm.leastconn') }, { name: 'source', description: _l('label.lb.algorithm.source') }] }); } }, 'sticky': { label: 'label.stickiness', custom: { buttonLabel: 'label.configure', action: cloudStack.lbStickyPolicy.dialog() } }, 'add-vm': { label: 'label.add.vm', addButton: true } }, add: { label: 'label.add.vm', 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.networks[0]; var state = tier.state; return state == 'Running' ? ['start'] : ['stop']; }, actions: { add: { label: 'label.add.new.tier', createForm: { title: 'label.add.new.tier', fields: { name: { label: 'label.name', validation: { required: true }, docID: 'helpTierName' }, networkOfferingId: { label: 'label.network.offering', docID: 'helpTierNetworkOffering', validation: { required: true }, dependsOn: 'zoneId', select: function(args) { var publicLbNetworkExists = false; $.ajax({ url: createURL('listNetworks'), data: { vpcid: args.context.vpc[0].id, supportedservices: 'LB' }, success: function(json) { var publicLbNetworkExists = false; var lbNetworks = json.listnetworksresponse.network; if (lbNetworks != null) { for (var i = 0; i < lbNetworks.length; i++) { var thisNetworkOfferingIncludesPublicLbService = false; $.ajax({ url: createURL('listNetworkOfferings'), data: { id: lbNetworks[i].networkofferingid }, async: false, success: function(json) { var networkOffering = json.listnetworkofferingsresponse.networkoffering[0]; $(networkOffering.service).each(function() { var thisService = this; if (thisService.name == "Lb" && lbProviderMap.publicLb.vpc.indexOf(thisService.provider[0].name) != -1) { thisNetworkOfferingIncludesPublicLbService = true; return false; //break $.each() loop } }); } }); if (thisNetworkOfferingIncludesPublicLbService == true) { publicLbNetworkExists = true; break; //break for loop } } } $.ajax({ url: createURL('listNetworkOfferings'), data: { forvpc: true, zoneid: args.zoneId, guestiptype: 'Isolated', supportedServices: 'SourceNat', state: 'Enabled' }, success: function(json) { var networkOfferings = json.listnetworkofferingsresponse.networkoffering; args.$select.change(function() { var $vlan = args.$select.closest('form').find('[rel=vlan]'); var networkOffering = $.grep( networkOfferings, function(netoffer) { return netoffer.id == args.$select.val(); } )[0]; if (networkOffering.specifyvlan) { $vlan.css('display', 'inline-block'); } else { $vlan.hide(); } }); //only one network(tier) is allowed to have PublicLb (i.e. provider is PublicLb provider like "VpcVirtualRouter", "Netscaler") in a VPC var items; if (publicLbNetworkExists == true) { //so, if a PublicLb network(tier) already exists in the vpc, exclude PublicLb network offerings from dropdown items = $.grep(networkOfferings, function(networkOffering) { var thisNetworkOfferingIncludesPublicLbService = false; $(networkOffering.service).each(function() { var thisService = this; if (thisService.name == "Lb" && lbProviderMap.publicLb.vpc.indexOf(thisService.provider[0].name) != -1) { thisNetworkOfferingIncludesPublicLbService = true; return false; //break $.each() loop } }); return !thisNetworkOfferingIncludesPublicLbService; }); } else { items = networkOfferings; } args.response.success({ data: $.map(items, function(item) { return { id: item.id, description: item.name }; }) }); } }); } }); } }, vlan: { label: 'label.vlan', validation: { required: true }, isHidden: true }, gateway: { label: 'label.gateway', docID: 'helpTierGateway', validation: { required: true } }, netmask: { label: 'label.netmask', docID: 'helpTierNetmask', validation: { required: true } }, aclid: { label: 'label.acl', select: function(args) { $.ajax({ url: createURL('listNetworkACLLists&vpcid=' + args.context.vpc[0].id), dataType: 'json', async: true, success: function(json) { var objs = json.listnetworkacllistsresponse.networkacllist; var items = []; items.push({ id: '', description: '' }); $(objs).each(function() { items.push({ id: this.id, description: this.name }); }); args.response.success({ data: items }); } }); } }, zoneid: { label: 'label.zone', validation: { required: true }, isHidden: true, select: function(args) { //var $zoneSelect = $(".ui-dialog-content").find('select.zoneid'); var $zoneSelect = args.$select.closest('form').find('[rel=zoneid]'); if (!args.context.regions) { $zoneSelect.hide(); args.response.success({ data: [] }); } else { $zoneSelect.css('display', 'inline-block'); $.ajax({ url: createURL('listZones'), success: function(json) { var zones = $.grep(json.listzonesresponse.zone, function(zone) { return (zone.networktype == 'Advanced'); }); args.response.success({ data: $.map(zones, function(zone) { return { id: zone.id, description: zone.name }; }) }); } }); } } } } }, action: function(args) { var dataObj = { vpcid: args.context.vpc[0].id, domainid: args.context.vpc[0].domainid, account: args.context.vpc[0].account, networkOfferingId: args.data.networkOfferingId, name: args.data.name, displayText: args.data.name, gateway: args.data.gateway, netmask: args.data.netmask }; if (args.context.regions) $.extend(dataObj, { zoneId: args.data.zoneid }) else $.extend(dataObj, { zoneId: args.context.vpc[0].zoneid }); if (args.data.aclid != '') $.extend(dataObj, { aclid: args.data.aclid }); if (args.$form.find('.form-item[rel=vlan]').is(':visible')) { $.extend(dataObj, { vlan: args.data.vlan }); } $.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 'label.add.new.tier'; } } }, /* start: { label: 'Start tier', shortLabel: 'Start', action: function(args) { args.response.success(); }, notification: { poll: function(args) { args.complete({ data: { state: 'Running' } }); } } }, */ /* stop: { label: 'Stop tier', shortLabel: 'Stop', action: function(args) { args.response.success(); }, notification: { poll: function(args) { args.complete({ data: { state: 'Stopped' } }); } } }, */ addVM: { label: 'label.add.VM.to.tier', shortLabel: 'label.add.vm', action: cloudStack.uiCustom.instanceWizard( $.extend(true, {}, cloudStack.instanceWizard, { pluginForm: { name: 'vpcTierInstanceWizard' } }) ), notification: { poll: pollAsyncJobResult } }, // Removing ACL buttons from the tier chart /* acl: { label: 'Configure ACL for tier', shortLabel: 'ACL', multiEdit: aclMultiEdit }, */ remove: { label: 'label.remove.tier', 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: pollAsyncJobResult } } }, // Get tiers dataProvider: function(args) { $.ajax({ url: createURL("listNetworks"), dataType: "json", data: { vpcid: args.context.vpc[0].id, //listAll: true, //do not pass listAll to listNetworks under VPC domainid: args.context.vpc[0].domainid, account: args.context.vpc[0].account }, async: true, success: function(json) { var networks = json.listnetworksresponse.network; var networkACLLists, publicIpAddresses, privateGateways, vpnGateways; var error = false; // Get network ACL lists $.ajax({ url: createURL('listNetworkACLLists'), data: { 'vpcid': args.context.vpc[0].id }, async: false, success: function(json) { networkACLLists = json.listnetworkacllistsresponse; }, error: function(json) { error = true; } }); // Get public IPs $.ajax({ url: createURL('listPublicIpAddresses'), async: false, data: { vpcid: args.context.vpc[0].id, listAll: true }, success: function(json) { publicIpAddresses = json.listpublicipaddressesresponse; }, error: function(json) { error = true; } }); // Get private gateways $.ajax({ url: createURL('listPrivateGateways'), async: false, data: { 'vpcid': args.context.vpc[0].id, listAll: true }, success: function(json) { privateGateways = json.listprivategatewaysresponse; }, error: function(json) { error = true; } }); // Get VPN gateways $.ajax({ url: createURL('listVpnGateways'), async: false, data: { listAll: true, 'vpcid': args.context.vpc[0].id }, success: function(json) { vpnGateways = json.listvpngatewaysresponse; }, error: function(json) { error = true; } }); args.response.success({ routerDashboard: [{ id: 'privateGateways', name: 'Private gateways', total: privateGateways.count }, { id: 'publicIPs', name: 'Public IP addresses', total: publicIpAddresses.count }, { id: 'siteToSiteVPNs', name: 'Site-to-site VPNs', total: vpnGateways.count }, { id: 'networkACLLists', name: 'Network ACL lists', total: networkACLLists.count }], tiers: $(networks).map(function(index, tier) { var internalLoadBalancers, publicLbIps, virtualMachines, staticNatIps; // Get internal load balancers $.ajax({ url: createURL('listLoadBalancers&listAll=true'), async: false, data: { networkid: tier.id }, success: function(json) { internalLoadBalancers = json.listloadbalancersresponse; }, error: function(json) { error = true; } }); // Get Public LB IPs $.ajax({ url: createURL('listPublicIpAddresses&listAll=true'), async: false, data: { associatednetworkid: tier.id, forloadbalancing: true }, success: function(json) { publicLbIps = json.listpublicipaddressesresponse; }, error: function(json) { error = true; } }); // Get static NAT IPs $.ajax({ url: createURL('listPublicIpAddresses&listAll=true'), async: false, data: { associatednetworkid: tier.id, isstaticnat: true }, success: function(json) { staticNatIps = json.listpublicipaddressesresponse; }, error: function(json) { error = true; } }); // Get VMs $.ajax({ url: createURL('listVirtualMachines&listAll=true'), async: false, data: { networkid: tier.id }, success: function(json) { virtualMachines = json.listvirtualmachinesresponse; }, error: function(json) { error = true; } }); // Highlight if any tier VM contains guest network $.grep( virtualMachines.virtualmachine ? virtualMachines.virtualmachine : [], function(vm) { return $.grep(vm.nic, function(nic) { return nic.type == 'Shared'; }).length; } ).length ? tier._highlighted = true : tier._highlighted = false; // Get LB capabilities var lbSchemes = $.grep( tier.service, function(service) { return service.name == 'Lb'; } ).length ? $.grep($.grep( tier.service, function(service) { return service.name == 'Lb'; } )[0].capability, function(capability) { return capability.name == 'LbSchemes'; }) : []; /* var lbSchemes = $.grep( $.grep( tier.service, function(service) { return service.name == 'Lb'; } )[0].capability, function(capability) { return capability.name == 'LbSchemes'; } );*/ var hasLbScheme = function(schemeVal) { return $.grep( lbSchemes, function(scheme) { return scheme.value == schemeVal; } ).length ? true : false; }; return $.extend(tier, { _dashboardItems: [{ id: 'internalLoadBalancers', name: 'Internal LB', total: internalLoadBalancers.count, _disabled: !hasLbScheme('Internal') }, { id: 'publicLbIps', name: 'Public LB IP', total: publicLbIps.count, _disabled: !hasLbScheme('Public') }, { id: 'tierStaticNATs', name: 'Static NATs', total: staticNatIps.count }, { id: 'tierVMs', name: 'Virtual Machines', total: virtualMachines.count }] }); }) }); if (error) { cloudStack.dialog.notice({ message: 'Error loading dashboard data.' }); } } }); } } }; }(jQuery, cloudStack));