blob: 5444874662dbeeac61cab249ce3752ee12c07b90 [file] [log] [blame]
// 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 elems = {
aclDialog: function(args) {
var isDialog = args.isDialog;
var actionArgs = args.actionArgs;
var context = args.context;
var $acl = $('<div>').addClass('acl').multiEdit(
$.extend(true, {}, actionArgs.multiEdit, {
context: context
})
);
// Show ACL dialog
if (isDialog) {
$acl.dialog({
title: _l('label.configure.network.ACLs'),
dialogClass: 'configure-acl',
width: 900,
height: 600,
buttons: {
'Done': function() {
$(':ui-dialog').remove();
$('.overlay').remove();
}
}
});
}
return $acl;
},
vpcConfigureTooltip: function(args) {
var context = args.context;
var $browser = args.$browser;
var $chart = args.$chart;
var ipAddresses = args.ipAddresses;
var acl = args.acl;
var gateways = args.gateways;
var siteToSiteVPN = args.siteToSiteVPN;
var links = {
'ip-addresses': _l('label.menu.ipaddresses'),
'gateways': _l('label.private.Gateway'),
'site-to-site-vpn': _l('label.site.to.site.VPN'),
'network-acls': _l('label.network.ACLs')
};
var $links = $('<ul>').addClass('links');
var $tooltip = $('<div>').addClass('vpc-configure-tooltip').append(
$('<div>').addClass('arrow')
);
var tierDetailView = args.tierDetailView;
// Make links
$.map(links, function(label, id) {
var $link = $('<li>').addClass('link').addClass(id);
var $label = $('<span>').html(label);
$link.append($label);
$link.appendTo($links);
// Link event
$link.click(function() {
switch (id) {
case 'network-acls':
$browser.cloudBrowser('addPanel', {
title: _l('label.network.ACLs'),
maximizeIfSelected: true,
complete: function($panel) {
$panel.listView(
$.extend(true, {}, acl.listView, {
listView: {
actions: {
add: {
label: 'label.add.network.ACL',
action: {
custom: function() {
elems.aclDialog({
isDialog: true,
actionArgs: acl,
context: context
});
}
}
}
},
detailView: function() {
var detailView = $.extend(true, {}, tierDetailView);
detailView.tabs = {
acl: tierDetailView.tabs.acl
};
return detailView;
}
}
}), {
context: acl.context
}
);
}
});
break;
case 'ip-addresses':
$browser.cloudBrowser('addPanel', {
title: _l('label.menu.ipaddresses'),
maximizeIfSelected: true,
complete: function($panel) {
//ipAddresses.listView is a function
$panel.listView(ipAddresses.listView(), {
context: ipAddresses.context
});
}
});
break;
case 'gateways':
//siteToSiteVPN is an object
var addAction = gateways.add;
var isGatewayPresent = addAction.preCheck({
context: gateways.context
});
var showGatewayListView = function() {
$browser.cloudBrowser('addPanel', {
title: _l('label.private.Gateway'),
maximizeIfSelected: true,
complete: function($panel) {
$panel.listView(gateways.listView(), {
context: gateways.context
});
}
});
};
if (isGatewayPresent) {
showGatewayListView();
} else {
cloudStack.dialog.createForm({
form: addAction.createForm,
context: args.gateways.context,
after: function(args) {
var data = args.data;
var error = function(message) {
cloudStack.dialog.notice({
message: message
});
};
addAction.action({
data: data,
$form: args.$form,
context: gateways.context,
response: {
success: function(args) {
var _custom = args._custom;
var notification = {
poll: addAction.notification.poll,
_custom: _custom,
desc: addAction.messages.notification()
};
var success = function(args) {
if (!$chart.is(':visible')) return;
cloudStack.dialog.confirm({
message: 'Gateway for VPC has been created successfully. Would you like to see its details?',
action: showGatewayListView
});
};
cloudStack.dialog.notice({
message: 'Your gateway is being created; please see notifications window.'
});
cloudStack.ui.notifications.add(
notification,
success, {},
error, {}
);
},
error: error
}
});
}
});
}
break;
case 'site-to-site-vpn':
//siteToSiteVPN is an object
var addAction = siteToSiteVPN.add;
var isVPNPresent = addAction.preCheck({
context: siteToSiteVPN.context
});
var showVPNListView = function() {
$browser.cloudBrowser('addPanel', {
title: _l('label.site.to.site.VPN'),
maximizeIfSelected: true,
complete: function($panel) {
$panel.listView(siteToSiteVPN, {
context: siteToSiteVPN.context
});
}
});
};
if (isVPNPresent) {
showVPNListView();
} else {
cloudStack.dialog.confirm({
message: 'Please confirm that you want to add a Site-to-Site VPN gateway.',
action: function() {
var error = function(message) {
cloudStack.dialog.notice({
message: message
});
};
addAction.action({
context: siteToSiteVPN.context,
response: {
success: function(args) {
var _custom = args._custom;
var notification = {
poll: addAction.notification.poll,
_custom: _custom,
desc: addAction.messages.notification()
};
var success = function(args) {
if (!$chart.is(':visible')) return;
cloudStack.dialog.confirm({
message: 'Gateway for VPC has been created successfully. Would you like to see its details?',
action: showVPNListView
});
};
cloudStack.dialog.notice({
message: 'Your VPN is being created; please see notifications window.'
});
cloudStack.ui.notifications.add(
notification,
success, {},
error, {}
);
},
error: error
}
});
}
});
}
break;
}
});
});
$tooltip.append($links);
// Tooltip hover event
$tooltip.hover(
function() {
$tooltip.addClass('active');
},
function() {
$tooltip.removeClass('active');
setTimeout(function() {
if (!$tooltip.hasClass('active')) {
$tooltip.remove();
}
}, 500);
}
);
return $tooltip;
},
vpcConfigureArea: function(args) {
var context = args.context;
var $browser = args.$browser;
var $chart = args.$chart;
var ipAddresses = args.ipAddresses;
var acl = args.acl;
var gateways = args.gateways;
var siteToSiteVPN = args.siteToSiteVPN;
var $config = $('<div>').addClass('config-area');
var $configIcon = $('<span>').addClass('icon').html('&nbsp');
var tierDetailView = args.tierDetailView;
$config.append($configIcon);
// Tooltip event
$configIcon.mouseover(function() {
var $tooltip = elems.vpcConfigureTooltip({
context: context,
$browser: $browser,
$chart: $chart,
ipAddresses: ipAddresses,
gateways: gateways,
acl: acl,
siteToSiteVPN: siteToSiteVPN,
tierDetailView: tierDetailView
});
// Make sure tooltip is center aligned with icon
$tooltip.css({
left: $configIcon.position().left
});
$tooltip.appendTo($config).hide();
$tooltip.stop().fadeIn('fast');
});
return $config;
},
router: function(args) {
var $browser = args.$browser;
var detailView = args.detailView;
var $router = $('<li>').addClass('tier virtual-router');
var $title = $('<span>').addClass('title').html(_l('label.virtual.router'));
$router.append($title);
// Append horizontal chart line
$router.append($('<div>').addClass('connect-line'));
$router.click(function() {
if ($router.hasClass('disabled')) return false;
$browser.cloudBrowser('addPanel', {
title: _l('label.VPC.router.details'),
complete: function($panel) {
$panel.detailView(detailView);
}
});
});
return $router;
},
tier: function(args) {
var ipAddresses = args.ipAddresses;
var acl = args.acl;
var name = args.name;
var cidr = args.cidr;
var context = args.context;
var vmListView = args.vmListView;
var actionPreFilter = args.actionPreFilter;
var actions = $.map(
args.actions ? args.actions : {}, function(value, key) {
return {
id: key,
action: value
};
}
);
var detailView = args.detailView;
var $browser = args.$browser;
var isPlaceholder = args.isPlaceholder;
var virtualMachines = args.virtualMachines;
var $tier = $('<li>').addClass('tier');
var $title = $('<span>').addClass('title');
var $cidr = $('<span>').addClass('cidr');
var $vmCount = $('<span>').addClass('vm-count');
var $actions = $('<div>').addClass('actions');
// Ignore special actions
// -- Add tier action is handled separately
actions = $.grep(actions, function(action) {
return action.id != 'add';
});
// Add loading indicator
$vmCount.append(
$('<div>').addClass('loading-overlay')
.attr('title', 'VMs are launching in this tier.')
);
// VM count shows instance list
$vmCount.click(function() {
var $dialog = $('<div>');
var $listView = $('<div>').listView($.extend(true, {}, vmListView, {
context: context
}));
$dialog.append($listView);
$dialog.dialog({
title: _l('label.VMs.in.tier') + ': ' + name,
dialogClass: 'multi-edit-add-list panel configure-acl',
width: 825,
height: 600,
buttons: {
'Done': function() {
$(':ui-dialog').remove();
$('.overlay').remove();
}
}
}).closest('.ui-dialog').overlay();
});
// Title shows tier details
$title.click(function() {
if ($browser && $browser.length) { // Fix null exception, if add tier returns error
$browser.cloudBrowser('addPanel', {
title: name,
maximizeIfSelected: true,
complete: function($panel) {
$panel.detailView($.extend(true, {}, detailView, {
$browser: $browser,
context: context
}));
}
});
}
});
if (isPlaceholder) {
$tier.addClass('placeholder');
$title.html(_l('label.add.new.tier'));
} else {
$title.html(
cloudStack.concat(name, 8)
);
$title.attr('title', name);
$cidr.html(cidr);
$vmCount.append(
$('<span>').addClass('total').html(virtualMachines != null ? virtualMachines.length : 0),
_l('label.vms')
);
$tier.append($actions);
// Build action buttons
$(actions).map(function(index, action) {
var $action = $('<div>').addClass('action');
var shortLabel = action.action.shortLabel;
var label = action.action.label;
$action.addClass(action.id);
if (action.id != 'remove') {
$action.append($('<span>').addClass('label').html(_l(shortLabel)));
} else {
$action.append($('<span>').addClass('icon').html('&nbsp;'));
}
$actions.append($action);
$action.attr('title', label);
$action.data('vpc-tier-action-id', action.id);
// Action event
$action.click(function() {
if ($action.hasClass('disabled')) {
return false;
}
tierAction({
action: action,
actionPreFilter: actionPreFilter,
context: context,
$tier: $tier,
$actions: $actions
});
return true;
});
});
}
$tier.prepend($title);
if (!isPlaceholder) {
$tier.append($title, $cidr, $vmCount);
}
// Append horizontal chart line
$tier.append($('<div>').addClass('connect-line'));
// Handle action filter
filterActions({
$actions: $actions,
actionPreFilter: actionPreFilter,
context: context
});
return $tier;
},
chart: function(args) {
var $browser = args.$browser;
var acl = args.acl;
var ipAddresses = args.ipAddresses;
var gateways = args.gateways;
var siteToSiteVPN = args.siteToSiteVPN;
var tiers = args.tiers;
var vmListView = args.vmListView;
var actions = args.actions;
var actionPreFilter = args.actionPreFilter;
var vpcName = args.vpcName;
var context = args.context;
var tierDetailView = args.tierDetailView;
var $tiers = $('<ul>').addClass('tiers');
var $router;
$router = elems.router({
$browser: $browser,
detailView: $.extend(true, {}, args.routerDetailView(), {
context: context
})
});
if (!isAdmin()) $router.addClass('disabled');
var $chart = $('<div>').addClass('vpc-chart');
var $title = $('<div>').addClass('vpc-title')
.append(
$('<span>').html(vpcName)
)
.append(
elems.vpcConfigureArea({
context: context,
$browser: $browser,
$chart: $chart,
ipAddresses: $.extend(ipAddresses, {
context: context
}),
gateways: $.extend(gateways, {
context: context
}),
siteToSiteVPN: $.extend(siteToSiteVPN, {
context: context
}),
acl: $.extend(acl, {
context: context
}),
tierDetailView: tierDetailView
})
);
var showAddTierDialog = function() {
if ($(this).find('.loading-overlay').length) {
return false;
}
addTierDialog({
ipAddresses: ipAddresses,
$browser: $browser,
tierDetailView: tierDetailView,
$tiers: $tiers,
acl: acl,
context: context,
actions: actions,
vmListView: vmListView,
actionPreFilter: actionPreFilter
});
return true;
};
if (tiers != null && tiers.length > 0) {
$(tiers).map(function(index, tier) {
var $tier = elems.tier({
ipAddresses: ipAddresses,
acl: acl,
$browser: $browser,
detailView: tierDetailView,
name: tier.name,
cidr: tier.cidr,
virtualMachines: tier.virtualMachines,
vmListView: vmListView,
actions: actions,
actionPreFilter: actionPreFilter,
context: $.extend(true, {}, context, {
networks: [tier]
})
});
$tier.appendTo($tiers);
});
}
elems.tier({
isPlaceholder: true
}).appendTo($tiers)
.click(showAddTierDialog);
$tiers.prepend($router);
$chart.append($title, $tiers);
if (!tiers || !tiers.length) {
showAddTierDialog();
}
return $chart;
}
};
var filterActions = function(args) {
var $actions = args.$actions;
var actionPreFilter = args.actionPreFilter;
var context = args.context;
var disabledActions, allowedActions;
disabledActions = actionPreFilter ? actionPreFilter({
context: context
}) : [];
// Visual appearance for disabled actions
$actions.find('.action').map(function(index, action) {
var $action = $(action);
var actionID = $action.data('vpc-tier-action-id');
if ($.inArray(actionID, disabledActions) > -1) {
$action.addClass('disabled');
} else {
$action.removeClass('disabled');
}
});
};
// Handles tier action, including UI effects
var tierAction = function(args) {
var $tier = args.$tier;
var $loading = $('<div>').addClass('loading-overlay');
var $actions = args.$actions;
var actionArgs = args.action.action;
var action = actionArgs.action;
var actionID = args.action.id;
var notification = actionArgs.notification;
var label = actionArgs.label;
var context = args.context;
var actionPreFilter = args.actionPreFilter;
var success = function(args) {
var remove = args ? args.remove : false;
var _custom = args ? args._custom : {};
var updateVMLoadingState = function() {
var pendingVMs = $tier.data('vpc-tier-pending-vms');
pendingVMs = pendingVMs ? pendingVMs - 1 : 0;
if (!pendingVMs) {
$tier.data('vpc-tier-pending-vms', 0);
$tier.removeClass('loading');
} else {
$tier.data('vpc-tier-pending-vms', pendingVMs);
}
};
cloudStack.ui.notifications.add(
// Notification
{
desc: label,
poll: notification.poll,
_custom: _custom
},
// Success
function(args) {
if (actionID == 'addVM') {
// Increment VM total
var $total = $tier.find('.vm-count .total');
var prevTotal = parseInt($total.html());
var newTotal = prevTotal + 1;
var newVM = args.data;
var newContext = $.extend(true, {}, context, {
vms: [newVM]
});
$total.html(newTotal);
filterActions({
$actions: $actions,
actionPreFilter: actionPreFilter,
context: newContext
});
updateVMLoadingState();
} else if (actionID == 'remove') { //remove tier
$loading.remove();
$tier.remove();
} else {
$loading.remove();
}
},
{},
// Error
function(args) {
if (actionID == 'addVM') {
updateVMLoadingState();
} else {
$loading.remove();
}
}
);
};
switch (actionID) {
case 'addVM':
action({
context: context,
complete: function(args) {
var pendingVMs = $tier.data('vpc-tier-pending-vms');
pendingVMs = pendingVMs ? pendingVMs + 1 : 1;
$tier.addClass('loading');
$tier.data('vpc-tier-pending-vms', pendingVMs);
success(args);
}
});
break;
case 'remove':
$loading.appendTo($tier);
action({
context: context,
response: {
success: function(args) {
success($.extend(args, {
remove: true
}));
}
}
});
break;
case 'acl':
elems.aclDialog({
isDialog: true,
actionArgs: actionArgs,
context: context
}).closest('.ui-dialog').overlay();
break;
default:
$loading.appendTo($tier);
action({
context: context,
complete: success,
response: {
success: success,
error: function(args) {
$loading.remove();
}
}
});
}
};
// Appends a new tier to chart
var addNewTier = function(args) {
var ipAddresses = args.ipAddresses;
var acl = args.acl;
var actions = args.actions;
var vmListView = args.vmListView;
var actionPreFilter = args.actionPreFilter;
var context = args.context;
var $browser = args.$browser;
var tierDetailView = args.tierDetailView;
var tier = $.extend(args.tier, {
ipAddresses: ipAddresses,
$browser: $browser,
detailView: tierDetailView,
context: context,
vmListView: vmListView,
actions: actions,
actionPreFilter: actionPreFilter,
acl: acl,
virtualMachines: []
});
var $tiers = args.$tiers;
$tiers.find('li.placeholder')
.before(
elems.tier(tier)
.hide()
.fadeIn('slow')
);
};
// Renders the add tier form, in a dialog
var addTierDialog = function(args) {
var ipAddresses = args.ipAddresses;
var actions = args.actions;
var context = args.context;
var vmListView = args.vmListView;
var actionPreFilter = args.actionPreFilter;
var $tiers = args.$tiers;
var $browser = args.$browser;
var tierDetailView = args.tierDetailView;
var acl = args.acl;
cloudStack.dialog.createForm({
context: context,
form: actions.add.createForm,
after: function(args) {
var $loading = $('<div>').addClass('loading-overlay').prependTo($tiers.find('li.placeholder'));
actions.add.action({
context: context,
data: args.data,
response: {
success: function(args) {
var tier = args.data;
cloudStack.ui.notifications.add(
// Notification
{
desc: actions.add.label
},
// Success
function(args) {
$loading.remove();
addNewTier({
ipAddresses: ipAddresses,
$browser: $browser,
tierDetailView: tierDetailView,
context: $.extend(true, {}, context, {
networks: [tier]
}),
tier: tier,
acl: acl,
$tiers: $tiers,
actions: actions,
actionPreFilter: actionPreFilter,
vmListView: vmListView
});
},
{},
// Error
function(args) {
$loading.remove();
}
);
},
error: function(errorMsg) {
cloudStack.dialog.notice({
message: _s(errorMsg)
});
$loading.remove();
}
}
});
}
});
};
cloudStack.uiCustom.vpc = function(args) {
var vmListView = args.vmListView;
var tierArgs = args.tiers;
var ipAddresses = args.ipAddresses;
var gateways = args.gateways;
var acl = args.acl;
var siteToSiteVPN = args.siteToSiteVPN;
var routerDetailView = args.routerDetailView;
return function(args) {
var context = args.context;
var $browser = $('#browser .container');
var $toolbar = $('<div>').addClass('toolbar');
var vpc = args.context.vpc[0];
$browser.cloudBrowser('addPanel', {
maximizeIfSelected: true,
title: _l('label.configure.vpc') + ': ' + vpc.name,
complete: function($panel) {
var $loading = $('<div>').addClass('loading-overlay').appendTo($panel);
$panel.append($toolbar);
// Load data
tierArgs.dataProvider({
context: context,
response: {
success: function(args) {
// Setup detail view tabs
var tierDetailView = $.extend(true, {}, tierArgs.detailView, {
tabs: {
acl: {
custom: function(args) {
var $acl = elems.aclDialog({
isDialog: false,
actionArgs: acl,
context: args.context
});
return $acl;
}
},
ipAddresses: {
custom: function(args) {
return $('<div>').listView(ipAddresses.listView(), {
context: args.context
});
}
}
}
});
var tiers = args.tiers;
var $chart = elems.chart({
$browser: $browser,
ipAddresses: ipAddresses,
gateways: gateways,
acl: acl,
tierDetailView: tierDetailView,
routerDetailView: routerDetailView,
siteToSiteVPN: siteToSiteVPN,
vmListView: vmListView,
context: context,
actions: tierArgs.actions,
actionPreFilter: tierArgs.actionPreFilter,
vpcName: vpc.name,
tiers: tiers
}).appendTo($panel);
$loading.remove();
$chart.fadeIn(function() {});
}
}
});
}
});
};
};
}(jQuery, cloudStack));