public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Gabriel Goller <g.goller@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH pve-manager v2 2/3] fabrics: add resource view for fabrics
Date: Fri, 22 Aug 2025 11:00:43 +0200	[thread overview]
Message-ID: <20250822090102.102949-12-g.goller@proxmox.com> (raw)
In-Reply-To: <20250822090102.102949-1-g.goller@proxmox.com>

When clicking on the fabric resources a new content view is available.
It shows the routes and the neighbors of the fabric on that specific
node.

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 www/manager6/Makefile                  |   1 +
 www/manager6/sdn/Browser.js            | 120 ++++++++++++++++++++-----
 www/manager6/sdn/FabricsContentView.js |  91 +++++++++++++++++++
 www/manager6/sdn/StatusView.js         |   2 +-
 4 files changed, 191 insertions(+), 23 deletions(-)
 create mode 100644 www/manager6/sdn/FabricsContentView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 07401f21520b..8b4d672f5145 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -313,6 +313,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/sdn/Browser.js b/www/manager6/sdn/Browser.js
index f7694ae91864..af82bd6390d3 100644
--- a/www/manager6/sdn/Browser.js
+++ b/www/manager6/sdn/Browser.js
@@ -15,39 +15,115 @@ Ext.define('PVE.sdn.Browser', {
         if (!sdnId) {
             throw 'no sdn ID specified';
         }
+        let sdnType = me.pveSelNode.data.sdn_type;
+        if (!sdnType) {
+            throw 'no sdn object type specified';
+        }
 
         me.items = [];
 
+        const caps = Ext.state.Manager.get('GuiCap');
+
+        switch (sdnType) {
+            case 'zone':
+                me.items.push({
+                    nodename: nodename,
+                    zone: sdnId,
+                    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/${sdnId}`,
+                    });
+                }
+                break;
+            case 'fabric':
+                {
+                    let neighborStore = new Ext.data.Store({
+                        model: 'Neighbor',
+                        proxy: {
+                            type: 'proxmox',
+                            url: '/api2/json/cluster/sdn/fabrics/neighbors',
+                            reader: {
+                                type: 'json',
+                                rootProperty: 'data',
+                            },
+                            extraParams: {
+                                node: nodename,
+                            },
+                        },
+                        autoLoad: true,
+                    });
+
+                    let routeStore = new Ext.data.Store({
+                        model: 'Route',
+                        proxy: {
+                            type: 'proxmox',
+                            url: '/api2/json/cluster/sdn/fabrics/routes',
+                            reader: {
+                                type: 'json',
+                                rootProperty: 'data',
+                            },
+                            extraParams: {
+                                node: nodename,
+                            },
+                        },
+                        autoLoad: true,
+                    });
+
+                    me.items.push({
+                        nodename: nodename,
+                        routeStore: routeStore,
+                        fabricId: sdnId,
+                        protocol: me.pveSelNode.data.protocol,
+                        xtype: 'pveSDNFabricRoutesContentView',
+                        title: gettext('Routes'),
+                        iconCls: 'fa fa-th',
+                        itemId: 'routes',
+                        width: '100%',
+                    });
+                    me.items.push({
+                        nodename: nodename,
+                        neighborStore: neighborStore,
+                        fabricId: sdnId,
+                        protocol: me.pveSelNode.data.protocol,
+                        xtype: 'pveSDNFabricNeighborsContentView',
+                        title: gettext('Neighbors'),
+                        iconCls: 'fa fa-th',
+                        itemId: 'neighbors',
+                        width: '100%',
+                    });
+                }
+                break;
+        }
+
         Ext.apply(me, {
             title: Ext.String.format(
-                gettext('Zone {0} on node {1}'),
+                gettext('{0} {1} on node {2}'),
+                `${sdnType}`,
                 `'${sdnId}'`,
                 `'${nodename}'`,
             ),
             hstateid: 'sdntab',
         });
 
-        const caps = Ext.state.Manager.get('GuiCap');
-
-        me.items.push({
-            nodename: nodename,
-            zone: sdnId,
-            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/${sdnId}`,
-            });
-        }
-
         me.callParent();
     },
 });
