diff --git a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
index 6c2c9f660b..143d85d6c1 100644
--- a/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
+++ b/src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb
@@ -110,7 +110,7 @@ module OpenNebulaJSON
template = template_to_str(params['template'])
- ['NIC', 'SCHED_ACTION', 'SCHED_REQUIREMENTS', 'SCHED_DS_REQUIREMENTS'].each { |i|
+ ['NIC', 'NIC_ALIAS', 'SCHED_ACTION', 'SCHED_REQUIREMENTS', 'SCHED_DS_REQUIREMENTS'].each { |i|
if params['template'][i] && params['template'][i].empty?
template << "\n#{i} = []"
end
diff --git a/src/sunstone/public/app/opennebula/vm.js b/src/sunstone/public/app/opennebula/vm.js
index 6bc12bd510..683b5f49cc 100644
--- a/src/sunstone/public/app/opennebula/vm.js
+++ b/src/sunstone/public/app/opennebula/vm.js
@@ -298,6 +298,16 @@ define(function(require) {
"VROUTER_IP6_ULA"
];
+ var NIC_ALIAS_IP_ATTRS = [
+ "IP",
+ "IP6",
+ "IP6_GLOBAL",
+ "IP6_ULA",
+ "VROUTER_IP",
+ "VROUTER_IP6_GLOBAL",
+ "VROUTER_IP6_ULA"
+ ];
+
var EXTERNAL_NETWORK_ATTRIBUTES = [
'GUEST_IP',
'GUEST_IP_ADDRESSES',
@@ -654,6 +664,7 @@ define(function(require) {
return MIGRATE_ACTION_STR[stateId];
},
"ipsStr": ipsStr,
+ "aliasStr": aliasStr,
"retrieveExternalIPs": retrieveExternalIPs,
"retrieveExternalNetworkAttrs": retrieveExternalNetworkAttrs,
"isNICGraphsSupported": isNICGraphsSupported,
@@ -802,6 +813,38 @@ define(function(require) {
}
};
+ // Return the Alias or several Aliases of a VM
+ function aliasStr(element, divider) {
+ var divider = divider || "
"
+ var nic_alias = element.TEMPLATE.NIC_ALIAS;
+ var ips = [];
+
+ if (nic_alias == undefined){
+ nic_alias = [];
+ }
+
+ if (!$.isArray(nic_alias)) {
+ nic_alias = [nic_alias];
+ }
+
+ if(ips.length==0)
+ {
+ $.each(nic_alias, function(index, value) {
+ $.each(NIC_ALIAS_IP_ATTRS, function(j, attr){
+ if (value[attr]) {
+ ips.push(value[attr]);
+ }
+ });
+ });
+ }
+
+ if (ips.length > 0) {
+ return ips.join(divider);
+ } else {
+ return '--';
+ }
+ };
+
// returns true if the vnc button should be enabled
function isVNCSupported(element) {
var graphics = element.TEMPLATE.GRAPHICS;
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js
index 3cabfd7c1e..14870d368f 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create-common.js
@@ -160,6 +160,8 @@ define(function(require) {
var templateJSON = {}
$.each(this.wizardTabs, function(index, wizardTab) {
$.extend(true, templateJSON, wizardTab.retrieve($('#' + wizardTab.wizardTabId, context)));
+
+ var a = templateJSON;
});
// vCenter PUBLIC_CLOUD is not defined in the hybrid tab. Because it is
@@ -174,6 +176,16 @@ define(function(require) {
// part of an array, and it is filled in different tabs, the $.extend deep
// merge can't work. We define an auxiliary attribute for it.
+ if (templateJSON["NIC_ALIAS"]) {
+ var alias = templateJSON["NIC_ALIAS"];
+
+ if (alias) {
+ templateJSON["NIC_ALIAS"] = alias;
+ } else {
+ delete templateJSON["NIC_ALIAS"];
+ }
+ }
+
if (templateJSON["NIC_PCI"] != undefined) {
if (templateJSON['PCI'] == undefined) {
templateJSON['PCI'] = [];
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
index 31ad7502d7..d1b1f56a2e 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network.js
@@ -53,6 +53,7 @@ define(function(require) {
this.wizardTabId = WIZARD_TAB_ID + UniqueId.id();
this.icon = 'fa-globe';
this.title = Locale.tr("Network");
+ this.nics = [];
this.classes = "hypervisor";
if(opts.listener != undefined){
@@ -115,6 +116,7 @@ define(function(require) {
var templateJSON = {}
var nicsJSON = [];
var pcisJSON = [];
+ var aliasJSON = [];
var tmpJSON;
$.each(this.nicTabObjects, function(id, nicTab) {
@@ -124,6 +126,8 @@ define(function(require) {
delete tmpJSON["NIC_PCI"];
tmpJSON["TYPE"] = "NIC";
pcisJSON.push(tmpJSON);
+ } else if (tmpJSON["PARENT"]) {
+ aliasJSON.push(tmpJSON);
} else {
nicsJSON.push(tmpJSON);
}
@@ -131,6 +135,7 @@ define(function(require) {
})
if (nicsJSON.length > 0) { templateJSON['NIC'] = nicsJSON; };
+ if (aliasJSON.length > 0) { templateJSON['NIC_ALIAS'] = aliasJSON; };
if (pcisJSON.length > 0) { templateJSON['NIC_PCI'] = pcisJSON; };
var nicDefault = WizardFields.retrieveInput($('#DEFAULT_MODEL', context));
@@ -146,6 +151,7 @@ define(function(require) {
function _fill(context, templateJSON) {
var that = this;
var nics = [];
+ var alias = [];
if (templateJSON.NIC != undefined){
nics = templateJSON.NIC;
@@ -155,6 +161,18 @@ define(function(require) {
nics = [nics];
}
+ if (templateJSON.NIC_ALIAS != undefined){
+ alias = templateJSON.NIC_ALIAS;
+ }
+
+ if (!(alias instanceof Array)) {
+ alias = [alias];
+ }
+
+ $.each(alias, function() {
+ nics.push(this);
+ });
+
if (templateJSON.PCI != undefined){
var pcis = templateJSON.PCI;
@@ -177,12 +195,22 @@ define(function(require) {
var nicTab = that.nicTabObjects[that.numberOfNics];
var nicContext = $('#' + nicTab.nicTabId, context);
nicTab.fill(nicContext, nicJSON);
+
+ if (nicJSON.PARENT) {
+ nicTab.fill_alias(nicJSON.PARENT);
+ }
});
+ that.renameTabLinks(context);
+
if (templateJSON.NIC) {
delete templateJSON.NIC;
}
+ if (templateJSON.NIC_ALIAS) {
+ delete templateJSON.NIC_ALIAS;
+ }
+
if (templateJSON.PCI != undefined) {
var pcis = templateJSON.PCI;
@@ -215,8 +243,13 @@ define(function(require) {
function _addNicTab(context) {
var that = this;
+
+ if (!that.nics.find(nic => nic.NAME === ("NIC" + that.numberOfNics))) {
+ that.nics.push({"NAME": "NIC" + that.numberOfNics, "ALIAS": false});
+ }
+
that.numberOfNics++;
- var nicTab = new NicTab(that.numberOfNics);
+ var nicTab = new NicTab(that.numberOfNics, that.nics);
var content = $('
' +
nicTab.html() +
@@ -242,11 +275,14 @@ define(function(require) {
var li = $(this).closest('li');
var ul = $(this).closest('ul');
var content = $(target);
+ var nicId = content.attr("nicId");
+ var index = that.nics.findIndex(nic => nic.NAME === ("NIC" + (nicId - 1)));
+
+ that.nics.splice(index, 1);
li.remove();
content.remove();
- var nicId = content.attr("nicId");
delete that.nicTabObjects[nicId];
if (li.hasClass('is-active')) {
@@ -254,12 +290,19 @@ define(function(require) {
}
that.renameTabLinks(context);
+ that.numberOfNics --;
});
}
function _renameTabLinks(context) {
$("#" + LINKS_CONTAINER_ID + " li", context).each(function(index) {
- $("a", this).html(Locale.tr("NIC") + ' ' + index + "
");
+ $("a", this).html(Locale.tr("NIC") + ' ' + index + "
");
+
+ if (!that.nics.find(nic => nic.ALIAS === ("NIC" + index))) {
+ $("#remove_nic_" + index).show();
+ } else {
+ $("#remove_nic_" + index).hide();
+ }
})
if(this.listener != undefined){
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab.js
index 3d4b2ee158..a31915a302 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab.js
@@ -43,9 +43,11 @@ define(function(require) {
CONSTRUCTOR
*/
- function NicTab(nicTabId) {
+ function NicTab(nicTabId, nics) {
that = this;
+ this.nicId = nicTabId - 1;
this.nicTabId = 'nicTab' + nicTabId + UniqueId.id();
+ this.nics = nics;
var options = {
'select': true,
@@ -78,6 +80,7 @@ define(function(require) {
NicTab.prototype.retrieve = _retrieve;
NicTab.prototype.fill = _fill;
NicTab.prototype.generateRequirements = _generateRequirements;
+ NicTab.prototype.fill_alias = _fill_alias;
return NicTab;
@@ -107,6 +110,7 @@ define(function(require) {
*/
function _setup(context, options) {
var that = this;
+ that.context = context;
if (options != undefined && options.hide_pci == true){
$("input.pci-type-nic", context).attr('disabled', 'disabled');
@@ -194,14 +198,128 @@ define(function(require) {
if(network_mode_on){
$(".no_auto", context).hide();
$(".auto", context).show();
+ $("#" + that.nicTabId + "interface_type", context).hide();
} else {
$(".auto", context).hide();
$(".no_auto", context).show();
+ $("#" + that.nicTabId + "interface_type", context).show();
}
});
$(".auto", context).hide();
+ $("input#" + this.nicTabId + "_interface_type", context).on("change", function(){
+ var alias_on = $(this).prop("checked");
+ var alias;
+ var found = false;
+
+ $.each(that.nics, function(index, value) {
+ if (value.ALIAS === ("NIC" + that.nicId)) {
+ alias = value.ALIAS;
+ }
+ });
+
+ $("#" + that.nicTabId + "_alias_parent", context).empty();
+ $("#" + that.nicTabId + "_alias_parent", context).append(new Option("Choose NIC", "INVALID"));
+ $("#" + that.nicTabId + "_alias_parent", context).val("INVALID");
+ $("#" + that.nicTabId + "_no_alias", context).html("Nic has alias");
+
+ if (that.nics.length == 1 && alias_on) {
+ $("#" + that.nicTabId + "_alias_parent", context).hide();
+ $(".network_selection", context).hide();
+ $("#" + that.nicTabId + "_no_alias", context).html("No NIC available");
+ $("#" + that.nicTabId + "_no_alias").show();
+ } else {
+ if(alias_on && !alias) {
+ $("#" + that.nicTabId + "_alias_parent", context).show();
+ $(".network_selection", context).hide();
+ $("#" + that.nicTabId + "_no_alias").hide();
+ } else if (alias_on && alias) {
+ $("#" + that.nicTabId + "_alias_parent", context).hide();
+ $(".network_selection", context).hide();
+ $("#" + that.nicTabId + "_no_alias").show();
+ } else {
+ $.each(that.nics, function(index, value) {
+ if (value.NAME == ("NIC" + that.nicId)) {
+ alias = value.ALIAS;
+ value.ALIAS = false;
+ }
+ });
+
+ if (alias) {
+ $.each(that.nics, function(index, value) {
+ if (value.ALIAS == alias) {
+ found = true;
+ }
+ });
+
+ if (found) {
+ $("#remove_nic_" + (alias[alias.length - 1])).hide();
+ } else {
+ $("#remove_nic_" + (alias[alias.length - 1])).show();
+ }
+ }
+
+ $("#" + that.nicTabId + "_alias_parent", context).hide();
+ $(".network_selection", context).show();
+ $("#" + that.nicTabId + "_no_alias").hide();
+ }
+ }
+ });
+
+ $("#" + this.nicTabId + "_no_alias").hide();
+
+ $("#" + this.nicTabId + "_alias_parent", context).append(new Option("Choose NIC", "INVALID"));
+ $("#" + this.nicTabId + "_alias_parent", context).val("INVALID");
+
+ $("#" + this.nicTabId + "_alias_parent", context).on("click", function(){
+ var selected_nic = $("#" + that.nicTabId + "_alias_parent", context).val();
+ var add = false;
+ var found = false;
+
+ $("#" + that.nicTabId + "_alias_parent").empty();
+
+ that.nics.forEach(function(element) {
+ if(element.NAME != ("NIC" + that.nicId) && !element.ALIAS &&
+ (that.nicId > element.NAME[element.NAME.length - 1])) {
+ $("#" + that.nicTabId + "_alias_parent").append(new Option(element.NAME, element.NAME));
+ add = true;
+ }
+ });
+
+ if (!add) {
+ $("#" + that.nicTabId + "_alias_parent", context).append(new Option("No NIC available", "INVALID"));
+ $("#" + that.nicTabId + "_alias_parent", context).val("INVALID");
+ } else if (add && selected_nic == "INVALID") {
+ $("#" + that.nicTabId + "_alias_parent", context).val($("#" + that.nicTabId + "_alias_parent option:first").val());
+ selected_nic = $("#" + that.nicTabId + "_alias_parent", context).val();
+ }
+
+ $.each(that.nics, function(index, value) {
+ if (value.NAME == ("NIC" + that.nicId) && selected_nic != "INVALID") {
+ value.ALIAS = selected_nic;
+ }
+ });
+
+ if (selected_nic && selected_nic != "INVALID") {
+ $.each(that.nics, function(index, value) {
+ if (value.ALIAS == selected_nic) {
+ found = true;
+ }
+ });
+
+ if (found) {
+ $("#remove_nic_" + (selected_nic[selected_nic.length - 1])).hide();
+ } else {
+ $("#remove_nic_" + (selected_nic[selected_nic.length - 1])).show();
+ }
+
+ $("#" + that.nicTabId + "_alias_parent", context).val(selected_nic);
+ }
+ });
+
+ $("#" + this.nicTabId + "_alias_parent", context).hide();
+
context.on("change", "input[name='" + that.nicTabId + "_req_select']", function() {
if ($("input[name='" + that.nicTabId + "_req_select']:checked").val() == "vnet_select") {
$("#"+ that.nicTabId +"_vnetTable",context).show();
@@ -255,6 +373,13 @@ define(function(require) {
}
}
+ if(!$("input#" + this.nicTabId + "_interface_type", context).prop("checked") ||
+ $("#" + this.nicTabId + "_alias_parent", context).val() == "INVALID") {
+ delete nicJSON["PARENT"];
+ } else {
+ nicJSON["PARENT"] = $("#" + this.nicTabId + "_alias_parent", context).val();
+ }
+
return nicJSON;
}
@@ -376,4 +501,20 @@ define(function(require) {
$("input#"+this.nicTabId+"_SCHED_REQUIREMENTS", context).val(req_string.join(" | "));
};
+
+ function _fill_alias(nicname) {
+ $.each(this.nics, function(index, value) {
+ if (value.NAME == ("NIC" + that.nicId)) {
+ value.ALIAS = nicname;
+ }
+ });
+
+ $("#" + this.nicTabId + "interface_type", this.context).show();
+ $("input#" + this.nicTabId + "_interface_type", this.context).click();
+ $("#" + this.nicTabId + "_alias_parent", this.context).show();
+ $("#" + this.nicTabId + "_alias_parent", this.context).empty();
+ $("#" + this.nicTabId + "_alias_parent").append(new Option(nicname, nicname));
+ $("#" + this.nicTabId + "_alias_parent", this.context).val(nicname);
+ $(".network_selection", this.context).hide();
+ }
});
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab/html.hbs b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab/html.hbs
index fc9bce422c..dcf41d6c5b 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab/html.hbs
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/create/wizard-tabs/network/nic-tab/html.hbs
@@ -17,16 +17,37 @@
diff --git a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js
index ec20d0cb69..4009e4f787 100644
--- a/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js
+++ b/src/sunstone/public/app/tabs/templates-tab/form-panels/instantiate.js
@@ -259,16 +259,20 @@ define(function(require) {
var nics = [];
var pcis = [];
+ var alias = [];
$.each(networks, function(){
if (this.TYPE == "NIC"){
pcis.push(this);
+ } else if (this.PARENT) {
+ alias.push(this);
} else {
nics.push(this);
}
});
tmp_json.NIC = nics;
+ tmp_json.NIC_ALIAS = alias;
// Replace PCIs of type nic only
var original_tmpl = that.template_objects[index].VMTEMPLATE;
@@ -297,6 +301,10 @@ define(function(require) {
tmp_json.PCI = pcis;
}
+ if (alias.length > 0) {
+ tmp_json.NIC_ALIAS = alias;
+ }
+
if (Config.isFeatureEnabled("vcenter_vm_folder")){
if(!$.isEmptyObject(original_tmpl.TEMPLATE.HYPERVISOR) &&
original_tmpl.TEMPLATE.HYPERVISOR === "vcenter"){
diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
index 771f0baa95..a70db65bae 100644
--- a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
+++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic.js
@@ -53,6 +53,7 @@ define(function(require) {
Dialog.prototype.onShow = _onShow;
Dialog.prototype.setup = _setup;
Dialog.prototype.setElement = _setElement;
+ Dialog.prototype.setNicsNames = _setNicsNames;
return Dialog;
@@ -68,15 +69,37 @@ define(function(require) {
}
function _setup(context) {
+ this.context = context;
+
var that = this;
+
that.nicTab.setup(context, {hide_pci: true, hide_auto: true});
Tips.setup(context);
+ $("#parent", context).hide();
+
+ $("#attach_alias", context).change(function() {
+ if(this.checked) {
+ $("#parent", context).show();
+ } else {
+ $("#parent", context).hide();
+ }
+ });
+
$('#' + DIALOG_ID + 'Form', context).submit(function() {
var templateJSON = that.nicTab.retrieve(context);
- var obj = {
- "NIC": templateJSON
+
+ if($("#attach_alias", context).prop("checked")) {
+ templateJSON.PARENT = $("#parent").val();
+
+ var obj = {
+ "NIC_ALIAS": templateJSON
+ }
+ } else {
+ var obj = {
+ "NIC": templateJSON
+ }
}
Sunstone.runAction('VM.attachnic', that.element.ID, obj);
@@ -100,4 +123,15 @@ define(function(require) {
function _setElement(element) {
this.element = element
}
+
+ function _setNicsNames(nicsNames) {
+ $("#parent", this.context).empty();
+ var that = this;
+
+ nicsNames.forEach(function(element) {
+ var alias_str = element.ID + " " + element.NET + " " + element.IP;
+
+ $("#parent", that.context).append(new Option(alias_str, element.NAME));
+ });
+ }
});
diff --git a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic/html.hbs b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic/html.hbs
index 3f862269eb..e178c31a9f 100644
--- a/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic/html.hbs
+++ b/src/sunstone/public/app/tabs/vms-tab/dialogs/attach-nic/html.hbs
@@ -23,6 +23,8 @@