From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 0BDDB1FF187 for ; Mon, 3 Nov 2025 15:18:40 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B39EF1EA51; Mon, 3 Nov 2025 15:19:17 +0100 (CET) Message-ID: <989750eb-3c4a-4421-a8e6-9871e01f6b08@proxmox.com> Date: Mon, 3 Nov 2025 15:19:13 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: Proxmox VE development discussion , Stefan Hanreich References: <20251030154851.540408-1-s.hanreich@proxmox.com> <20251030154851.540408-33-s.hanreich@proxmox.com> Content-Language: en-US From: Hannes Laimer In-Reply-To: <20251030154851.540408-33-s.hanreich@proxmox.com> X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1762179536586 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.042 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pve-devel] [PATCH pve-manager 5/8] ui: resource tree: add network resource X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" small typo inline On 10/30/25 16:50, Stefan Hanreich wrote: > From: Gabriel Goller > > Add the newly introduced network resource to the resource tree, so the > the status of fabrics can be displayed in the UI. For this matter, a > new NetworkBrowser widget is added, which is responsible for showing > the contents of a network resource. > > The NetworkBrowser widget also contains code for handling the zone > type, which is currently still contained in the sdn resource type. > This ensures a smooth transition when moving the zones into the new > network resource type. > > Co-authored-by: Stefan Hanreich > Signed-off-by: Gabriel Goller > Signed-off-by: Stefan Hanreich > --- > www/manager6/Makefile | 2 + > www/manager6/Utils.js | 11 ++ > www/manager6/Workspace.js | 1 + > www/manager6/sdn/FabricsContentView.js | 77 ++++++++++++ > www/manager6/sdn/NetworkBrowser.js | 167 +++++++++++++++++++++++++ > www/manager6/tree/ResourceTree.js | 6 + > 6 files changed, 264 insertions(+) > create mode 100644 www/manager6/sdn/FabricsContentView.js > create mode 100644 www/manager6/sdn/NetworkBrowser.js > > diff --git a/www/manager6/Makefile b/www/manager6/Makefile > index 85f9268d1..ba762578e 100644 > --- a/www/manager6/Makefile > +++ b/www/manager6/Makefile > @@ -278,6 +278,7 @@ JSSRC= \ > qemu/USBEdit.js \ > qemu/VirtiofsEdit.js \ > sdn/Browser.js \ > + sdn/NetworkBrowser.js \ > sdn/ControllerView.js \ > sdn/Status.js \ > sdn/StatusView.js \ > @@ -313,6 +314,7 @@ JSSRC= \ > sdn/zones/VlanEdit.js \ > sdn/zones/VxlanEdit.js \ > sdn/FabricsView.js \ > + sdn/FabricsContentView.js \ > sdn/fabrics/Common.js \ > sdn/fabrics/InterfacePanel.js \ > sdn/fabrics/NodeEdit.js \ > diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js > index c48ee0b25..2f812a442 100644 > --- a/www/manager6/Utils.js > +++ b/www/manager6/Utils.js > @@ -1276,6 +1276,12 @@ Ext.define('PVE.Utils', { > // templates > objType = 'template'; > status = type; > + } else if (type === 'network') { > + const network_type_mapping = { > + fabric: 'fa fa-road', > + }; > + > + return network_type_mapping[record.network_type] ?? ''; > } else if (type === 'storage' && record.content === 'import') { > return 'fa fa-cloud-download'; > } else { > @@ -1299,6 +1305,11 @@ Ext.define('PVE.Utils', { > var cls = PVE.Utils.get_object_icon_class(value, record.data); > > var fa = ' '; > + > + if (value === 'network') { > + return fa + record.data.network_type; > + } > + > return fa + value; > }, > > diff --git a/www/manager6/Workspace.js b/www/manager6/Workspace.js > index a25746582..9f1e807d5 100644 > --- a/www/manager6/Workspace.js > +++ b/www/manager6/Workspace.js > @@ -250,6 +250,7 @@ Ext.define('PVE.StdWorkspace', { > lxc: 'pveLXCConfig', > storage: 'PVE.storage.Browser', > sdn: 'PVE.sdn.Browser', > + network: 'PVE.network.Browser', > pool: 'pvePoolConfig', > tag: 'pveTagConfig', > }; > diff --git a/www/manager6/sdn/FabricsContentView.js b/www/manager6/sdn/FabricsContentView.js > new file mode 100644 > index 000000000..47e8bce7f > --- /dev/null > +++ b/www/manager6/sdn/FabricsContentView.js > @@ -0,0 +1,77 @@ > +Ext.define('PVE.sdn.FabricRoutesContentView', { > + extend: 'Ext.grid.GridPanel', > + alias: 'widget.pveSDNFabricRoutesContentView', > + > + columns: [ > + { > + header: gettext('Route'), > + sortable: true, > + dataIndex: 'route', > + flex: 1, > + }, > + { > + header: gettext('Via'), > + sortable: true, > + dataIndex: 'via', > + renderer: (value) => { > + if (Ext.isArray(value)) { > + return value.join('
'); > + } > + return value || ''; > + }, > + flex: 1, > + }, > + ], > +}); > + > +Ext.define('PVE.sdn.FabricNeighborsContentView', { > + extend: 'Ext.grid.GridPanel', > + alias: 'widget.pveSDNFabricNeighborsContentView', > + > + columns: [ > + { > + header: gettext('Neighbor'), > + sortable: true, > + dataIndex: 'neighbor', > + flex: 1, > + }, > + { > + header: gettext('Status'), > + sortable: true, > + dataIndex: 'status', > + flex: 0.5, > + }, > + { > + header: gettext('Uptime'), > + sortable: true, > + dataIndex: 'uptime', > + flex: 0.5, > + }, > + ], > +}); > + > +Ext.define('PVE.sdn.FabricInterfacesContentView', { > + extend: 'Ext.grid.GridPanel', > + alias: 'widget.pveSDNFabricInterfacesContentView', > + > + columns: [ > + { > + header: gettext('Name'), > + sortable: true, > + dataIndex: 'name', > + flex: 1, > + }, > + { > + header: gettext('Type'), > + sortable: true, > + dataIndex: 'type', > + flex: 1, > + }, > + { > + header: gettext('State'), > + sortable: true, > + dataIndex: 'state', > + flex: 1, > + }, > + ], > +}); > diff --git a/www/manager6/sdn/NetworkBrowser.js b/www/manager6/sdn/NetworkBrowser.js > new file mode 100644 > index 000000000..ad024e6a1 > --- /dev/null > +++ b/www/manager6/sdn/NetworkBrowser.js > @@ -0,0 +1,167 @@ > +Ext.define('PVE.network.Browser', { > + extend: 'PVE.panel.Config', > + alias: 'widget.PVE.network.Browser', > + > + initComponent: function () { > + let me = this; > + let data = me.pveSelNode.data; > + > + let node = data.node; > + if (!node) { > + throw 'no node name specified'; > + } > + > + let name = data.network; > + if (!name) { > + throw 'no name specified'; > + } > + > + let networkType = data.network_type; > + if (!name) { > + throw 'no type specified'; > + } s/name/networkType/ > + > + me.items = []; > + > + if (networkType === 'fabric') { > + me.onlineHelp = 'pvesdn_config_fabrics'; > + > + me.items.push({ > + nodename: node, > + fabricId: name, > + protocol: me.pveSelNode.data.protocol, > + xtype: 'pveSDNFabricRoutesContentView', > + title: gettext('Routes'), > + iconCls: 'fa fa-exchange', > + itemId: 'routes', > + width: '100%', > + store: { > + proxy: { > + type: 'proxmox', > + url: `/api2/json/nodes/${node}/sdn/fabrics/${name}/routes`, > + reader: { > + type: 'json', > + rootProperty: 'data', > + }, > + }, > + autoLoad: true, > + }, > + }); > + > + me.items.push({ > + nodename: node, > + fabricId: name, > + protocol: me.pveSelNode.data.protocol, > + xtype: 'pveSDNFabricNeighborsContentView', > + title: gettext('Neighbors'), > + iconCls: 'fa fa-handshake-o', > + itemId: 'neighbors', > + width: '100%', > + store: { > + proxy: { > + type: 'proxmox', > + url: `/api2/json/nodes/${node}/sdn/fabrics/${name}/neighbors`, > + reader: { > + type: 'json', > + rootProperty: 'data', > + }, > + }, > + autoLoad: true, > + }, > + }); > + > + me.items.push({ > + nodename: node, > + fabricId: name, > + protocol: me.pveSelNode.data.protocol, > + xtype: 'pveSDNFabricInterfacesContentView', > + title: gettext('Interfaces'), > + iconCls: 'fa fa-upload', > + itemId: 'interfaces', > + width: '100%', > + store: { > + proxy: { > + type: 'proxmox', > + url: `/api2/json/nodes/${node}/sdn/fabrics/${name}/interfaces`, > + reader: { > + type: 'json', > + rootProperty: 'data', > + }, > + }, > + autoLoad: true, > + }, > + }); > + } else if (networkType === 'zone') { > + const caps = Ext.state.Manager.get('GuiCap'); > + > + me.items.push({ > + nodename: node, > + zone: name, > + xtype: 'pveSDNZoneContentPanel', > + title: gettext('Content'), > + iconCls: 'fa fa-th', > + itemId: 'content', > + }); > + > + if (caps.sdn['Permissions.Modify']) { > + me.items.push({ > + xtype: 'pveACLView', > + title: gettext('Permissions'), > + iconCls: 'fa fa-unlock', > + itemId: 'permissions', > + path: `/sdn/zones/${name}`, > + }); > + } > + > + me.items.push({ > + nodename: node, > + zone: name, > + xtype: 'pveSDNZoneBridgePanel', > + title: gettext('Bridges'), > + iconCls: 'fa fa-network-wired x-fa-sdn-treelist', > + itemId: 'bridges', > + }); > + > + if (data.zone_type && data.zone_type === 'evpn') { > + me.items.push({ > + nodename: node, > + zone: name, > + xtype: 'pveSDNEvpnZoneIpVrfPanel', > + title: gettext('IP-VRF'), > + iconCls: 'fa fa-th-list', > + itemId: 'ip-vrf', > + }); > + > + me.items.push({ > + nodename: node, > + zone: name, > + xtype: 'pveSDNEvpnZoneMacVrfPanel', > + title: gettext('MAC-VRFs'), > + iconCls: 'fa fa-th-list', > + itemId: 'mac-vrfs', > + }); > + } > + } else { > + me.items.push({ > + xtype: 'container', > + title: gettext('Content'), > + iconCls: 'fa fa-th', > + itemId: 'content', > + html: `unknown network type: ${networkType}`, > + width: '100%', > + }); > + } > + > + Ext.apply(me, { > + title: Ext.String.format( > + gettext('{0} {1} on node {2}'), > + `${networkType}`, > + `'${name}'`, > + `'${node}'`, > + ), > + hstateid: 'networktab', > + }); > + > + me.callParent(); > + }, > +}); > diff --git a/www/manager6/tree/ResourceTree.js b/www/manager6/tree/ResourceTree.js > index e83ccfc85..b6ab9a1e9 100644 > --- a/www/manager6/tree/ResourceTree.js > +++ b/www/manager6/tree/ResourceTree.js > @@ -25,6 +25,10 @@ Ext.define('PVE.tree.ResourceTree', { > iconCls: 'fa fa-th', > text: gettext('SDN'), > }, > + network: { > + iconCls: 'fa fa-globe', > + text: gettext('Network'), > + }, > qemu: { > iconCls: 'fa fa-desktop', > text: gettext('Virtual Machine'), > @@ -55,6 +59,8 @@ Ext.define('PVE.tree.ResourceTree', { > return 2; > case 'sdn': > return 3; > + case 'network': > + return 3.5; > case 'storage': > return 4; > default: _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel