From 3a9034a0105ec664438c84a32a1495d5363b1899 Mon Sep 17 00:00:00 2001 From: Alejandro Huertas Herrero Date: Thu, 20 Dec 2018 09:38:34 +0100 Subject: [PATCH] F #911: IP(v6) alias(es) support (#2693) * Made changes in info tab. * Made changes in network tab, to attach/detach alias. * Made changes in VM template update/instantiate. --- .../models/OpenNebulaJSON/TemplateJSON.rb | 2 +- src/sunstone/public/app/opennebula/vm.js | 43 +++++ .../form-panels/create-common.js | 12 ++ .../form-panels/create/wizard-tabs/network.js | 49 ++++- .../create/wizard-tabs/network/nic-tab.js | 143 ++++++++++++++- .../wizard-tabs/network/nic-tab/html.hbs | 41 ++++- .../templates-tab/form-panels/instantiate.js | 8 + .../app/tabs/vms-tab/dialogs/attach-nic.js | 38 +++- .../tabs/vms-tab/dialogs/attach-nic/html.hbs | 2 + .../public/app/tabs/vms-tab/panels/info.js | 3 + .../app/tabs/vms-tab/panels/info/html.hbs | 6 + .../public/app/tabs/vms-tab/panels/network.js | 81 +++++++- src/sunstone/public/app/utils/nics-section.js | 173 +++++++++++++++++- .../public/app/utils/nics-section/dd.hbs | 48 +++-- 14 files changed, 613 insertions(+), 36 deletions(-) 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 @@
-
- - -
- +
+ {{tr "Interface type"}} +
+ + +
+ +    + + {{tr "NIC has alias"}} + + +
+
+ {{tr "Network selection"}} +
+ + +
+ +
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 @@
+ Attach as an alias +
{{{nicTabHTML}}}