+
+Ext.define('Route', {
+    extend: 'Ext.data.Model',
+    fields: ['route', 'via', 'fabric_id', 'protocol'],
+});
+Ext.define('Neighbor', {
+    extend: 'Ext.data.Model',
+    fields: ['neighbor', 'status', 'fabric_id', 'protocol'],
+});
diff --git a/www/manager6/sdn/FabricsContentView.js b/www/manager6/sdn/FabricsContentView.js
new file mode 100644
index 000000000000..f1e5ec146b8b
--- /dev/null
+++ b/www/manager6/sdn/FabricsContentView.js
@@ -0,0 +1,91 @@
+Ext.define('PVE.sdn.FabricRoutesContentView', {
+    extend: 'Ext.grid.GridPanel',
+    alias: 'widget.pveSDNFabricRoutesContentView',
+
+    initComponent: function () {
+        let me = this;
+        let sm = Ext.create('Ext.selection.RowModel', {});
+
+        me.routeStore.addFilter([
+            {
+                property: 'fabric_id',
+                value: me.fabricId,
+            },
+            {
+                property: 'protocol',
+                value: me.protocol,
+            },
+        ]);
+        me.routeStore.sort('route', 'ASC');
+
+        Ext.apply(me, {
+            store: me.routeStore,
+            selModel: sm,
+            columns: [
+                {
+                    header: 'Route',
+                    sortable: true,
+                    dataIndex: 'route',
+                    flex: 1,
+                },
+                {
+                    header: 'Via',
+                    sortable: true,
+                    dataIndex: 'via',
+                    renderer: (value) => {
+                        if (Ext.isArray(value)) {
+                            return value.join('<br>');
+                        }
+                        return value || '';
+                    },
+                    flex: 1,
+                },
+            ],
+        });
+
+        me.callParent();
+    },
+});
+
+Ext.define('PVE.sdn.FabricNeighborsContentView', {
+    extend: 'Ext.grid.GridPanel',
+    alias: 'widget.pveSDNFabricNeighborsContentView',
+
+    initComponent: function () {
+        let me = this;
+        let sm = Ext.create('Ext.selection.RowModel', {});
+
+        me.neighborStore.addFilter([
+            {
+                property: 'fabric_id',
+                value: me.fabricId,
+            },
+            {
+                property: 'protocol',
+                value: me.protocol,
+            },
+        ]);
+        me.neighborStore.sort('neighbor', 'ASC');
+
+        Ext.apply(me, {
+            store: me.neighborStore,
+            selModel: sm,
+            columns: [
+                {
+                    header: 'Neighbor',
+                    sortable: true,
+                    dataIndex: 'neighbor',
+                    flex: 1,
+                },
+                {
+                    header: 'Status',
+                    sortable: true,
+                    dataIndex: 'status',
+                    flex: 0.5,
+                },
+            ],
+        });
+
+        me.callParent();
+    },
+});
diff --git a/www/manager6/sdn/StatusView.js b/www/manager6/sdn/StatusView.js
index dd05c73fdfcf..e66e3f624354 100644
--- a/www/manager6/sdn/StatusView.js
+++ b/www/manager6/sdn/StatusView.js
@@ -102,7 +102,7 @@ Ext.define(
     function () {
         Ext.define('pve-sdn-status', {
             extend: 'Ext.data.Model',
-            fields: ['id', 'type', 'node', 'status', 'sdn'],
+            fields: ['id', 'type', 'node', 'status', 'sdn', 'sdn_type'],
             idProperty: 'id',
         });
     },
-- 
2.47.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-08-22  9:02 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-22  9:00 [pve-devel] [PATCH manager/network/proxmox{-ve-rs, -perl-rs} v2 00/12] Add fabric status view Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-ve-rs v2 1/2] frr: make room for deserialization structs Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-ve-rs v2 2/2] frr: add deserialization types for openfabric and ospf Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-perl-rs v2 1/4] pve: fabrics: update proxmox-frr import path Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-perl-rs v2 2/4] fabrics: add function to get status of fabric Gabriel Goller
2025-08-25  8:11   ` Wolfgang Bumiller
2025-08-25  8:25     ` Wolfgang Bumiller
2025-08-25 11:39     ` Gabriel Goller
2025-08-25 14:37       ` Wolfgang Bumiller
2025-08-25 15:33         ` Gabriel Goller
2025-08-26  7:55           ` Wolfgang Bumiller
2025-08-26  8:29             ` Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-perl-rs v2 3/4] fabrics: add function to get all routes distributed by the fabrics Gabriel Goller
2025-08-25  8:22   ` Wolfgang Bumiller
2025-08-25 11:40     ` Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH proxmox-perl-rs v2 4/4] fabrics: add function to get all neighbors of the fabric Gabriel Goller
2025-08-25  8:28   ` Wolfgang Bumiller
2025-08-25 11:41     ` Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH pve-network v2 1/3] fabrics: add fabrics status to SDN::status function Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH pve-network v2 2/3] fabrics: add api endpoint to return fabrics routes Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH pve-network v2 3/3] fabrics: add api endpoint to return fabric neighbors Gabriel Goller
2025-08-22  9:00 ` [pve-devel] [PATCH pve-manager v2 1/3] pvestatd: add fabrics status to pvestatd Gabriel Goller
2025-08-22  9:00 ` Gabriel Goller [this message]
2025-08-22  9:00 ` [pve-devel] [PATCH pve-manager v2 3/3] permissions: differentiate between zone and fabric paths Gabriel Goller
2025-08-26  9:52 ` [pve-devel] [PATCH manager/network/proxmox{-ve-rs, -perl-rs} v2 00/12] Add fabric status view Gabriel Goller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250822090102.102949-12-g.goller@proxmox.com \
    --to=g.goller@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal