From: Stefan Hanreich <s.hanre...@proxmox.com> This component is generic over both protocols and is used for edit and creation of nodes. It shows a node-selector, the router-id and a list of interfaces available to be selected. If the node is not reachable, we show a read-only panel with a warning.
Co-authored-by: Stefan Hanreich <s.hanre...@proxmox.com> Signed-off-by: Gabriel Goller <g.gol...@proxmox.com> --- www/manager6/Makefile | 1 + www/manager6/sdn/fabrics/NodeEdit.js | 224 +++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 www/manager6/sdn/fabrics/NodeEdit.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index 980c992432de..a0a739d7de99 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -304,6 +304,7 @@ JSSRC= \ sdn/zones/VlanEdit.js \ sdn/zones/VxlanEdit.js \ sdn/fabrics/Common.js \ + sdn/fabrics/NodeEdit.js \ sdn/fabrics/openfabric/InterfacePanel.js \ sdn/fabrics/ospf/InterfacePanel.js \ storage/ContentView.js \ diff --git a/www/manager6/sdn/fabrics/NodeEdit.js b/www/manager6/sdn/fabrics/NodeEdit.js new file mode 100644 index 000000000000..adace6a7bb28 --- /dev/null +++ b/www/manager6/sdn/fabrics/NodeEdit.js @@ -0,0 +1,224 @@ +Ext.define('PVE.sdn.Fabric.Node.InputPanel', { + extend: 'Proxmox.panel.InputPanel', + + viewModel: {}, + + isCreate: undefined, + protocol: undefined, + loadClusterInterfaces: undefined, + interfaceSelector: undefined, + nodeNotAccessibleWarning: undefined, + alreadyConfiguredNodes: undefined, + + onSetValues: function(values) { + let me = this; + me.interfaceSelector.setNetworkInterfaces(values.networkInterfaces); + if (values.node) { + // this means we are in edit mode and we have a config + me.interfaceSelector.addInterfaces(values.node.interfaces); + me.interfaceSelector.updateSelectedInterfaces(values.node.interfaces); + me.interfaceSelector.originalValue = values.node.interfaces; + return { + node_id: values.node.node_id, + router_id: values.node.router_id, + interfaces: values.node.interfaces, + digest: values.node.digest, + }; + } else if (values.router_id) { + // if only a single router_id is set, we only want to update + // that parameter, without reloading the interface panel. + return { router_id: values.router_id }; + } else { + // this means we are in create mode, so don't select any interfaces + me.interfaceSelector.addInterfaces(null); + me.interfaceSelector.updateSelectedInterfaces(null); + return {}; + } + }, + + initComponent: function() { + let me = this; + const PROTOCOL_INTERFACE_PANELS = { + 'openfabric': 'PVE.sdn.Fabric.OpenFabric.InterfacePanel', + 'ospf': 'PVE.sdn.Fabric.Ospf.InterfacePanel', + }; + + me.interfaceSelector = Ext.create(PROTOCOL_INTERFACE_PANELS[me.protocol], { + name: 'interfaces', + parentClass: me.isCreate ? me : undefined, + }); + me.items = [ + { + xtype: 'pveNodeSelector', + reference: 'nodeselector', + fieldLabel: gettext('Node'), + labelWidth: 120, + name: 'node_id', + allowBlank: false, + disabled: !me.isCreate, + disallowedNodes: me.alreadyConfiguredNodes, + onlineValidator: me.isCreate, + autoSelect: me.isCreate, + listeners: { + change: function(f, value) { + if (me.isCreate) { + me.loadClusterInterfaces(value, (result) => { + me.setValues({ networkInterfaces: result }); + }); + } + }, + }, + listConfig: { + columns: [ + { + header: gettext('Node'), + dataIndex: 'node', + sortable: true, + hideable: false, + flex: 1, + }, + ], + }, + + }, + me.nodeNotAccessibleWarning, + { + xtype: 'textfield', + fieldLabel: gettext('Loopback IP'), + labelWidth: 120, + name: 'router_id', + allowBlank: false, + }, + me.interfaceSelector, + ]; + + if (!me.isCreate) { + me.items.push({ + xtype: 'textfield', + name: 'digest', + hidden: true, + allowBlank: false, + }); + } + + me.callParent(); + }, +}); + +Ext.define('PVE.sdn.Fabric.Node.Edit', { + extend: 'Proxmox.window.Edit', + xtype: 'pveSDNFabricAddNode', + + width: 800, + subject: gettext('Node'), + + protocol: undefined, + isCreate: undefined, + + controller: { + xclass: 'Ext.app.ViewController', + }, + + + submitUrl: function(url, values) { + let me = this; + return `${me.url}/${me.extraRequestParams.fabric}/node`; + }, + + loadClusterInterfaces: function(node, onSuccess) { + Proxmox.Utils.API2Request({ + url: `/api2/extjs/nodes/${node}/network`, + method: 'GET', + success: function(response, _opts) { + onSuccess(response.result.data); + }, + // No failure callback because this api call can't fail, it + // just hangs the request :) (if the node doesn't exist it gets proxied) + }); + }, + loadFabricInterfaces: function(protocol, fabric, node, onSuccess, onFailure) { + Proxmox.Utils.API2Request({ + url: `/cluster/sdn/fabrics/${protocol}/${fabric}/node/${node}`, + method: 'GET', + success: function(response, _opts) { + onSuccess(response.result.data); + }, + failure: onFailure, + }); + }, + loadAllAvailableNodes: function(onSuccess) { + Proxmox.Utils.API2Request({ + url: `/cluster/config/nodes`, + method: 'GET', + success: function(response, _opts) { + onSuccess(response.result.data); + }, + }); + }, + + initComponent: function() { + let me = this; + me.onlineHelp = `pvesdn_${me.protocol}_fabric`; + me.url = '/cluster/sdn/fabrics/' + me.protocol; + + me.nodeNotAccessibleWarning = Ext.create('Proxmox.form.field.DisplayEdit', { + userCls: 'pmx-hint', + value: gettext('The node is not accessible.'), + hidden: true, + }); + + let ipanel = Ext.create('PVE.sdn.Fabric.Node.InputPanel', { + nodeNotAccessibleWarning: me.nodeNotAccessibleWarning, + isCreate: me.isCreate, + protocol: me.protocol, + loadClusterInterfaces: me.loadClusterInterfaces, + alreadyConfiguredNodes: me.alreadyConfiguredNodes, + }); + + Ext.apply(me, { + items: [ipanel], + }); + + me.callParent(); + + if (!me.isCreate) { + me.loadAllAvailableNodes((allNodes) => { + if (allNodes.some(i => i.name === me.node)) { + me.loadClusterInterfaces(me.node, (clusterResult) => { + me.loadFabricInterfaces(me.protocol, me.fabric, me.node, (fabricResult) => { + fabricResult.interfaces = fabricResult.interfaces + .map(i => PVE.Parser.parsePropertyString(i)); + + let data = { + node: fabricResult, + networkInterfaces: clusterResult, + }; + + ipanel.setValues(data); + }); + }); + } else { + me.nodeNotAccessibleWarning.setHidden(false); + // If the node is not currently in the cluster and not available (we can't get it's interfaces). + me.loadFabricInterfaces(me.protocol, me.fabric, me.node, (fabricResult) => { + fabricResult.interfaces = fabricResult.interfaces + .map(i => PVE.Parser.parsePropertyString(i)); + + let data = { + node: fabricResult, + }; + + ipanel.setValues(data); + }); + } + }); + } + + if (me.isCreate) { + me.method = 'POST'; + } else { + me.method = 'PUT'; + } + }, +}); + -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel