Rohit Yadav 4534cefa40
backports for 4.11.1 from master (#2621)
* CLOUDSTACK-10147 Disabled Xenserver Cluster can still deploy VM's. Added code to skip disabled clusters when selecting a host (#2442)

(cherry picked from commit c3488a51db4bce4ec32c09e6fef78193d360cf3f)
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* CLOUDSTACK-10318: Bug on sorting ACL rules list in chrome (#2478)

(cherry picked from commit 4412563f19ec8b808fe4c79e2baf658507a84873)
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* CLOUDSTACK-10284:Creating a snapshot from VM Snapshot generates error if hypervisor is not KVM.

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* CLOUDSTACK-10221: Allow IPv6 when creating a Basic Network (#2397)

Since CloudStack 4.10 Basic Networking supports IPv6 and thus
should be allowed to be specified when creating a network.

Signed-off-by: Wido den Hollander <wido@widodh.nl>
(cherry picked from commit 9733a10ecda5f1af0f2c0fa863fc976a3e710946)
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* CLOUDSTACK-10214: Unable to remove local primary storage (#2390)

Allow admins to remove primary storage pool.
Cherry-picked from eba2e1d8a1ce4e86b4df144db03e96739da455e5

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* dateutil: constistency of tzdate input and output (#2392)

Signed-off-by: Yoan Blanc <yoan.blanc@exoscale.ch>
Signed-off-by: Daan Hoogland <daan.hoogland@shapeblue.com>
(cherry picked from commit 2ad520282319da9a03061b8c744e51a4ffdf94a2)
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* CLOUDSTACK-10054:Volume download times out in 3600 seconds (#2244)

(cherry picked from commit bb607d07a97476dc4fb934b3d75df6affba47086)
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>

* When creating a new account (via domain admin) it is possible to select “root admin” as the role for the new user (#2606)

* create account with domain admin showing 'root admin' role

Domain admins should not be able to assign the role of root admin to new users. Therefore, the role ‘root admin’ (or any other of the same type) should not be visible to domain admins.

* License and formatting

* Break long sentence into multiple lines

* Fix wording of method 'getCurrentAccount'

* fix typo in variable name

* [CLOUDSTACK-10259] Missing float part of secondary storage data in listAccounts

* [CLOUDSTACK-9338] ACS not accounting resources of VMs with custom service offering

ACS is accounting the resources properly when deploying VMs with custom service offerings. However, there are other methods (such as updateResourceCount) that do not execute the resource accounting properly, and these methods update the resource count for an account in the database. Therefore, if a user deploys VMs with custom service offerings, and later this user calls the “updateResourceCount” method, it (the method) will only account for VMs with normal service offerings, and update this as the number of resources used by the account. This will result in a smaller number of resources to be accounted for the given account than the real used value. The problem becomes worse because if the user starts to delete these VMs, it is possible to reach negative values of resources allocated (breaking all of the resource limiting for accounts). This is a very serious attack vector for public cloud providers!

* [CLOUDSTACK-10230] User should not be able to use removed “Guest OS type” (#2404)

* [CLOUDSTACK-10230] User is able to change to “Guest OS type” that has been removed

Users are able to change the OS type of VMs to “Guest OS type” that has been removed. This becomes a security issue when we try to force users to use HVM VMs (Meltdown/Spectre thing). A removed “guest os type” should not be usable by any users in the cloud.

* Remove trailing lines that are breaking build due to checkstyle compliance

* Remove unused imports

* fix classes that were in the wrong folder structure

* Updates to capacity management
2018-05-09 15:20:19 +05:30

4518 lines
227 KiB
JavaScript

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
(function($, cloudStack) {
var isNumeric = function (n) {
return !isNaN(parseFloat(n));
};
var createSafeCsvValue = function(value){
if(value){
return '"' + value + '"';
}
return "";
};
var generateCsvForAclRules = function(aclRules){
var csv = createSafeCsvValue('id') + ',';
for(var field in aclRuleFields){
var fieldLabel = aclRuleFields[field].label;
var fieldLabelTranslated = _l(fieldLabel);
csv = csv + createSafeCsvValue(fieldLabelTranslated) + ',';
}
csv = csv.substr(0, csv.length - 1) + '\n';
if(!aclRules){
return csv;
}
aclRules.forEach(function(entry){
csv = csv +
createSafeCsvValue(entry.id) + ',' +
createSafeCsvValue(entry.number) + ',' +
createSafeCsvValue(entry.cidrlist) + ',' +
createSafeCsvValue(entry.action) + ',' ;
if(isNumeric(entry.protocol)){
csv = csv +
createSafeCsvValue(_l('label.protocol.number')) + ',' +
createSafeCsvValue(entry.protocol) + ',';
}else{
csv = csv +
createSafeCsvValue(entry.protocol) + ',' +
createSafeCsvValue('') + ',';
}
csv = csv +
createSafeCsvValue(entry.startport) + ',' +
createSafeCsvValue(entry.endport) + ',' +
createSafeCsvValue(entry.icmptype) + ',' +
createSafeCsvValue(entry.icmpcode) + ',' +
createSafeCsvValue(entry.traffictype) + ',' +
createSafeCsvValue(entry.reason) + '\n';
});
return csv;
};
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 aclRuleFields = {
'number': {
label: 'label.rule.number.short',
desc: '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();
$portFields.attr('disabled', 'disabled');
$icmpFields.hide();
$icmpFields.attr('disabled', 'disabled');
$protocolFields.attr('disabled', 'disabled');
$protocolFields.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.hide();
$portFields.attr('disabled', 'disabled');
$icmpFields.hide();
$icmpFields.attr('disabled', 'disabled');
$protocolFields.hide();
$protocolFields.attr('disabled', 'disabled');
} 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.short',
desc: '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
},
'icmptype': {
edit: true,
label: 'ICMP.type',
desc: 'ICMP.type.desc',
defaultValue: '-1',
isEditable: true
},
'icmpcode': {
edit: true,
label: 'ICMP.code',
desc: 'ICMP.code.desc',
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'
}]
});
}
},
'reason': {
edit: true,
label: 'label.acl.reason',
desc: 'label.acl.reason.description',
isEditable: true,
isTextarea: true
}
};
var aclRuleFieldsForMultiEdit = {
'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
};
})
});
}
});
}
},
};
jQuery.extend(aclRuleFieldsForMultiEdit, aclRuleFields);
var aclMultiEdit = {
doNotShowInputTable: true,
editOptionsFirst: true,
noSelect: true,
reorder: {
moveDrag: {
action: function(args) {
var rule = args.context.multiRule[0];
var previousRuleId = args.prevItem ? args.prevItem.id : undefined;
var nextRuleId = args.nextItem ? args.nextItem.id : undefined;
$.ajax({
url: createURL('moveNetworkAclItem'),
data: {
id: rule.id,
previousaclruleid: previousRuleId,
nextaclruleid: nextRuleId
},
success: function(json) {
var pollTimer = setInterval(function() {
pollAsyncJobResult({
_custom: {
jobId: json.moveNetworkAclItemResponse.jobid
},
complete: function() {
clearInterval(pollTimer);
args.response.success();
},
error: function(errorMsg) {
clearInterval(pollTimer);
args.response.error(errorMsg);
}
});
}, 1000);
}
});
}
}
},
fields: aclRuleFieldsForMultiEdit,
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,
reason: args.data.reason
};
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;
}
data.partialupgrade = false;
$.ajax({
url: createURL('updateNetworkACLItem'),
data: data,
type: "POST",
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) {
var data = {
page: args.page,
pageSize: pageSize,
networkid: args.context.networks[0].id,
listAll: true
};
var keyword = (((args || {}).filterBy || {}).search || {}).value;
if (keyword) {
data.keyword = keyword;
}
$.ajax({
url: createURL('listLoadBalancers'),
data: data,
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
});
}
});
}
},
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,
listall: 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
}
},
edit: {
label: 'label.edit.acl.list',
action: function(args) {
var data = args.data;
data.id = args.context.aclLists[0].id;
$.ajax({
url: createURL('updateNetworkACLList'),
type: "POST",
data: data,
success: function(json) {
var jid = json.updatenetworkacllistresponse.jobid;
args.response.success({
_custom: {
jobId: jid,
getUpdatedItem: function() {
$(window).trigger('cloudStack.fullRefresh');
jQuery('div[id=breadcrumbs] ul:visible li span').last().html(data.name);
}
}
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
},
notification: {
poll: pollAsyncJobResult,
desc: 'label.edit.acl.list'
}
}
},
tabs: {
details: {
title: 'label.details',
fields: [{
name: {
label: 'label.name',
isEditable: true
},
description: {
label: 'label.description',
isEditable: true
},
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");
allowedActions.push("edit");
}
return allowedActions;
}
});
});
}
},
aclRules: {
title: 'label.acl.list.rules',
custom: function(args) {
return $('<div>').multiEdit($.extend(true, {}, aclMultiEdit, {
context: args.context,
fields: {
networkid: false
},
dataProvider: function(args) {
var aclListId = args.context.aclLists[0].id;
$.ajax({
url: createURL('listNetworkACLs&aclid=' + aclListId),
success: function(json) {
var items = json.listnetworkaclsresponse.networkacl;
if(items){
items.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
});
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.add').size() === 0){
var $addAclRuleDivButton = jQuery('<div>').addClass('button add');
var $spanAddAclRuleButtonMessage = jQuery('<span>').html(_l('label.add.ACL'));
$addAclRuleDivButton.html($spanAddAclRuleButtonMessage);
$addAclRuleDivButton.click(function(){
cloudStack.dialog.createForm({
form: {
title: 'label.add.rule',
desc: 'label.add.rule.desc',
fields: aclRuleFields
},
after: function(argsLocal) {
var data = argsLocal.data;
data.aclid = argsLocal.context.aclLists[0].id;
if(data.protocol != 'icmp'){
data.icmpcode = undefined;
data.icmptype = undefined;
}
if(data.protocol != 'protocolnumber'){
data.protocolnumber = undefined;
}else{
data.protocol = data.protocolnumber;
data.protocolnumber = undefined;
}
if(data.protocol === 'all'){
data.startport = undefined;
data.endport = undefined;
}
$.ajax({
url: createURL('createNetworkACL'),
data: argsLocal.data,
type: "POST",
success: function(json) {
jQuery('button.cancel:visible').click();
jQuery('div.toolbar:visible div.refresh').click();
}
});
},
context: args.context
});
});
jQuery('#details-tab-aclRules').siblings('div.toolbar').append($addAclRuleDivButton);
}
if(jQuery('#details-tab-aclRules').siblings('div.toolbar').children('div.export').size() === 0){
var $exportAclsDivButton = jQuery('<div>').addClass('button export');
var $linkExportAclRulesButtonMessage = jQuery('<a>').html(_l('label.acl.export'));
$exportAclsDivButton.html($linkExportAclRulesButtonMessage);
$exportAclsDivButton.click(function(){
$.ajax({
url: createURL('listNetworkACLs&aclid=' + aclListId),
type: "GET",
async: false,
success: function(json) {
var acls = json.listnetworkaclsresponse.networkacl;
var csv = generateCsvForAclRules(acls);
window.URL = window.URL || window.webkiURL;
var blob = new Blob([csv]);
var blobURL = window.URL.createObjectURL(blob);
$linkExportAclRulesButtonMessage.attr("href", blobURL);
$linkExportAclRulesButtonMessage.attr("download", "aclRules.csv");
}
});
});
jQuery('#details-tab-aclRules').siblings('div.toolbar').append($exportAclsDivButton);
}
}
});
}
}));
}
}
}
}
}
},
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 $('<div>').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=" + encodeURIComponent(args.data.name));
array1.push("&displaytext=" + encodeURIComponent(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=" + encodeURIComponent(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=" + encodeURIComponent(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 "<font color='red'>Yes</font>";
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 $('<div>');
}
},
ipAddresses: {
title: 'label.menu.ipaddresses',
custom: function(args) {
// Widget renders IP addresses, overriding this fn
return $('<div>');
}
},
addloadBalancer: {
title: 'label.add.load.balancer',
custom: function(args) {
var context = args.context;
return $('<div>').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
}
},
externalId: {
label: 'label.guest.externalId'
},
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.externalId != null && args.data.externalId.length > 0) {
$.extend(dataObj, {
externalid: args.data.externalId
});
}
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 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));