(function(cloudStack, $, testData) {
var actionFilters = {
ipAddress: function(args) {
var allowedActions = args.context.actions;
var disallowedActions = [];
var item = args.context.item;
var status = item.state;
if (status == 'Released') {
return [];
}
if (status == 'Destroyed' ||
status == 'Releasing' ||
status == 'Released' ||
status == 'Creating' ||
status == 'Allocating' ||
item.account == 'system') {
disallowedActions = allowedActions;
}
if (item.isstaticnat) {
disallowedActions.push('enableStaticNAT');
} else {
disallowedActions.push('disableStaticNAT');
}
if (item.vpnenabled) {
disallowedActions.push('enableVPN');
} else {
disallowedActions.push('disableVPN');
}
if (item.issourcenat){
disallowedActions.push('enableStaticNAT');
disallowedActions.push('disableStaticNAT');
disallowedActions.push('destroy');
} else {
disallowedActions.push('enableVPN');
disallowedActions.push('disableVPN');
}
allowedActions = $.grep(allowedActions, function(item) {
return $.inArray(item, disallowedActions) == -1;
});
return allowedActions;
},
securityGroups: function(args) {
var allowedActions = [];
var isSecurityGroupOwner = isAdmin() ||
args.context.item.account == args.context.users[0].account;
if (isSecurityGroupOwner &&
args.context.item.state != 'Destroyed' &&
args.context.item.name != 'default') {
allowedActions.push('destroy');
}
return allowedActions;
}
};
cloudStack.sections.network = {
title: 'Network',
id: 'network',
sectionSelect: {
preFilter: function(args) {
var isSecurityGroupEnabled = false;
var hasIsolatedNetworks = false;
$.ajax({
url: createURL('listNetworks'),
data: {
supportedServices: 'SecurityGroup'
},
async: false,
success: function(data) {
$.ajax({
url: createURL('listNetworks'),
data: {
type: 'isolated',
supportedServices: 'SourceNat'
},
async: false,
success: function(data) {
if (data.listnetworksresponse.network &&
data.listnetworksresponse.network.length) {
hasIsolatedNetworks = true;
}
}
});
if (data.listnetworksresponse.network &&
data.listnetworksresponse.network.length) {
isSecurityGroupEnabled = true;
}
}
});
if (isSecurityGroupEnabled && !hasIsolatedNetworks) return ['securityGroups'];
if (isSecurityGroupEnabled && hasIsolatedNetworks) return ['securityGroups', 'networks'];
return ['networks'];
},
label: 'Select view'
},
sections: {
networks: {
id: 'networks',
type: 'select',
title: 'Guest Networks',
listView: {
actions: {
add: {
label: 'Add guest network',
createForm: {
title: 'Add new guest network',
desc: 'Please specify name and zone for this network; note that network will be isolated and source NAT-enabled.',
fields: {
name: { label: 'Name', validation: { required: true } },
displayText: { label: 'Display Text', validation: { required: true }},
zoneId: {
label: 'Zone',
validation: { required: true },
select: function(args) {
$.ajax({
url: createURL('listZones'),
data: {
type: 'Advanced'
},
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
};
})
});
}
});
}
},
networkOfferingId: {
label: 'Network Offering',
validation: { required: true },
select: function(args) {
$.ajax({
url: createURL('listNetworkOfferings'),
data: {
supportedServices: 'SourceNat',
type: 'isolated',
state: 'Enabled'
},
success: function(json) {
var networkOfferings = json.listnetworkofferingsresponse.networkoffering;
args.response.success({
data: $.map(networkOfferings, function(zone) {
return {
id: zone.id,
description: zone.name
};
})
});
}
});
}
}
}
},
action: function(args) {
$.ajax({
url: createURL('createNetwork'),
data: args.data,
success: function(json) {
args.response.success({
data: json.createnetworkresponse.network
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
},
messages: {
notification: function() { return 'Added guest network'; }
}
}
},
id: 'networks',
fields: {
name: { label: 'Name' },
accounts: { label: 'Account' },
zonename: { label: 'Zone' },
type: { label: 'Type' },
vlan: { label: 'VLAN' },
cidr: { label: 'CIDR' },
state: { label: 'State', indicator: {
'Implemented': 'on', 'Setup': 'on', 'Allocated': 'on',
'Destroyed': 'off'
} }
},
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("listNetworks&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
data: {
type: 'isolated',
supportedServices: 'SourceNat'
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: data.listnetworksresponse.network
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
detailView: {
name: 'Guest network details',
viewAll: {
path: 'network.ipAddresses',
label: 'IP addresses',
preFilter: function(args) {
if (args.context.networks[0].state == 'Destroyed') return false;
return true;
}
},
actions: {
edit: {
label: 'Edit',
messages: {
confirm: function(args) {
return 'Are you sure you want to edit network?';
},
success: function(args) {
return 'Network is being edited.';
},
notification: function(args) {
return 'Editing network';
},
complete: function(args) {
return 'Network has been edited.';
}
},
action: function(args) {
var array1 = [];
array1.push("&name=" + todb(args.data.name));
array1.push("&displaytext=" + todb(args.data.displaytext));
//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));
//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));
$.ajax({
url: createURL("updateNetwork&id=" + args.context.networks[0].id + array1.join("")),
dataType: "json",
success: function(json) {
var jid = json.updatenetworkresponse.jobid;
args.response.success(
{_custom:
{jobId: jid,
getUpdatedItem: function(json) {
var item = json.queryasyncjobresultresponse.jobresult.network;
return {data: item};
}
}
}
);
}
});
},
notification: {
poll: pollAsyncJobResult
}
},
'restart': {
label: 'Restart network',
createForm: {
title: 'Restart network',
desc: 'Please confirm that you want to restart network',
fields: {
cleanup: {
label: 'Clean up',
isBoolean: true,
isChecked: false
}
}
},
messages: {
confirm: function(args) {
return 'Please confirm that you want to restart network';
},
notification: function(args) {
return 'Restarting 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
}
},
destroy: {
label: 'Delete network',
messages: {
confirm: function(args) {
return 'Are you sure you want to delete network ?';
},
notification: function(args) {
return 'Deleting 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,
getUpdatedItem: function(json) {
return { state: 'Destroyed' }; //nothing in this network needs to be updated, in fact, this whole template has being deleted
}
}
}
);
}
});
},
notification: {
poll: pollAsyncJobResult
}
}
},
tabs: {
details: {
title: '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("netmask");
}
if(args.context.networks[0].type == "Isolated") {
hiddenFields.push("networkofferingdisplaytext");
hiddenFields.push("networkdomaintext");
hiddenFields.push("gateway");
//hiddenFields.push("netmask");
}
else { //selectedGuestNetworkObj.type == "Shared"
hiddenFields.push("networkofferingid");
hiddenFields.push("networkdomain");
}
return hiddenFields;
},
fields: [
{
name: {
label: 'Name',
isEditable: true
}
},
{
id: { label: 'ID' },
displaytext: {
label: 'Description',
isEditable: true
},
type: {
label: 'Type'
},
state: {
label: 'State'
},
restartrequired: {
label: 'Restart required',
converter: function(booleanValue) {
if(booleanValue == true)
return "Yes";
else if(booleanValue == false)
return "No";
}
},
vlan: { label: 'VLAN ID' },
scope: { label: 'Scope' },
//networkofferingdisplaytext: { label: 'Network offering' },
networkofferingid: {
label: 'Network offering',
isEditable: true,
select: function(args){
if (args.context.networks[0].state == 'Destroyed') {
args.response.success({ data: [] });
return;
}
var items = [];
$.ajax({
url: createURL("listNetworkOfferings&networkid=" + args.context.networks[0].id),
dataType: "json",
async: false,
success: function(json) {
var networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering;
$(networkOfferingObjs).each(function() {
items.push({id: this.id, description: this.displaytext});
});
}
});
$.ajax({
url: createURL("listNetworkOfferings&id=" + args.context.networks[0].networkofferingid), //include currently selected network offeirng to dropdown
dataType: "json",
async: false,
success: function(json) {
var networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering;
$(networkOfferingObjs).each(function() {
items.push({id: this.id, description: this.displaytext});
});
}
});
args.response.success({data: items});
}
},
gateway: { label: 'Gateway' },
//netmask: { label: 'Netmask' },
cidr: { label: 'CIDR' },
networkdomaintext: {
label: 'Network domain'
},
networkdomain: {
label: 'Network domain',
isEditable: true
}
}
],
dataProvider: function(args) {
args.response.success({
actionFilter: function(args) {
if (args.context.networks[0].state == 'Destroyed')
return [];
return args.context.actions;
},
data: args.context.networks[0]
});
}
}
}
}
}
},
ipAddresses: {
type: 'select',
title: 'IP Addresses',
listView: {
id: 'ipAddresses',
label: 'IPs',
filters: {
allocated: { label: 'Allocated ' },
mine: { label: 'My network' }
},
fields: {
ipaddress: {
label: 'IP',
converter: function(text, item) {
if (item.issourcenat) {
return text + ' [Source NAT]';
}
return text;
}
},
zonename: { label: 'Zone' },
vlanname: { label: 'VLAN' },
account: { label: 'Account' },
state: { label: 'State', indicator: { 'Allocated': 'on', 'Released': 'off' } }
},
actions: {
add: {
label: 'Acquire new IP',
addRow: 'true',
action: function(args) {
$.ajax({
url: createURL('associateIpAddress'),
data: {
networkId: args.context.networks[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.associateipaddressresponse.jobid,
getUpdatedItem: function(data) {
var newIP = data.queryasyncjobresultresponse.jobresult.ipaddress;
return $.extend(newIP, {
state: 'Allocated'
});
},
getActionFilter: function() {
return actionFilters.ipAddress;
}
}
});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
},
messages: {
confirm: function(args) {
return 'Please confirm that you would like to acquire a net IP for this network.';
},
notification: function(args) {
return 'Allocated IP';
}
},
notification: {
poll: pollAsyncJobResult
}
},
enableStaticNAT: {
label: 'Enable static NAT',
action: {
noAdd: true,
custom: cloudStack.uiCustom.enableStaticNAT({
listView: $.extend(true, {}, cloudStack.sections.instances, {
listView: {
dataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
networkid: args.context.networks[0].id
},
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));
}
});
}
}
}),
action: function(args) {
$.ajax({
url: createURL('enableStaticNat'),
data: {
ipaddressid: args.context.ipAddresses[0].id,
virtualmachineid: args.context.instances[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success();
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
})
},
messages: {
confirm: function(args) {
return 'Are you sure you want to enable static NAT?';
},
notification: function(args) {
return 'Enabled Static NAT';
}
},
notification: {
poll: function(args) {
args.complete({
data: {
isstaticnat: true
}
});
}
}
},
disableStaticNAT: {
label: 'Disable static NAT',
action: function(args) {
$.ajax({
url: createURL('disableStaticNat'),
data: {
ipaddressid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.disablestaticnatresponse.jobid,
getUpdatedItem: function(json) {
return $.extend(args.context.ipAddresses[0], {
isstaticnat: false
});
},
getActionFilter: function() {
return actionFilters.ipAddresses;
}
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Are you sure you want to disable static NAT?';
},
notification: function(args) {
return 'Disable Static NAT';
}
},
notification: {
poll: pollAsyncJobResult
}
},
destroy: {
label: 'Release IP',
action: function(args) {
$.ajax({
url: createURL('disassociateIpAddress'),
data: {
id: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.disassociateipaddressresponse.jobid,
getActionFilter: function() {
return function(args) {
var allowedActions = [];
return allowedActions;
};
},
getUpdatedItem: function(args) {
return {
state: 'Released'
};
}
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Are you sure you want to release this IP?';
},
notification: function(args) {
return 'Release IP';
}
},
notification: { poll: pollAsyncJobResult }
}
},
dataProvider: function(args) {
var data = {
page: args.page,
pageSize: pageSize
};
if (g_supportELB == "guest") // IPs are allocated on guest network
$.extend(data, {
forvirtualnetwork: false,
forloadbalancing: true
});
else if(g_supportELB == "public") // IPs are allocated on public network
$.extend(data, {
forvirtualnetwork: true,
forloadbalancing: true
});
if (args.context.networks) {
$.extend(data, { associatedNetworkId: args.context.networks[0].id });
}
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("listPublicIpAddresses&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
data: data,
dataType: "json",
async: true,
success: function(json) {
var items = json.listpublicipaddressesresponse.publicipaddress;
var processedItems = 0;
if (!items) {
args.response.success({
data: []
});
return;
}
args.response.success({
actionFilter: actionFilters.ipAddress,
data: items
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
// Detail view
detailView: {
name: 'IP address detail',
tabFilter: function(args) {
var item = args.context.ipAddresses[0];
// Get VPN data
$.ajax({
url: createURL('listRemoteAccessVpns'),
data: {
publicipid: item.id
},
dataType: 'json',
async: false,
success: function(vpnResponse) {
var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count;
if (isVPNEnabled) {
item.vpnenabled = true;
item.remoteaccessvpn = vpnResponse.listremoteaccessvpnsresponse.remoteaccessvpn[0];
};
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
var disabledTabs = [];
var ipAddress = args.context.ipAddresses[0];
if (!ipAddress.issourcenat ||
(ipAddress.issourcenat && !ipAddress.vpnenabled)) {
disabledTabs.push('vpn');
}
return disabledTabs;
},
actions: {
enableVPN: {
label: 'Enable VPN',
action: function(args) {
$.ajax({
url: createURL('createRemoteAccessVpn'),
data: {
publicipid: args.context.ipAddresses[0].id,
domainid: args.context.ipAddresses[0].domainid
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
getUpdatedItem: function(json) {
return {
vpn: json.queryasyncjobresultresponse.jobresult.remoteaccessvpn,
vpnenabled: true
};
},
getActionFilter: function() {
return actionFilters.ipAddress;
},
jobId: data.createremoteaccessvpnresponse.jobid
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Please confirm that you want VPN enabled for this IP address.';
},
notification: function(args) {
return 'Enabled VPN';
},
complete: function(args) {
return 'VPN is now enabled for IP ' + args.vpn.publicip + '.'
+ '
Your IPsec pre-shared key is:
' + args.vpn.presharedkey;
}
},
notification: {
poll: pollAsyncJobResult
}
},
disableVPN: {
label: 'Disable VPN',
action: function(args) {
$.ajax({
url: createURL('deleteRemoteAccessVpn'),
data: {
publicipid: args.context.ipAddresses[0].id,
domainid: args.context.ipAddresses[0].domainid
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
getUpdatedItem: function(data) {
return {
vpnenabled: false
};
},
getActionFilter: function() { return actionFilters.ipAddress; },
jobId: data.deleteremoteaccessvpnresponse.jobid
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Are you sure you want to disable VPN?';
},
notification: function(args) {
return 'Disabled VPN';
}
},
notification: {
poll: pollAsyncJobResult
}
},
enableStaticNAT: {
label: 'Enable static NAT',
action: {
noAdd: true,
custom: cloudStack.uiCustom.enableStaticNAT({
listView: $.extend(true, {}, cloudStack.sections.instances, {
listView: {
dataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
networkid: args.context.networks[0].id
},
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));
}
});
}
}
}),
action: function(args) {
$.ajax({
url: createURL('enableStaticNat'),
data: {
ipaddressid: args.context.ipAddresses[0].id,
virtualmachineid: args.context.instances[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success();
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
})
},
messages: {
notification: function(args) {
return 'Enabled Static NAT';
}
},
notification: {
poll: function(args) {
args.complete({
data: {
isstaticnat: true
}
});
}
}
},
disableStaticNAT: {
label: 'Disable static NAT',
action: function(args) {
$.ajax({
url: createURL('disableStaticNat'),
data: {
ipaddressid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.disablestaticnatresponse.jobid,
getUpdatedItem: function() {
return {
isstaticnat: false
};
},
getActionFilter: function() {
return function(args) {
return ['enableStaticNAT'];
};
}
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Are you sure you want to disable static NAT?';
},
notification: function(args) {
return 'Disable Static NAT';
}
},
notification: {
poll: pollAsyncJobResult
}
},
destroy: {
label: 'Release IP',
action: function(args) {
$.ajax({
url: createURL('disassociateIpAddress'),
data: {
id: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.disassociateipaddressresponse.jobid,
getActionFilter: function() {
return function(args) {
var allowedActions = ['enableStaticNAT'];
return allowedActions;
};
},
getUpdatedItem: function(args) {
return {
state: 'Released'
};
}
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
messages: {
confirm: function(args) {
return 'Are you sure you want to release this IP?';
},
notification: function(args) {
return 'Release IP';
}
},
notification: { poll: pollAsyncJobResult }
}
},
tabs: {
details: {
title: 'Details',
fields: [
{
ipaddress: { label: 'IP' }
},
{
id: { label: 'id' },
networkname: { label: 'Network' },
networktype: { label: 'Network Type' },
networkid: { label: 'Network ID' },
associatednetworkid: { label: 'Assoc. Network ID' },
state: { label: 'State' },
domain: { label: 'Domain' },
account: { label: 'Account' },
zonename: { label: 'Zone' },
vlanname: { label: 'VLAN' },
issourcenat: { label: 'Source NAT', isBoolean: true, converter: function(value) {
return value ? 'Yes' : 'No';
} },
isstaticnat: { label: 'Static NAT', isBoolean: true, converter: function(value) {
return value ? 'Yes' : 'No';
} }
}
],
//dataProvider: testData.dataProvider.detailView('network')
dataProvider: function(args) {
var items = args.context.ipAddresses;
// Get network data
$.ajax({
url: createURL("listPublicIpAddresses&id="+args.id),
dataType: "json",
async: true,
success: function(json) {
var item = items[0];
$.ajax({
url: createURL('listNetworks'),
data: {
networkid: this.associatednetworkid
},
dataType: 'json',
async: true,
success: function(data) {
// Get VPN data
$.ajax({
url: createURL('listRemoteAccessVpns'),
data: {
publicipid: item.id
},
dataType: 'json',
async: true,
success: function(vpnResponse) {
var isVPNEnabled = vpnResponse.listremoteaccessvpnsresponse.count;
if (isVPNEnabled) {
item.vpnenabled = true;
item.remoteaccessvpn = vpnResponse.listremoteaccessvpnsresponse.remoteaccessvpn[0];
};
// Check if data retrieval complete
item.network = data.listnetworksresponse.network[0];
item.networkname = item.network.name;
item.networktype = item.network.type;
args.response.success({
actionFilter: actionFilters.ipAddress,
data: item
});
}
});
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
ipRules: {
title: 'Configuration',
custom: cloudStack.ipRules({
preFilter: function(args) {
if (args.context.ipAddresses[0].isstaticnat) {
return args.items; // All items filtered means static NAT
}
if (g_firewallRuleUiEnabled != 'true') {
return ['firewall'];
}
return [];
},
// Firewall rules
firewall: {
noSelect: true,
fields: {
'cidrlist': { edit: true, label: 'Source CIDR' },
'protocol': {
label: 'Protocol',
select: function(args) {
args.$select.change(function() {
var $inputs = args.$form.find('input');
var $icmpFields = $inputs.filter(function() {
var name = $(this).attr('name');
return $.inArray(name, [
'icmptype',
'icmpcode'
]) > -1;
});
var $otherFields = $inputs.filter(function() {
var name = $(this).attr('name');
return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist';
});
if ($(this).val() == 'icmp') {
$icmpFields.attr('disabled', false);
$otherFields.attr('disabled', 'disabled');
} else {
$otherFields.attr('disabled', false);
$icmpFields.attr('disabled', 'disabled');
}
});
args.response.success({
data: [
{ name: 'tcp', description: 'TCP' },
{ name: 'udp', description: 'UDP' },
{ name: 'icmp', description: 'ICMP' }
]
});
}
},
'startport': { edit: true, label: 'Start Port' },
'endport': { edit: true, label: 'End Port' },
'icmptype': { edit: true, label: 'ICMP Type', isDisabled: true },
'icmpcode': { edit: true, label: 'ICMP Code', isDisabled: true },
'add-rule': {
label: 'Add Rule',
addButton: true
}
},
add: {
label: 'Add',
action: function(args) {
$.ajax({
url: createURL('createFirewallRule'),
data: $.extend(args.data, {
ipaddressid: args.context.ipAddresses[0].id
}),
dataType: 'json',
success: function(data) {
args.response.success({
_custom: {
jobId: data.createfirewallruleresponse.jobid
},
notification: {
label: 'Add firewall rule',
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
actions: {
destroy: {
label: 'Remove Rule',
action: function(args) {
$.ajax({
url: createURL('deleteFirewallRule'),
data: {
id: args.context.multiRule[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var jobID = data.deletefirewallruleresponse.jobid;
args.response.success({
_custom: {
jobId: jobID
},
notification: {
label: 'Remove firewall rule ' + args.context.multiRule[0].id,
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
},
dataProvider: function(args) {
$.ajax({
url: createURL('listFirewallRules'),
data: {
ipaddressid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: data.listfirewallrulesresponse.firewallrule
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
staticNATDataProvider: function(args) {
$.ajax({
url: createURL('listPublicIpAddresses'),
data: {
id: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var ipAddress = data.listpublicipaddressesresponse.publicipaddress[0];
args.response.success({
data: ipAddress
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
vmDataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
id: args.context.ipAddresses[0].virtualmachineid
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: data.listvirtualmachinesresponse.virtualmachine[0]
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
vmDetails: cloudStack.sections.instances.listView.detailView,
staticNAT: {
noSelect: true,
fields: {
'protocol': {
label: 'Protocol',
select: function(args) {
args.response.success({
data: [
{ name: 'tcp', description: 'TCP' },
{ name: 'udp', description: 'UDP' }
]
});
}
},
'startport': { edit: true, label: 'Start Port' },
'endport': { edit: true, label: 'End Port' },
'add-rule': {
label: 'Add Rule',
addButton: true
}
},
add: {
label: 'Add',
action: function(args) {
$.ajax({
url: createURL('createIpForwardingRule'),
data: $.extend(args.data, {
ipaddressid: args.context.ipAddresses[0].id
}),
dataType: 'json',
success: function(data) {
args.response.success({
_custom: {
jobId: data.createipforwardingruleresponse.jobid
},
notification: {
label: 'Added static NAT rule',
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
actions: {
destroy: {
label: 'Remove Rule',
action: function(args) {
$.ajax({
url: createURL('deleteIpForwardingRule'),
data: {
id: args.context.multiRule[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var jobID = data.deleteipforwardingruleresponse.jobid;
args.response.success({
_custom: {
jobId: jobID
},
notification: {
label: 'Removed static NAT rule',
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
},
dataProvider: function(args) {
setTimeout(function() {
$.ajax({
url: createURL('listIpForwardingRules'),
data: {
ipaddressid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
data: data.listipforwardingrulesresponse.ipforwardingrule
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}, 100);
}
},
// Load balancing rules
loadBalancing: {
listView: $.extend(true, {}, cloudStack.sections.instances, {
listView: {
dataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
networkid: args.context.ipAddresses[0].associatednetworkid
},
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: 'Name' },
'publicport': { edit: true, label: 'Public Port' },
'privateport': { edit: true, label: 'Private Port' },
'algorithm': {
label: 'Algorithm',
select: function(args) {
args.response.success({
data: [
{ name: 'roundrobin', description: 'Round-robin' },
{ name: 'leastconn', description: 'Least connections' },
{ name: 'source', description: 'Source' }
]
});
}
},
'sticky': {
label: 'Sticky Policy',
custom: {
buttonLabel: 'Configure',
action: function(args) {
var success = args.response.success;
var fields = {
methodname: {
label: 'Stickiness method',
select: function(args) {
var $select = args.$select;
var $form = $select.closest('form');
args.response.success({
data: [
{
id: 'none',
description: 'None'
},
{
id: 'LbCookie',
description: 'LB-based'
},
{
id: 'AppCookie',
description: 'Cookie-based'
},
{
id: 'SourceBased',
description: 'Source-based'
}
]
}, 500);
$select.change(function() {
var value = $select.val();
var showFields = [];
switch (value) {
case 'none':
showFields = [];
break;
case 'LbCookie':
showFields = ['name', 'mode', 'nocache', 'indirect', 'postonly', 'domain'];
break;
case 'AppCookie':
showFields = ['name', 'length', 'holdtime', 'request-learn', 'prefix', 'mode'];
break;
case 'SourceBased':
showFields = ['tablesize', 'expire'];
break;
}
$select.closest('.form-item').siblings('.form-item').each(function() {
var $field = $(this);
var id = $field.attr('rel');
if ($.inArray(id, showFields) > -1) {
$field.css('display', 'inline-block');
} else {
$field.hide();
}
});
$select.closest(':ui-dialog').dialog('option', 'position', 'center');
});
}
},
name: { label: 'Name', validation: { required: true }, isHidden: true },
mode: { label: 'Mode', isHidden: true },
length: { label: 'Length', validation: { required: true }, isHidden: true },
holdtime: { label: 'Hold Time', validation: { required: true }, isHidden: true },
tablesize: { label: 'Table size', isHidden: true },
expire: { label: 'Expire', isHidden: true },
requestlearn: { label: 'Request-Learn', isBoolean: true, isHidden: true },
prefix: { label: 'Prefix', isBoolean: true, isHidden: true },
nocache: { label: 'No cache', isBoolean: true, isHidden: true },
indirect: { label: 'Indirect', isBoolean: true, isHidden: true },
postonly: { label: 'Is post-only', isBoolean: true, isHidden: true },
domain: { label: 'Domain', isBoolean: true, isHidden: true }
};
if (args.data) {
var populatedFields = $.map(fields, function(field, id) {
return id;
});
$(populatedFields).each(function() {
var id = this;
var field = fields[id];
var dataItem = args.data[id];
if (field.isBoolean) {
field.isChecked = dataItem ? true : false;
} else {
field.defaultValue = dataItem;
}
});
}
cloudStack.dialog.createForm({
form: {
title: 'Configure Sticky Policy',
desc: 'Please complete the following fields',
fields: fields
},
after: function(args) {
var data = cloudStack.serializeForm(args.$form);
success({
data: $.extend(data, {
_buttonLabel: data.methodname.toUpperCase()
})
});
}
});
}
}
},
'add-vm': {
label: 'Add VMs',
addButton: true
}
},
add: {
label: 'Add VMs',
action: function(args) {
var openFirewall = g_firewallRuleUiEnabled == "true" ? false : true;
var data = {
algorithm: args.data.algorithm,
name: args.data.name,
privateport: args.data.privateport,
publicport: args.data.publicport
};
var stickyData = $.extend(true, {}, args.data.sticky);
$.ajax({
url: createURL('createLoadBalancerRule'),
data: $.extend(data, {
openfirewall: openFirewall,
publicipid: args.context.ipAddresses[0].id,
networkid: args.context.networks[0].id
}),
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) {
args.response.success({
_custom: {
jobId: jobID
},
notification: {
label: 'Add load balancer rule',
poll: function(args) {
var complete = args.complete;
var error = args.error;
pollAsyncJobResult({
_custom: args._custom,
complete: function(args) {
// Create stickiness policy
if (stickyData && stickyData.methodname != 'none') {
var stickyURLData = '';
var stickyParams;
switch (stickyData.methodname) {
case 'LbCookie':
stickyParams = ['name', 'mode', 'nocache', 'indirect', 'postonly', 'domain'];
break;
case 'AppCookie':
stickyParams = ['name', 'length', 'holdtime', 'request-learn', 'prefix', 'mode'];
break;
case 'SourceBased':
stickyParams = ['tablesize', 'expire'];
break;
}
$(stickyParams).each(function(index) {
var param = '¶m[' + index + ']';
var name = this;
var value = stickyData[name];
if (!value) return true;
if (value == 'on') value = true;
stickyURLData += param + '.name=' + name + param + '.value=' + value;
});
$.ajax({
url: createURL('createLBStickinessPolicy' + stickyURLData),
data: {
lbruleid: args.data.loadbalancer.id,
name: stickyData.name,
methodname: stickyData.methodname
},
success: function(json) {
var addStickyCheck = setInterval(function() {
pollAsyncJobResult({
_custom: {
jobId: json.createLBStickinessPolicy.jobid,
},
complete: function(args) {
clearInterval(addStickyCheck);
complete();
},
error: function(args) {
clearInterval(addStickyCheck);
}
});
}, 1000);
},
error: error
});
} else {
complete();
}
},
error: error
});
}
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
actions: {
destroy: {
label: 'Remove load balancer rule',
action: function(args) {
$.ajax({
url: createURL('deleteLoadBalancerRule'),
data: {
id: args.context.multiRule[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var jobID = data.deleteloadbalancerruleresponse.jobid;
args.response.success({
_custom: {
jobId: jobID
},
notification: {
label: 'Remove load balancer rule ' + args.context.multiRule[0].id,
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
},
dataProvider: function(args) {
$.ajax({
url: createURL('listLoadBalancerRules'),
data: {
publicipid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var loadBalancerData = data.listloadbalancerrulesresponse.loadbalancerrule;
var loadVMTotal = loadBalancerData ? loadBalancerData.length : 0;
var loadVMCurrent = 0;
$(loadBalancerData).each(function() {
var item = this;
// Get instances
$.ajax({
url: createURL('listLoadBalancerRuleInstances'),
dataType: 'json',
async: true,
data: {
id: item.id
},
success: function(data) {
loadVMCurrent++;
$.extend(item, {
_itemData: data
.listloadbalancerruleinstancesresponse.loadbalancerruleinstance
});
if (loadVMCurrent == loadVMTotal) {
args.response.success({
data: loadBalancerData
});
}
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
});
}
});
}
},
// Port forwarding rules
portForwarding: {
listView: $.extend(true, {}, cloudStack.sections.instances, {
listView: {
dataProvider: function(args) {
$.ajax({
url: createURL('listVirtualMachines'),
data: {
networkid: args.context.ipAddresses[0].associatednetworkid
},
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));
}
});
}
}
}),
fields: {
'private-ports': {
edit: true,
label: 'Private Ports',
range: ['privateport', 'privateendport']
},
'public-ports': {
edit: true,
label: 'Public Ports',
range: ['publicport', 'publicendport']
},
'protocol': {
label: 'Protocol',
select: function(args) {
args.response.success({
data: [
{ name: 'tcp', description: 'TCP' },
{ name: 'udp', description: 'UDP' }
]
});
}
},
'add-vm': {
label: 'Add VM',
addButton: true
}
},
add: {
label: 'Add VM',
action: function(args) {
var openFirewall = g_firewallRuleUiEnabled == "true" ? false : true;
$.ajax({
url: createURL('createPortForwardingRule'),
data: $.extend(args.data, {
openfirewall: openFirewall,
ipaddressid: args.context.ipAddresses[0].id,
virtualmachineid: args.itemData[0].id
}),
dataType: 'json',
async: true,
success: function(data) {
args.response.success({
_custom: {
jobId: data.createportforwardingruleresponse.jobid
},
notification: {
label: 'Add port forwarding rule',
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
},
actions: {
destroy: {
label: 'Remove port forwarding rule',
action: function(args) {
$.ajax({
url: createURL('deletePortForwardingRule'),
data: {
id: args.context.multiRule[0].id
},
dataType: 'json',
async: true,
success: function(data) {
var jobID = data.deleteportforwardingruleresponse.jobid;
args.response.success({
_custom: {
jobId: jobID
},
notification: {
label: 'Remove port forwarding rule ' + args.context.multiRule[0].id,
poll: pollAsyncJobResult
}
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
},
dataProvider: function(args) {
$.ajax({
url: createURL('listPortForwardingRules'),
data: {
ipaddressid: args.context.ipAddresses[0].id
},
dataType: 'json',
async: true,
success: function(data) {
// Get instance
var portForwardingData = data
.listportforwardingrulesresponse.portforwardingrule;
var loadTotal = portForwardingData ? portForwardingData.length : 0;
var loadCurrent = 0;
$(portForwardingData).each(function() {
var item = this;
$.ajax({
url: createURL('listVirtualMachines'),
dataType: 'json',
async: true,
data: {
id: item.virtualmachineid
},
success: function(data) {
loadCurrent++;
$.extend(item, {
_itemData: data.listvirtualmachinesresponse.virtualmachine,
_context: {
instances: data.listvirtualmachinesresponse.virtualmachine
}
});
if (loadCurrent == loadTotal) {
args.response.success({
data: portForwardingData
});
}
}
});
});
},
error: function(data) {
args.response.error(parseXMLHttpResponse(data));
}
});
}
}
})
},
vpn: {
title: 'VPN',
custom: function(args) {
var ipAddress = args.context.ipAddresses[0].ipaddress;
var psk = args.context.ipAddresses[0].remoteaccessvpn.presharedkey;
return $('