* [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking
@ 2025-11-13 16:19 Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 1/2] pve-rs: update proxmox-frr dependency Stefan Hanreich
` (21 more replies)
0 siblings, 22 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
## Warning
Applying this patch series, will break all version of PDM that do not have
support for the new network type, since all nodes now send resources that are
incompatible with the PDM schema. We might want to consider holding off the
resource type parts until after we've prepared a PDM version that can actually
handle those resources. Prior to v2, this was only limited to Remotes that have
an SDN fabric configured - now it isn't anymore since every node sends at least
the localnetwork SDN zone as a network resource.
## Introduction
This patch series builds upon and replaces the two patch series initially
submitted by Gabriel [1] [2]. Main reason for merging those is that some
additional refactoring to the status API module structure as well as the UI
widgets for the SDN browser has been done, which both series would need to
depend on. Additionally, the EVPN series depended on the fabric series already
as well, so submitting them as one seemed like the least complicated option for
both developers and maintainers with the additional changes introduced in this
iteration.
refreshed packages are available on sani: `network-resource-pve`
## Rationale
Currently, the SDN and PVE networking stack provide little insight into their
inner workings and can be a bit of a black box to users. Inspecting the current
state of networking resources, particularly for EVPN zones, requires dropping
into the CLI and invoking specific iproute2 / FRR commands. The current status
endpoint only provides very coarse and limited feedback on the current state of
SDN / networking resources.
With this iteration, this patch series also adds status reporting for bridges /
vnets, which has been requested several times in forums / enterprise support /
trainings.
Most of those endpoints could be interesting additions to the PDM UI as well,
particularly fabrics and evpn status.
## New network resource type
While the initial implementations extended the existing SDN resource type, this
iteration introduces a 'network' resource type. The pre-existing SDN resource
type utilized 'sdn/<zone_id>' as its id, which makes it hard to add additional
types that do not share that ID space. Changing the schema for the ID would also
break backwards-compatibility of API and UI between 9.0 and 9.1.
With potential additional status reporting for other network entities (see
below), it would make sense to generalize the resource type to network in
particular, to avoid cluttering the top level with one type per SDN/networking
entity. If that is not a concern, the current state could be easily adapted to
have one top-level type per resource - simplifying the current implementation.
The ID schema for this resource type is now as follow:
network/{node}/{network_type}/{name}
An example network resource:
{
"id": "network/acolyte/fabric/underlay",
"type": "network",
"network-type": "fabric",
"network": "underlay"
"node": "acolyte",
"status": "ok",
"protocol": "ospf",
}
The plan for migrating:
* New nodes will report the resource status in *both* formats
* New networking entities (fabrics, for now) will utilize the network resource
type only
* When migrating from PVE 9 -> 10, status reporting for zones will move to the
new network resource type completely
* old nodes should be able to cope with the old format, but they cannot display
any newly returned information - it will get dropped
* PDM will also be able to handle both formats with a separate pdm series, so
older versions of Proxmox VE can also be used with PDM
I know this is a bit of a sledgehammer method of solving this problem, but imo
while this migration might be a bit painful now, it seems the best option to me
long-term. Any suggestions / opinions on this would be greatly appreciated. I
don't really see another way of implementing additional types of entities
without either breaking backwards-compatibility with PVE <= 9.0 or having
potential ID collisions in the SDN resource type or having one dedicated type
per networking resource.
## Potential future work / extensions
Add status reporting for the firewall, which currently acts a bit like a
black-box as well, without any easy way of checking the current (running) state
of the firewall.
Other entities to consider adding to the resources: controllers, DNS, external
IPAM.
The data from those endpoints could be used to provide a graphical overview of a
bridge in the UI, an idea which has been floating around internally for awhile.
## New API endpoints
/nodes/{node}/sdn/fabrics/{fabric}/routes
/nodes/{node}/sdn/fabrics/{fabric}/neighbors
/nodes/{node}/sdn/fabrics/{fabric}/interfaces
/nodes/{node}/sdn/zones/{zone}/ip-vrf
/nodes/{node}/sdn/zones/{zone}/bridges
/nodes/{node}/sdn/vnets/{vnet}/mac-vrf
## New UI panels
Those panels can all be reached via the resource tree and are found in the SDN
browser.
For all zones:
* Bridges overview
For EVPN zones:
* IP-VRF
* MAC-VRFs
For Fabrics:
* Routes
* Neighbors
* Interfaces
## Dependencies
proxmox-perl-rs depends on proxmox-ve-rs
pve-network depends on proxmox-perl-rs
pve-network depends on pve-common
pve-manager depends on pve-network
Changes from v3:
* omitted applied patches
* rename network_type -> network-type
* rename zone_type -> zone-type
* rebased on top of current master
* added permission helper for network resource
* split the pvestatd / resources api call commit into two
Changes from v2:
* Made the implications of merging this patch series more evident and prominent
in the cover letter
* Fix SDN status overview
* Fix displayed icon for zones in the ResourceTree
Changes from v1 (Thanks @Thomas, @Wolfgang, @Hannes, @Gabriel!):
* Broadcast zones via both resource types, not only the previous sdn one
* Add handling for receiving zones via both resource types, to avoid duplicated
entries
* Update fabrics API endpoints descriptions and property descriptions
* Fix typo when checking parameter in the NetworkBrowser panel
* add definedness check in ip_link_is_bridge_member
* add integration / snapshot tests (courtesy of gabriel)
* -compressvlan -> -compressvlans in IPRoute2 Helper
Changes from (v1, v4):
* refactor the SDN status API module structure (no functional changes to
existing endpoints)
* move the fabrics API endpoints to the pre-existing /nodes/{node}/sdn subdir
* refactor the SDN content view panel, so it can be reused for the EVPN panels
(no functional changes to existing UI panels)
* add a completely new resource type, instead of trying to re-use the existing
SDN one (reasoning above).
* move the iproute2 and bridge helpers to pve-common
* improve JSONSchema of all API endpoints (descriptions mainly)
* return additional information in the fabric endpoints
* add full UI integration for EVPN status (IP-VRF + MAC-VRF panels)
* Use the installed, duplicate and bestpath properties of FRR to show only
routes that are actually installed into the kernel routing table for EVPN
zones
* filter for type 2 routes specifically when invoking vtysh
[1] https://lore.proxmox.com/pve-devel/20250904114206.193052-1-g.goller@proxmox.com/
[2] https://lore.proxmox.com/pve-devel/20250905114504.195110-1-g.goller@proxmox.com/
proxmox-perl-rs:
Stefan Hanreich (2):
pve-rs: update proxmox-frr dependency
pve-rs: sdn status: rename network_type to network-type
pve-rs/Cargo.toml | 2 +-
pve-rs/debian/control | 2 +-
pve-rs/src/sdn/status.rs | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
pve-network:
Gabriel Goller (3):
fabrics: add fabrics status to SDN::status function
api: nodes: fabrics: add endpoint for querying route status
api: nodes: fabrics: add endpoint for querying neighbor information
Stefan Hanreich (6):
refactor: rework api module structure for the /nodes/{node}/sdn subdir
sdn: status: add zone type to sdn resource
api: nodes: fabrics: add endpoint for querying interface status
api: nodes: zones: add bridge status
api: nodes: zones: add ip vrf endpoint for evpn zones
api: nodes: vnets: add mac-vrf endpoint for evpn vnets
src/PVE/API2/Network/SDN/Makefile | 2 +-
src/PVE/API2/Network/SDN/Nodes/Fabric.pm | 187 +++++++++
src/PVE/API2/Network/SDN/Nodes/Fabrics.pm | 16 +
.../Network/SDN/{Zones => Nodes}/Makefile | 12 +-
src/PVE/API2/Network/SDN/Nodes/Status.pm | 61 +++
src/PVE/API2/Network/SDN/Nodes/Vnet.pm | 147 +++++++
src/PVE/API2/Network/SDN/Nodes/Vnets.pm | 16 +
src/PVE/API2/Network/SDN/Nodes/Zone.pm | 379 ++++++++++++++++++
.../SDN/{Zones/Status.pm => Nodes/Zones.pm} | 58 +--
src/PVE/API2/Network/SDN/Vnets.pm | 2 +-
src/PVE/API2/Network/SDN/Zones/Content.pm | 88 ----
src/PVE/Network/SDN.pm | 6 +-
src/PVE/Network/SDN/Zones.pm | 2 +
src/test/debug/statuscheck.pl | 3 +-
14 files changed, 833 insertions(+), 146 deletions(-)
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabric.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabrics.pm
rename src/PVE/API2/Network/SDN/{Zones => Nodes}/Makefile (51%)
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Status.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnet.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnets.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Zone.pm
rename src/PVE/API2/Network/SDN/{Zones/Status.pm => Nodes/Zones.pm} (56%)
delete mode 100644 src/PVE/API2/Network/SDN/Zones/Content.pm
pve-manager:
Gabriel Goller (2):
pvestatd: add network resource to status reporting
ui: resource tree: add network resource
Stefan Hanreich (8):
api: nodes: use new status module for sdn subdirectory
refactor: ui: sdn browser: parametrize zone content panel
api: cluster: add support for network resource type
pvestatd: sdn: adapt to changes in status reporting
ui: network browser: Add ip-vrf panel for evpn zones
ui: network browser: add mac vrf panel
ui: network browser: add zone bridge view
ui: sdn: status view: adapt to new network resource
PVE/API2/Cluster.pm | 123 +++++++++++++----
PVE/API2/Nodes.pm | 50 +------
PVE/Service/pvestatd.pm | 39 ++++--
www/manager6/Makefile | 6 +
www/manager6/Utils.js | 12 ++
www/manager6/Workspace.js | 1 +
www/manager6/sdn/Browser.js | 20 +++
www/manager6/sdn/EvpnZoneIpVrfPanel.js | 84 ++++++++++++
www/manager6/sdn/EvpnZoneMacVrfPanel.js | 130 ++++++++++++++++++
www/manager6/sdn/FabricsContentView.js | 77 +++++++++++
www/manager6/sdn/NetworkBrowser.js | 167 ++++++++++++++++++++++++
www/manager6/sdn/StatusView.js | 11 +-
www/manager6/sdn/ZoneBridgeView.js | 88 +++++++++++++
www/manager6/sdn/ZoneBridgesPanel.js | 131 +++++++++++++++++++
www/manager6/sdn/ZoneContentPanel.js | 11 +-
www/manager6/sdn/ZoneContentView.js | 75 ++++++-----
www/manager6/tree/ResourceTree.js | 6 +
17 files changed, 914 insertions(+), 117 deletions(-)
create mode 100644 www/manager6/sdn/EvpnZoneIpVrfPanel.js
create mode 100644 www/manager6/sdn/EvpnZoneMacVrfPanel.js
create mode 100644 www/manager6/sdn/FabricsContentView.js
create mode 100644 www/manager6/sdn/NetworkBrowser.js
create mode 100644 www/manager6/sdn/ZoneBridgeView.js
create mode 100644 www/manager6/sdn/ZoneBridgesPanel.js
Summary over all repositories:
34 files changed, 1750 insertions(+), 265 deletions(-)
--
Generated by git-murpp 0.8.0
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH proxmox-perl-rs v4 1/2] pve-rs: update proxmox-frr dependency
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 2/2] pve-rs: sdn status: rename network_type to network-type Stefan Hanreich
` (20 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
pve-rs/Cargo.toml | 2 +-
pve-rs/debian/control | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pve-rs/Cargo.toml b/pve-rs/Cargo.toml
index 68680a9..2f6da0e 100644
--- a/pve-rs/Cargo.toml
+++ b/pve-rs/Cargo.toml
@@ -33,7 +33,7 @@ proxmox-apt = { version = "0.99.4", features = ["cache"] }
proxmox-apt-api-types = "2"
proxmox-base64 = "1"
proxmox-config-digest = "1"
-proxmox-frr = { version = "0.1" }
+proxmox-frr = { version = "0.2" }
proxmox-http = { version = "1.0.2", features = ["client-sync", "client-trait"] }
proxmox-http-error = "1"
proxmox-log = "1"
diff --git a/pve-rs/debian/control b/pve-rs/debian/control
index c5c3da4..4fab07a 100644
--- a/pve-rs/debian/control
+++ b/pve-rs/debian/control
@@ -19,7 +19,7 @@ Build-Depends: cargo:native <!nocheck>,
librust-proxmox-apt-api-types-2+default-dev,
librust-proxmox-base64-1+default-dev,
librust-proxmox-config-digest-1+default-dev,
- librust-proxmox-frr-0.1+default-dev,
+ librust-proxmox-frr-0.2+default-dev,
librust-proxmox-http-1+client-sync-dev (>= 1.0.2-~~),
librust-proxmox-http-1+client-trait-dev (>= 1.0.2-~~),
librust-proxmox-http-1+default-dev (>= 1.0.2-~~),
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH proxmox-perl-rs v4 2/2] pve-rs: sdn status: rename network_type to network-type
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 1/2] pve-rs: update proxmox-frr dependency Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 1/9] refactor: rework api module structure for the /nodes/{node}/sdn subdir Stefan Hanreich
` (19 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
To follow our kebab-casing conventions for new properties returned
from the API.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
pve-rs/src/sdn/status.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/pve-rs/src/sdn/status.rs b/pve-rs/src/sdn/status.rs
index 6e75562..78b5550 100644
--- a/pve-rs/src/sdn/status.rs
+++ b/pve-rs/src/sdn/status.rs
@@ -159,6 +159,7 @@ pub struct Status {
status: FabricStatus,
protocol: Protocol,
network: FabricId,
+ #[serde(rename = "network-type")]
network_type: String,
}
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 1/9] refactor: rework api module structure for the /nodes/{node}/sdn subdir
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 1/2] pve-rs: update proxmox-frr dependency Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 2/2] pve-rs: sdn status: rename network_type to network-type Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 2/9] fabrics: add fabrics status to SDN::status function Stefan Hanreich
` (18 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
Previously, the endpoints for the SDN browser were contained in the
PVE::API2::Network::SDN::Zones module, which was registered in
PVE::API2::Nodes (located in pve-manager) directly with the sub-path
'sdn/{zone}'.
Instead of importing the zones module in pve-manager directly, create
a top-level Nodes module in pve-network, that is then imported in
pve-manager under the path 'sdn'. By importing just the root-level
module, changes can be made to the pve-network API without having to
update pve-manager. This allows for a better module structure on
pve-network side, because different entities can then be managed in
pve-network directly in the new top-level module. This is mainly in
preparation for adding new Vnets and Fabrics modules.
Also, the zones' content endpoint was contained in its own module. In
order to make it easier to add new endpoints to the 'sdn/zones/{zone}'
directory, move the contents endpoint into a new module that is
imported directly under 'sdn/zones/{zone}'. This allows easily adding
endpoints under the 'sdn/zones/{zone}' sub directory, without having
to create a separate module for each endpoint and registering it in
the Status module.
No functional changes intended, every endpoint should be the same as
before (URL + returned information).
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Makefile | 2 +-
.../Network/SDN/{Zones => Nodes}/Makefile | 8 ++-
src/PVE/API2/Network/SDN/Nodes/Status.pm | 49 +++++++++++++++
.../SDN/{Zones/Content.pm => Nodes/Zone.pm} | 59 +++++++++++++++----
.../SDN/{Zones/Status.pm => Nodes/Zones.pm} | 56 +++---------------
5 files changed, 111 insertions(+), 63 deletions(-)
rename src/PVE/API2/Network/SDN/{Zones => Nodes}/Makefile (62%)
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Status.pm
rename src/PVE/API2/Network/SDN/{Zones/Content.pm => Nodes/Zone.pm} (60%)
rename src/PVE/API2/Network/SDN/{Zones/Status.pm => Nodes/Zones.pm} (59%)
diff --git a/src/PVE/API2/Network/SDN/Makefile b/src/PVE/API2/Network/SDN/Makefile
index 08bec75..2624d9a 100644
--- a/src/PVE/API2/Network/SDN/Makefile
+++ b/src/PVE/API2/Network/SDN/Makefile
@@ -6,6 +6,6 @@ PERL5DIR=${DESTDIR}/usr/share/perl5
.PHONY: install
install:
for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/SDN/$$i; done
- make -C Zones install
make -C Fabrics install
+ make -C Nodes install
diff --git a/src/PVE/API2/Network/SDN/Zones/Makefile b/src/PVE/API2/Network/SDN/Nodes/Makefile
similarity index 62%
rename from src/PVE/API2/Network/SDN/Zones/Makefile
rename to src/PVE/API2/Network/SDN/Nodes/Makefile
index 9b0a42b..edf0225 100644
--- a/src/PVE/API2/Network/SDN/Zones/Makefile
+++ b/src/PVE/API2/Network/SDN/Nodes/Makefile
@@ -1,8 +1,10 @@
-SOURCES=Status.pm Content.pm
-
+SOURCES=\
+ Status.pm\
+ Zone.pm\
+ Zones.pm
PERL5DIR=${DESTDIR}/usr/share/perl5
.PHONY: install
install:
- for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/SDN/Zones/$$i; done
+ for i in ${SOURCES}; do install -D -m 0644 $$i ${PERL5DIR}/PVE/API2/Network/SDN/Nodes/$$i; done
diff --git a/src/PVE/API2/Network/SDN/Nodes/Status.pm b/src/PVE/API2/Network/SDN/Nodes/Status.pm
new file mode 100644
index 0000000..e862d4a
--- /dev/null
+++ b/src/PVE/API2/Network/SDN/Nodes/Status.pm
@@ -0,0 +1,49 @@
+package PVE::API2::Network::SDN::Nodes::Status;
+
+use strict;
+use warnings;
+
+use PVE::API2::Network::SDN::Nodes::Zones;
+
+use PVE::JSONSchema qw(get_standard_option);
+
+use PVE::RESTHandler;
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Zones",
+ path => 'zones',
+});
+
+__PACKAGE__->register_method({
+ name => 'sdnindex',
+ path => '',
+ method => 'GET',
+ permissions => { user => 'all' },
+ description => "SDN index.",
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+ links => [{ rel => 'child', href => "{name}" }],
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $result = [
+ { name => 'zones' },
+ ];
+ return $result;
+ },
+});
+
+1;
diff --git a/src/PVE/API2/Network/SDN/Zones/Content.pm b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
similarity index 60%
rename from src/PVE/API2/Network/SDN/Zones/Content.pm
rename to src/PVE/API2/Network/SDN/Nodes/Zone.pm
index 7666321..1e963fc 100644
--- a/src/PVE/API2/Network/SDN/Zones/Content.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
@@ -1,26 +1,65 @@
-package PVE::API2::Network::SDN::Zones::Content;
+package PVE::API2::Network::SDN::Nodes::Zone;
use strict;
use warnings;
-use PVE::SafeSyslog;
-use PVE::Cluster;
-use PVE::INotify;
+use JSON qw(decode_json);
+
use PVE::Exception qw(raise_param_exc);
-use PVE::RPCEnvironment;
-use PVE::RESTHandler;
+use PVE::INotify;
+use PVE::IPRoute2;
use PVE::JSONSchema qw(get_standard_option);
-use PVE::Network::SDN;
+use PVE::Network;
+use PVE::Network::SDN::Vnets;
+use PVE::Network::SDN::Zones;
+use PVE::RS::SDN::Fabrics;
+use PVE::Tools qw(extract_param run_command);
+use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
__PACKAGE__->register_method({
- name => 'index',
+ name => 'diridx',
path => '',
method => 'GET',
+ description => "Directory index for SDN zone status.",
+ permissions => {
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit']],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ zone => get_standard_option('pve-sdn-zone-id'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ subdir => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{subdir}" }],
+ },
+ code => sub {
+ my ($param) = @_;
+ my $res = [
+ { subdir => 'content' }, { subdir => 'bridges' }, { subdir => 'ip-vrf' },
+ ];
+
+ return $res;
+ },
+});
+
+__PACKAGE__->register_method({
+ path => 'content',
+ name => 'index',
+ method => 'GET',
description => "List zone content.",
permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit']],
},
protected => 1,
proxyto => 'node',
@@ -70,7 +109,7 @@ __PACKAGE__->register_method({
my $res = [];
- my ($zone_status, $vnet_status) = PVE::Network::SDN::status();
+ my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
foreach my $id (keys %{$vnet_status}) {
if ($vnet_status->{$id}->{zone} eq $zoneid) {
diff --git a/src/PVE/API2/Network/SDN/Zones/Status.pm b/src/PVE/API2/Network/SDN/Nodes/Zones.pm
similarity index 59%
rename from src/PVE/API2/Network/SDN/Zones/Status.pm
rename to src/PVE/API2/Network/SDN/Nodes/Zones.pm
index 4957567..54c444f 100644
--- a/src/PVE/API2/Network/SDN/Zones/Status.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Zones.pm
@@ -1,24 +1,17 @@
-package PVE::API2::Network::SDN::Zones::Status;
+package PVE::API2::Network::SDN::Nodes::Zones;
-use strict;
-use warnings;
-
-use File::Path;
-use File::Basename;
-use PVE::Tools;
+use PVE::API2::Network::SDN::Nodes::Zone;
use PVE::INotify;
-use PVE::Cluster;
-use PVE::API2::Network::SDN::Zones::Content;
-use PVE::RESTHandler;
-use PVE::RPCEnvironment;
use PVE::JSONSchema qw(get_standard_option);
-use PVE::Exception qw(raise_param_exc);
+use PVE::Network::SDN;
+use PVE::RPCEnvironment;
+use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
__PACKAGE__->register_method({
- subclass => "PVE::API2::Network::SDN::Zones::Content",
- path => '{zone}/content',
+ subclass => "PVE::API2::Network::SDN::Nodes::Zone",
+ path => '{zone}',
});
__PACKAGE__->register_method({
@@ -75,39 +68,4 @@ __PACKAGE__->register_method({
},
});
-__PACKAGE__->register_method({
- name => 'diridx',
- path => '{zone}',
- method => 'GET',
- description => "",
- permissions => {
- check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit'], any => 1],
- },
- parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- zone => get_standard_option('pve-sdn-zone-id'),
- },
- },
- returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {
- subdir => { type => 'string' },
- },
- },
- links => [{ rel => 'child', href => "{subdir}" }],
- },
- code => sub {
- my ($param) = @_;
- my $res = [
- { subdir => 'content' },
- ];
-
- return $res;
- },
-});
-
1;
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 2/9] fabrics: add fabrics status to SDN::status function
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (2 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 1/9] refactor: rework api module structure for the /nodes/{node}/sdn subdir Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 3/9] sdn: status: add zone type to sdn resource Stefan Hanreich
` (17 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
From: Gabriel Goller <g.goller@proxmox.com>
This makes it so fabrics can be included in the SDN panel in the Web
UI. To avoid having to calculate the fabrics status information on
endpoints that only require the zone status, move the pre-existing
call sites over to the zone-specific function.
Co-authored-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Zones.pm | 2 +-
src/PVE/Network/SDN.pm | 6 ++++--
src/test/debug/statuscheck.pl | 3 ++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/PVE/API2/Network/SDN/Nodes/Zones.pm b/src/PVE/API2/Network/SDN/Nodes/Zones.pm
index 54c444f..b92be6a 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Zones.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Zones.pm
@@ -56,7 +56,7 @@ __PACKAGE__->register_method({
my $res = [];
- my ($zone_status, $vnet_status) = PVE::Network::SDN::status();
+ my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
foreach my $id (sort keys %{$zone_status}) {
my $item->{zone} = $id;
diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm
index f2ecd4a..81374b0 100644
--- a/src/PVE/Network/SDN.pm
+++ b/src/PVE/Network/SDN.pm
@@ -16,6 +16,8 @@ use PVE::RESTEnvironment qw(log_warn);
use PVE::RPCEnvironment;
use PVE::Tools qw(file_get_contents file_set_contents extract_param dir_glob_regex run_command);
+use PVE::RS::SDN::Fabrics;
+
use PVE::Network::SDN::Vnets;
use PVE::Network::SDN::Zones;
use PVE::Network::SDN::Controllers;
@@ -97,9 +99,9 @@ sub ifquery_check {
}
sub status {
-
my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
- return ($zone_status, $vnet_status);
+ my $fabric_status = PVE::RS::SDN::Fabrics::status();
+ return ($zone_status, $vnet_status, $fabric_status);
}
sub running_config {
diff --git a/src/test/debug/statuscheck.pl b/src/test/debug/statuscheck.pl
index e43003b..e963117 100644
--- a/src/test/debug/statuscheck.pl
+++ b/src/test/debug/statuscheck.pl
@@ -3,7 +3,8 @@ use warnings;
use PVE::Network::SDN;
use Data::Dumper;
-my ($transport_status, $vnet_status) = PVE::Network::SDN::status();
+my ($transport_status, $vnet_status, $fabric_status) = PVE::Network::SDN::status();
+print Dumper($fabric_status);
print Dumper($vnet_status);
print Dumper($transport_status);
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 3/9] sdn: status: add zone type to sdn resource
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (3 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 2/9] fabrics: add fabrics status to SDN::status function Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 4/9] api: nodes: fabrics: add endpoint for querying route status Stefan Hanreich
` (16 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This will mainly be used by the UI determine whether to show panels
that are specific to a certain zone type (e.g. IP-VRF panel for EVPN
zones).
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/Network/SDN/Zones.pm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/PVE/Network/SDN/Zones.pm b/src/PVE/Network/SDN/Zones.pm
index 5f30df3..4da9458 100644
--- a/src/PVE/Network/SDN/Zones.pm
+++ b/src/PVE/Network/SDN/Zones.pm
@@ -254,7 +254,9 @@ sub status {
next
if defined($zone_cfg->{ids}->{$id}->{nodes})
&& !$zone_cfg->{ids}->{$id}->{nodes}->{$nodename};
+
$zone_status->{$id}->{status} = $err_config ? 'pending' : 'available';
+ $zone_status->{$id}->{'zone-type'} = $zone_cfg->{ids}->{$id}->{type};
}
foreach my $id (sort keys %{ $vnet_cfg->{ids} }) {
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 4/9] api: nodes: fabrics: add endpoint for querying route status
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (4 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 3/9] sdn: status: add zone type to sdn resource Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 5/9] api: nodes: fabrics: add endpoint for querying neighbor information Stefan Hanreich
` (15 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
From: Gabriel Goller <g.goller@proxmox.com>
This endpoint returns all routes from a given fabric, that are
imported in to the kernel routing table. For more information about
the return value, consult the respective proxmox-perl-rs commit. It is
used by the NetworkBrowser panel in pve-manager.
Co-authored-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Fabric.pm | 94 +++++++++++++++++++++++
src/PVE/API2/Network/SDN/Nodes/Fabrics.pm | 16 ++++
src/PVE/API2/Network/SDN/Nodes/Makefile | 2 +
src/PVE/API2/Network/SDN/Nodes/Status.pm | 8 +-
4 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabric.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabrics.pm
diff --git a/src/PVE/API2/Network/SDN/Nodes/Fabric.pm b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
new file mode 100644
index 0000000..43a7a36
--- /dev/null
+++ b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
@@ -0,0 +1,94 @@
+package PVE::API2::Network::SDN::Nodes::Fabric;
+
+use strict;
+use warnings;
+
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::Network::SDN::Fabrics;
+use PVE::RPCEnvironment;
+use PVE::RS::SDN::Fabrics;
+use PVE::Tools qw(extract_param);
+
+use PVE::RESTHandler;
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+ name => 'diridx',
+ path => '',
+ method => 'GET',
+ description => "Directory index for SDN fabric status.",
+ permissions => {
+ check => ['perm', '/sdn/fabrics/{fabric}', ['SDN.Audit']],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ fabric => get_standard_option('pve-sdn-fabric-id'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ subdir => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{subdir}" }],
+ },
+ code => sub {
+ my ($param) = @_;
+ my $res = [
+ { subdir => 'routes' },
+ ];
+
+ return $res;
+ },
+});
+
+__PACKAGE__->register_method({
+ name => 'routes',
+ path => 'routes',
+ method => 'GET',
+ description => "Get all routes for a fabric.",
+ permissions => {
+ check => ['perm', '/sdn/fabrics/{fabric}', ['SDN.Audit']],
+ },
+ protected => 1,
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ fabric => get_standard_option('pve-sdn-fabric-id'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ route => {
+ description => "The CIDR block for this routing table entry.",
+ type => 'string',
+ },
+ via => {
+ description => "A list of nexthops for that route.",
+ type => 'array',
+ items => {
+ type => 'string',
+ description => 'The IP address of the nexthop.',
+ },
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $fabric_id = extract_param($param, 'fabric');
+ return PVE::RS::SDN::Fabrics::routes($fabric_id);
+ },
+});
+
diff --git a/src/PVE/API2/Network/SDN/Nodes/Fabrics.pm b/src/PVE/API2/Network/SDN/Nodes/Fabrics.pm
new file mode 100644
index 0000000..bbf557b
--- /dev/null
+++ b/src/PVE/API2/Network/SDN/Nodes/Fabrics.pm
@@ -0,0 +1,16 @@
+package PVE::API2::Network::SDN::Nodes::Fabrics;
+
+use strict;
+use warnings;
+
+use PVE::API2::Network::SDN::Nodes::Fabric;
+
+use PVE::RESTHandler;
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Fabric",
+ path => '{fabric}',
+});
+
+1;
diff --git a/src/PVE/API2/Network/SDN/Nodes/Makefile b/src/PVE/API2/Network/SDN/Nodes/Makefile
index edf0225..4e4791a 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Makefile
+++ b/src/PVE/API2/Network/SDN/Nodes/Makefile
@@ -1,4 +1,6 @@
SOURCES=\
+ Fabric.pm\
+ Fabrics.pm\
Status.pm\
Zone.pm\
Zones.pm
diff --git a/src/PVE/API2/Network/SDN/Nodes/Status.pm b/src/PVE/API2/Network/SDN/Nodes/Status.pm
index e862d4a..2ce2702 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Status.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Status.pm
@@ -3,6 +3,7 @@ package PVE::API2::Network::SDN::Nodes::Status;
use strict;
use warnings;
+use PVE::API2::Network::SDN::Nodes::Fabrics;
use PVE::API2::Network::SDN::Nodes::Zones;
use PVE::JSONSchema qw(get_standard_option);
@@ -10,6 +11,11 @@ use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use base qw(PVE::RESTHandler);
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Fabrics",
+ path => 'fabrics',
+});
+
__PACKAGE__->register_method({
subclass => "PVE::API2::Network::SDN::Nodes::Zones",
path => 'zones',
@@ -40,7 +46,7 @@ __PACKAGE__->register_method({
my ($param) = @_;
my $result = [
- { name => 'zones' },
+ { name => 'fabrics' }, { name => 'zones' },
];
return $result;
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 5/9] api: nodes: fabrics: add endpoint for querying neighbor information
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (5 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 4/9] api: nodes: fabrics: add endpoint for querying route status Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 6/9] api: nodes: fabrics: add endpoint for querying interface status Stefan Hanreich
` (14 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
From: Gabriel Goller <g.goller@proxmox.com>
This endpoint returns all neighbors for a given fabric and their
current status. For more information about the return value, consult
the respective proxmox-perl-rs commit. It is used by the
NetworkBrowser panel.
Co-authored-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Fabric.pm | 48 +++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/PVE/API2/Network/SDN/Nodes/Fabric.pm b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
index 43a7a36..436d987 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
@@ -40,7 +40,7 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
my $res = [
- { subdir => 'routes' },
+ { subdir => 'neighbors' }, { subdir => 'routes' },
];
return $res;
@@ -92,3 +92,49 @@ __PACKAGE__->register_method({
},
});
+__PACKAGE__->register_method({
+ name => 'neighbors',
+ path => 'neighbors',
+ method => 'GET',
+ description => "Get all neighbors for a fabric.",
+ permissions => {
+ check => ['perm', '/sdn/fabrics/{fabric}', ['SDN.Audit']],
+ },
+ protected => 1,
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ fabric => get_standard_option('pve-sdn-fabric-id'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ neighbor => {
+ description => "The IP or hostname of the neighbor.",
+ type => 'string',
+ },
+ status => {
+ description => "The status of the neighbor, as returned by FRR.",
+ type => 'string',
+ },
+ uptime => {
+ description =>
+ "The uptime of this neighbor, as returned by FRR (e.g. 8h24m12s).",
+ type => 'string',
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $fabric_id = extract_param($param, 'fabric');
+ return PVE::RS::SDN::Fabrics::neighbors($fabric_id);
+ },
+});
+
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 6/9] api: nodes: fabrics: add endpoint for querying interface status
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (6 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 5/9] api: nodes: fabrics: add endpoint for querying neighbor information Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 7/9] api: nodes: zones: add bridge status Stefan Hanreich
` (13 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This endpoint returns the state of interfaces that are part of the
fabric. For more information on the returned values, consult the
proxmox-perl-rs commit. It is used by the NetworkBrowser panel.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Fabric.pm | 47 ++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/src/PVE/API2/Network/SDN/Nodes/Fabric.pm b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
index 436d987..0202b81 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Fabric.pm
@@ -138,3 +138,50 @@ __PACKAGE__->register_method({
},
});
+__PACKAGE__->register_method({
+ name => 'interfaces',
+ path => 'interfaces',
+ method => 'GET',
+ description => "Get all interfaces for a fabric.",
+ protected => 1,
+ permissions => {
+ check => ['perm', '/sdn/fabrics/{fabric}', ['SDN.Audit']],
+ },
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ fabric => get_standard_option('pve-sdn-fabric-id'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ name => {
+ description => "The name of the network interface.",
+ type => 'string',
+ },
+ type => {
+ description =>
+ "The type of this interface in the fabric (e.g. Point-to-Point, Broadcast, ..).",
+ type => 'string',
+ },
+ state => {
+ description => "The current state of the interface.",
+ type => 'string',
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $fabric_id = extract_param($param, 'fabric');
+ return PVE::RS::SDN::Fabrics::interfaces($fabric_id);
+ },
+});
+
+1;
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 7/9] api: nodes: zones: add bridge status
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (7 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 6/9] api: nodes: fabrics: add endpoint for querying interface status Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 8/9] api: nodes: zones: add ip vrf endpoint for evpn zones Stefan Hanreich
` (12 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This endpoint returns an overview of all ports that are currently
members of a bridge (the running state). Additionally it provides
information about the configured VLANs on VLAN-aware bridges. If the
special zone name 'localnetwork' is used, then this endpoint returns
the information for all bridges that are configured outside of SDN via
/etc/network/interfaces.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Zone.pm | 173 +++++++++++++++++++++++++
1 file changed, 173 insertions(+)
diff --git a/src/PVE/API2/Network/SDN/Nodes/Zone.pm b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
index 1e963fc..d7312df 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Zone.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
@@ -124,4 +124,177 @@ __PACKAGE__->register_method({
},
});
+__PACKAGE__->register_method({
+ name => 'bridges',
+ path => 'bridges',
+ proxyto => 'node',
+ method => 'GET',
+ protected => 1,
+ description =>
+ "Get a list of all bridges (vnets) that are part of a zone, as well as the ports that are members of that bridge.",
+ permissions => {
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit']],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ zone => {
+ type => 'string',
+ description => 'zone name or "localnetwork"',
+ },
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ description => 'List of bridges contained in the SDN zone.',
+ type => 'object',
+ properties => {
+ name => {
+ description => 'Name of the bridge.',
+ type => 'string',
+ },
+ vlan_filtering => {
+ description =>
+ 'Whether VLAN filtering is enabled for this bridge (= VLAN-aware).',
+ type => 'string',
+ },
+ ports => {
+ description => 'All ports that are members of the bridge',
+ type => 'array',
+ items => {
+ description => 'Information about bridge ports.',
+ type => 'object',
+ properties => {
+ name => {
+ description => 'The name of the bridge port.',
+ type => 'string',
+ },
+ vmid => {
+ description =>
+ 'The ID of the guest that this interface belongs to.',
+ type => 'number',
+ optional => 1,
+ },
+ index => {
+ description =>
+ 'The index of the guests network device that this interface belongs to.',
+ type => 'number',
+ optional => 1,
+ },
+ primary_vlan => {
+ description =>
+ 'The primary VLAN configured for the port of this bridge (= PVID). Only for VLAN-aware bridges.',
+ type => 'number',
+ optional => 1,
+ },
+ vlans => {
+ description =>
+ 'A list of VLANs and VLAN ranges that are allowed for this bridge port in addition to the primary VLAN. Only for VLAN-aware bridges.',
+ type => 'array',
+ items => {
+ description =>
+ 'A single VLAN (123) or a VLAN range (234-435).',
+ type => 'string',
+ },
+ optional => 1,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $zone_id = extract_param($param, 'zone');
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+
+ my @bridges_in_zone;
+ if ($zone_id eq 'localnetwork') {
+ my $interface_config = PVE::INotify::read_file('interfaces', 1);
+ my $interfaces = $interface_config->{data}->{ifaces};
+
+ @bridges_in_zone =
+ grep { $interfaces->{$_}->{type} eq 'bridge' } keys $interfaces->%*;
+ } else {
+ my $zone = PVE::Network::SDN::Zones::get_zone($zone_id, 1);
+
+ raise_param_exc({
+ zone => "zone does not exist",
+ })
+ if !$zone;
+
+ my $vnet_cfg = PVE::Network::SDN::Vnets::config(1);
+ @bridges_in_zone =
+ grep { $vnet_cfg->{ids}->{$_}->{zone} eq $zone_id } keys $vnet_cfg->{ids}->%*;
+ }
+
+ my $ip_details = PVE::Network::ip_link_details();
+ my $vlan_information = PVE::IPRoute2::get_vlan_information();
+
+ my $result = {};
+ for my $bridge_name (@bridges_in_zone) {
+ next
+ if !$rpcenv->check_any(
+ $authuser,
+ "/sdn/zones/$zone_id/$bridge_name",
+ ['SDN.Audit', 'SDN.Allocate'],
+ 1,
+ );
+
+ my $ip_link = $ip_details->{$bridge_name};
+
+ $result->{$bridge_name} = {
+ name => $bridge_name,
+ vlan_filtering => $ip_link->{linkinfo}->{info_data}->{vlan_filtering},
+ ports => [],
+ };
+ }
+
+ for my $interface (values $ip_details->%*) {
+ if (PVE::IPRoute2::ip_link_is_bridge_member($interface)) {
+ my $master = $interface->{master};
+
+ # avoid potential TOCTOU by just skipping over the interface,
+ # if we didn't get the master from 'ip link'
+ next if !defined($result->{$master});
+
+ my $ifname = $interface->{ifname};
+
+ my $port = {
+ name => $ifname,
+ };
+
+ if ($ifname =~ m/^(?:fwpr(\d+)p(\d+)|veth(\d+)i(\d+)|tap(\d+)i(\d+))$/) {
+ $port->{vmid} = $1;
+ $port->{index} = $2;
+ }
+
+ if ($result->{$master}->{vlan_filtering} == 1) {
+ $port->{vlans} = [];
+
+ for my $vlan ($vlan_information->{$ifname}->{vlans}->@*) {
+ if (grep { $_ eq 'PVID' } $vlan->{flags}->@*) {
+ $port->{primary_vlan} = $vlan->{vlan};
+ } elsif ($vlan->{vlan} && $vlan->{vlanEnd}) {
+ push $port->{vlans}->@*, "$vlan->{vlan}-$vlan->{vlanEnd}";
+ } elsif ($vlan->{vlan}) {
+ push $port->{vlans}->@*, "$vlan->{vlan}";
+ }
+ }
+ }
+
+ push $result->{$master}->{ports}->@*, $port;
+ }
+ }
+
+ my @result = values $result->%*;
+ return \@result;
+ },
+});
+
1;
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 8/9] api: nodes: zones: add ip vrf endpoint for evpn zones
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (8 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 7/9] api: nodes: zones: add bridge status Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 9/9] api: nodes: vnets: add mac-vrf endpoint for evpn vnets Stefan Hanreich
` (11 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This endpoint returns the state of the routing table on a node for a
given EVPN zone. This is used by the SDN browser panel to display
status information in the UI.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Zone.pm | 79 ++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/src/PVE/API2/Network/SDN/Nodes/Zone.pm b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
index d7312df..43acbe9 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Zone.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Zone.pm
@@ -297,4 +297,83 @@ __PACKAGE__->register_method({
},
});
+__PACKAGE__->register_method({
+ name => 'ip-vrf',
+ path => 'ip-vrf',
+ proxyto => 'node',
+ method => 'GET',
+ protected => 1,
+ description => "Get the IP VRF of an EVPN zone.",
+ permissions => {
+ check => ['perm', '/sdn/zones/{zone}', ['SDN.Audit']],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ zone => {
+ type => 'string',
+ description => 'Name of an EVPN zone.',
+ },
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ description => 'All entries in the VRF table of zone {zone} of the node.'
+ . 'This does not include /32 routes for guests on this host,'
+ . 'since they are handled via the respective vnet bridge directly.',
+ type => 'array',
+ items => {
+ type => 'object',
+ properties => {
+ ip => {
+ type => 'string',
+ format => 'CIDR',
+ description => 'The CIDR of the route table entry.',
+ },
+ metric => {
+ type => 'integer',
+ description => 'This route\'s metric.',
+ },
+ protocol => {
+ type => 'string',
+ description => 'The protocol where this route was learned from (e.g. BGP).',
+ },
+ 'nexthops' => {
+ type => 'array',
+ description => 'A list of nexthops for the route table entry.',
+ items => {
+ type => 'string',
+ description => 'the interface name or ip address of the next hop',
+ },
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $zone_id = extract_param($param, 'zone');
+ my $zone = PVE::Network::SDN::Zones::get_zone($zone_id, 1);
+
+ raise_param_exc({
+ zone => "zone does not exist",
+ })
+ if !$zone;
+
+ raise_param_exc({
+ zone => "zone is not an EVPN zone",
+ })
+ if $zone->{type} ne 'evpn';
+
+ my $node_id = extract_param($param, 'node');
+
+ raise_param_exc({
+ zone => "zone does not exist on node $node_id",
+ })
+ if defined($zone->{nodes}) && !grep { $_ eq $node_id } $zone->{nodes}->@*;
+
+ return PVE::RS::SDN::Fabrics::l3vpn_routes($zone_id);
+ },
+});
+
1;
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-network v4 9/9] api: nodes: vnets: add mac-vrf endpoint for evpn vnets
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (9 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 8/9] api: nodes: zones: add ip vrf endpoint for evpn zones Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 01/10] api: nodes: use new status module for sdn subdirectory Stefan Hanreich
` (10 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This endpoint returns the current L2VNI of a given EVPN VNet, as
learned via BGP. This is used by the SDN browser to provide status
information for the EVPN vnet.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
src/PVE/API2/Network/SDN/Nodes/Makefile | 2 +
src/PVE/API2/Network/SDN/Nodes/Status.pm | 8 +-
src/PVE/API2/Network/SDN/Nodes/Vnet.pm | 147 +++++++++++++++++++++++
src/PVE/API2/Network/SDN/Nodes/Vnets.pm | 16 +++
src/PVE/API2/Network/SDN/Vnets.pm | 2 +-
5 files changed, 173 insertions(+), 2 deletions(-)
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnet.pm
create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnets.pm
diff --git a/src/PVE/API2/Network/SDN/Nodes/Makefile b/src/PVE/API2/Network/SDN/Nodes/Makefile
index 4e4791a..e70d2ce 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Makefile
+++ b/src/PVE/API2/Network/SDN/Nodes/Makefile
@@ -2,6 +2,8 @@ SOURCES=\
Fabric.pm\
Fabrics.pm\
Status.pm\
+ Vnet.pm\
+ Vnets.pm\
Zone.pm\
Zones.pm
diff --git a/src/PVE/API2/Network/SDN/Nodes/Status.pm b/src/PVE/API2/Network/SDN/Nodes/Status.pm
index 2ce2702..7977e0c 100644
--- a/src/PVE/API2/Network/SDN/Nodes/Status.pm
+++ b/src/PVE/API2/Network/SDN/Nodes/Status.pm
@@ -5,6 +5,7 @@ use warnings;
use PVE::API2::Network::SDN::Nodes::Fabrics;
use PVE::API2::Network::SDN::Nodes::Zones;
+use PVE::API2::Network::SDN::Nodes::Vnets;
use PVE::JSONSchema qw(get_standard_option);
@@ -21,6 +22,11 @@ __PACKAGE__->register_method({
path => 'zones',
});
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Vnets",
+ path => 'vnets',
+});
+
__PACKAGE__->register_method({
name => 'sdnindex',
path => '',
@@ -46,7 +52,7 @@ __PACKAGE__->register_method({
my ($param) = @_;
my $result = [
- { name => 'fabrics' }, { name => 'zones' },
+ { name => 'fabrics' }, { name => 'vnets' }, { name => 'zones' },
];
return $result;
},
diff --git a/src/PVE/API2/Network/SDN/Nodes/Vnet.pm b/src/PVE/API2/Network/SDN/Nodes/Vnet.pm
new file mode 100644
index 0000000..d5dae56
--- /dev/null
+++ b/src/PVE/API2/Network/SDN/Nodes/Vnet.pm
@@ -0,0 +1,147 @@
+package PVE::API2::Network::SDN::Nodes::Vnet;
+
+use strict;
+use warnings;
+
+use PVE::API2::Network::SDN::Vnets;
+use PVE::Exception qw(raise_param_exc);
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::Network::SDN::Vnets;
+use PVE::Network::SDN::Zones;
+use PVE::RS::SDN::Fabrics;
+use PVE::Tools qw(extract_param);
+
+use PVE::RESTHandler;
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+ name => 'diridx',
+ path => '',
+ method => 'GET',
+ description => "",
+ permissions => {
+ description => "Require 'SDN.Audit' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vnet => get_standard_option(
+ 'pve-sdn-vnet-id',
+ {
+ completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
+ },
+ ),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {
+ subdir => { type => 'string' },
+ },
+ },
+ links => [{ rel => 'child', href => "{subdir}" }],
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $vnet_id = extract_param($param, 'vnet');
+ $PVE::API2::Network::SDN::Vnets::check_vnet_access->($vnet_id, ['SDN.Audit']);
+
+ my $res = [
+ { subdir => 'mac-vrf' },
+ ];
+
+ return $res;
+ },
+});
+
+__PACKAGE__->register_method({
+ name => 'mac-vrf',
+ path => 'mac-vrf',
+ proxyto => 'node',
+ method => 'GET',
+ description => "Get the MAC VRF for a VNet in an EVPN zone.",
+ protected => 1,
+ permissions => {
+ description => "Require 'SDN.Audit' permissions on '/sdn/zones/<zone>/<vnet>'",
+ user => 'all',
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ vnet => get_standard_option(
+ 'pve-sdn-vnet-id',
+ {
+ completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets,
+ },
+ ),
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ description =>
+ 'All routes from the MAC VRF that this node self-originates or has learned via BGP.',
+ type => 'array',
+ items => {
+ type => 'object',
+ properties => {
+ ip => {
+ type => 'string',
+ format => 'ip',
+ description => 'The IP address of the MAC VRF entry.',
+ },
+ mac => {
+ type => 'string',
+ format => 'mac-addr',
+ description => 'The MAC address of the MAC VRF entry.',
+ },
+ 'nexthop' => {
+ type => 'string',
+ format => 'ip',
+ description => 'The IP address of the nexthop.',
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $vnet_id = extract_param($param, 'vnet');
+
+ $PVE::API2::Network::SDN::Vnets::check_vnet_access->($vnet_id, ['SDN.Audit']);
+
+ my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnet_id, 1);
+
+ raise_param_exc({
+ vnet => "vnet does not exist",
+ })
+ if !$vnet;
+
+ my $zone = PVE::Network::SDN::Zones::get_zone($vnet->{zone}, 1);
+
+ raise_param_exc({
+ zone => "zone $vnet->{zone} does not exist",
+ })
+ if !$zone;
+
+ raise_param_exc({
+ zone => "zone $vnet->{zone} is not an EVPN zone.",
+ })
+ if $zone->{type} ne 'evpn';
+
+ my $node_id = extract_param($param, 'node');
+
+ raise_param_exc({
+ zone => "zone $vnet->{zone} of vnet $vnet_id does not exist on node $node_id",
+ })
+ if defined($zone->{nodes}) && !grep { $_ eq $node_id } $zone->{nodes}->@*;
+
+ return PVE::RS::SDN::Fabrics::l2vpn_routes($vnet_id);
+ },
+});
+
+1;
diff --git a/src/PVE/API2/Network/SDN/Nodes/Vnets.pm b/src/PVE/API2/Network/SDN/Nodes/Vnets.pm
new file mode 100644
index 0000000..4f07201
--- /dev/null
+++ b/src/PVE/API2/Network/SDN/Nodes/Vnets.pm
@@ -0,0 +1,16 @@
+package PVE::API2::Network::SDN::Nodes::Vnets;
+
+use strict;
+use warnings;
+
+use PVE::API2::Network::SDN::Nodes::Vnet;
+
+use PVE::RESTHandler;
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Vnet",
+ path => '{vnet}',
+});
+
+1;
diff --git a/src/PVE/API2/Network/SDN/Vnets.pm b/src/PVE/API2/Network/SDN/Vnets.pm
index 1d9e500..b8faeac 100644
--- a/src/PVE/API2/Network/SDN/Vnets.pm
+++ b/src/PVE/API2/Network/SDN/Vnets.pm
@@ -63,7 +63,7 @@ my $api_sdn_vnets_deleted_config = sub {
}
};
-my $check_vnet_access = sub {
+our $check_vnet_access = sub {
my ($vnet, $privs) = @_;
my $cfg = PVE::Network::SDN::Vnets::config();
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 01/10] api: nodes: use new status module for sdn subdirectory
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (10 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 9/9] api: nodes: vnets: add mac-vrf endpoint for evpn vnets Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 02/10] refactor: ui: sdn browser: parametrize zone content panel Stefan Hanreich
` (9 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
In order to avoid having to import every single new module for future
status reporting, SDN now exposes a single module that is imported
here.
Also remove the legacy have_sdn guards here, since SDN is
pre-installed for awhile and the guard therefore not needed anymore.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
PVE/API2/Nodes.pm | 50 ++++++-----------------------------------------
1 file changed, 6 insertions(+), 44 deletions(-)
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index 4590b6186..08d9d1b51 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -49,6 +49,7 @@ use PVE::API2::Hardware;
use PVE::API2::LXC::Status;
use PVE::API2::LXC;
use PVE::API2::Network;
+use PVE::API2::Network::SDN::Nodes::Status;
use PVE::API2::NodeConfig;
use PVE::API2::Qemu::CPU;
use PVE::API2::Qemu;
@@ -60,12 +61,6 @@ use PVE::API2::Subscription;
use PVE::API2::Tasks;
use PVE::API2::VZDump;
-my $have_sdn;
-eval {
- require PVE::API2::Network::SDN::Zones::Status;
- $have_sdn = 1;
-};
-
use base qw(PVE::RESTHandler);
my $verify_command_item_desc = {
@@ -201,42 +196,10 @@ __PACKAGE__->register_method({
path => 'config',
});
-if ($have_sdn) {
- __PACKAGE__->register_method({
- subclass => "PVE::API2::Network::SDN::Zones::Status",
- path => 'sdn/zones',
- });
-
- __PACKAGE__->register_method({
- name => 'sdnindex',
- path => 'sdn',
- method => 'GET',
- permissions => { user => 'all' },
- description => "SDN index.",
- parameters => {
- additionalProperties => 0,
- properties => {
- node => get_standard_option('pve-node'),
- },
- },
- returns => {
- type => 'array',
- items => {
- type => "object",
- properties => {},
- },
- links => [{ rel => 'child', href => "{name}" }],
- },
- code => sub {
- my ($param) = @_;
-
- my $result = [
- { name => 'zones' },
- ];
- return $result;
- },
- });
-}
+__PACKAGE__->register_method({
+ subclass => "PVE::API2::Network::SDN::Nodes::Status",
+ path => 'sdn',
+});
__PACKAGE__->register_method({
name => 'index',
@@ -285,6 +248,7 @@ __PACKAGE__->register_method({
{ name => 'rrd' }, # fixme: remove?
{ name => 'rrddata' },
{ name => 'scan' },
+ { name => 'sdn' },
{ name => 'services' },
{ name => 'spiceshell' },
{ name => 'startall' },
@@ -303,8 +267,6 @@ __PACKAGE__->register_method({
{ name => 'wakeonlan' },
];
- push @$result, { name => 'sdn' } if $have_sdn;
-
return $result;
},
});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 02/10] refactor: ui: sdn browser: parametrize zone content panel
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (11 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 01/10] api: nodes: use new status module for sdn subdirectory Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 03/10] pvestatd: add network resource to status reporting Stefan Hanreich
` (8 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
In order to reuse the zone content panel for future, additional,
panels in the SDN browser, move all static configuration properties
into the declaration of the ExtJS widget. In particular, make the
on_(de)select callbacks configurable, so this panel can be customized
to work with a multitude of additional panels.
This is a preparation for extended status reporting for SDN zones,
which will add several new panels that want to utilize the content
view.
The selectionModel uses the default configuration that is included in
the GridPanel, so it can be removed.
No functional changes intended.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/sdn/ZoneContentPanel.js | 11 +++-
www/manager6/sdn/ZoneContentView.js | 75 +++++++++++++++-------------
2 files changed, 49 insertions(+), 37 deletions(-)
diff --git a/www/manager6/sdn/ZoneContentPanel.js b/www/manager6/sdn/ZoneContentPanel.js
index 76b8500b1..50d2dd741 100644
--- a/www/manager6/sdn/ZoneContentPanel.js
+++ b/www/manager6/sdn/ZoneContentPanel.js
@@ -18,12 +18,21 @@ Ext.define('PVE.sdn.ZoneContentPanel', {
var vnetview_panel = Ext.createWidget('pveSDNZoneContentView', {
title: 'VNets',
region: 'west',
- permissions_panel: permissions_panel,
+ sub_panel: permissions_panel,
nodename: me.nodename,
zone: me.zone,
width: '50%',
border: false,
split: true,
+
+ on_select: function (_sm, rec) {
+ let path = `/sdn/zones/${me.zone}/${rec.data.vnet}`;
+ permissions_panel.setPath(path);
+ },
+
+ on_deselect: function () {
+ permissions_panel.setPath(undefined);
+ },
});
Ext.apply(me, {
diff --git a/www/manager6/sdn/ZoneContentView.js b/www/manager6/sdn/ZoneContentView.js
index 97b3612e1..2243f277f 100644
--- a/www/manager6/sdn/ZoneContentView.js
+++ b/www/manager6/sdn/ZoneContentView.js
@@ -16,6 +16,43 @@ Ext.define(
groupHeaderTpl: '{name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})',
},
],
+
+ sub_panel: null,
+
+ columns: [
+ {
+ header: gettext('VNet'),
+ width: 100,
+ sortable: true,
+ dataIndex: 'vnet',
+ },
+ {
+ header: gettext('Alias'),
+ width: 300,
+ sortable: true,
+ dataIndex: 'alias',
+ },
+ {
+ header: gettext('Status'),
+ width: 100,
+ sortable: true,
+ dataIndex: 'status',
+ },
+ {
+ header: gettext('Details'),
+ flex: 1,
+ dataIndex: 'statusmsg',
+ },
+ ],
+
+ on_select: function (selectionModel, record) {
+ // do nothing by default
+ },
+
+ on_deselect: function () {
+ // do nothing by default
+ },
+
initComponent: function () {
var me = this;
@@ -44,8 +81,6 @@ Ext.define(
},
});
- var sm = Ext.create('Ext.selection.RowModel', {});
-
var reload = function () {
store.load();
};
@@ -53,43 +88,11 @@ Ext.define(
Proxmox.Utils.monStoreErrors(me, store);
Ext.apply(me, {
store: store,
- selModel: sm,
- tbar: [],
- columns: [
- {
- header: 'VNet',
- width: 100,
- sortable: true,
- dataIndex: 'vnet',
- },
- {
- header: 'Alias',
- width: 300,
- sortable: true,
- dataIndex: 'alias',
- },
- {
- header: gettext('Status'),
- width: 100,
- sortable: true,
- dataIndex: 'status',
- },
- {
- header: gettext('Details'),
- flex: 1,
- dataIndex: 'statusmsg',
- },
- ],
listeners: {
activate: reload,
show: reload,
- select: function (_sm, rec) {
- let path = `/sdn/zones/${me.zone}/${rec.data.vnet}`;
- me.permissions_panel.setPath(path);
- },
- deselect: function () {
- me.permissions_panel.setPath(undefined);
- },
+ select: me.on_select,
+ deselect: me.on_deselect,
},
});
store.load();
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 03/10] pvestatd: add network resource to status reporting
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (12 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 02/10] refactor: ui: sdn browser: parametrize zone content panel Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 04/10] api: cluster: add support for network resource type Stefan Hanreich
` (7 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
From: Gabriel Goller <g.goller@proxmox.com>
The new network resource will act as the top-level resource for all
networking entities (including SDN entities). The network resource
contains a network_type field, which indicates the type of networking
resource - similar to how the storage plugin handles different types
of storages. For now, it contains SDN fabrics and the SDN zones have
been copied over as well.
The main reason for moving over to a new resource type is the current
ID schema of the SDN resource, which is 'sdn/{zone_id}'. This makes it
hard to extend without the possibility of ID collisions. Additionally,
since the ID is used in several places throughout the backend / UI,
changing the schema would break compatibility with nodes that are on
an earlier version and would be an API break as well.
With this patch, nodes will still broadcast the old format for
backwards-compatibility. A subsequent patch for the resources API will
handle this case and ignore the old SDN resources from nodes that are
already sending the new format, to avoid including zones twice in the
returned resource data.
Co-authored-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
PVE/Service/pvestatd.pm | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
index 618d6139a..572eb7eb5 100755
--- a/PVE/Service/pvestatd.pm
+++ b/PVE/Service/pvestatd.pm
@@ -15,6 +15,7 @@ use PVE::CpuSet;
use Filesys::Df;
use PVE::INotify;
use PVE::Network;
+use PVE::RS::SDN::Fabrics;
use PVE::NodeConfig;
use PVE::Cluster qw(cfs_read_file);
use PVE::Storage;
@@ -775,6 +776,28 @@ sub update_sdn_status {
}
}
+sub update_network_status {
+ my $network_status = {};
+
+ my ($fabric_status) = PVE::RS::SDN::Fabrics::status();
+ for my $fabric (values $fabric_status->%*) {
+ $network_status->{"fabric/$fabric->{network}"} = $fabric;
+ }
+
+ my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
+ for my $id (sort keys $zone_status->%*) {
+ my $zone = $zone_status->{$id};
+
+ $zone->{'network-type'} = 'zone';
+ $zone->{network} = $id;
+ $zone->{type} = 'network';
+
+ $network_status->{"zone/$id"} = $zone;
+ }
+
+ PVE::Cluster::broadcast_node_kv("network", encode_json($network_status));
+}
+
my $broadcast_version_info_done = 0;
my sub broadcast_version_info : prototype() {
if (
@@ -840,6 +863,10 @@ sub update_status {
$err = $@;
syslog('err', "sdn status update error: $err") if $err;
+ eval { update_network_status(); };
+ $err = $@;
+ syslog('err', "network status update error: $err") if $err;
+
eval { broadcast_version_info(); };
$err = $@;
syslog('err', "version info update error: $err") if $err;
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 04/10] api: cluster: add support for network resource type
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (13 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 03/10] pvestatd: add network resource to status reporting Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 05/10] pvestatd: sdn: adapt to changes in status reporting Stefan Hanreich
` (6 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
pvestatd now broadcasts a new network resource type, instead of the
sdn resource type. This commit adds handling for this new network type
to the resources endpoint. In order to be able to deal with older
nodes, keep support for parsing the old sdn resource type.
Upgraded nodes will still broadcast the old format for
backwards-compatibility and nodes with this patch applied support
handling both formats. With this patch, nodes will check whether a
node is sending both formats or only the old one, and parse the
resources based on that information. Older nodes will drop the new
network resource type, but will still be able to show zones, because
the old format still gets broadcast. Newer nodes will take the
information from the network store, if available, otherwise fall back
to the SDN store.
Another reason for keeping the old format around is so we do not break
older clients, that rely on the old SDN format - removing it would be
a breaking API change.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
PVE/API2/Cluster.pm | 106 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 88 insertions(+), 18 deletions(-)
diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
index 479803960..eb9ddcc39 100644
--- a/PVE/API2/Cluster.pm
+++ b/PVE/API2/Cluster.pm
@@ -222,6 +222,32 @@ __PACKAGE__->register_method({
},
});
+my sub can_access_network {
+ my ($rpcenv, $network) = @_;
+ my $authuser = $rpcenv->get_user();
+
+ if ($network->{'network-type'} eq 'fabric') {
+ return $rpcenv->check_any(
+ $authuser,
+ "/sdn/fabrics/$network->{network}",
+ ['SDN.Audit', 'SDN.Allocate'],
+ 1,
+ );
+ } elsif ($network->{'network-type'} eq 'zone') {
+ return $rpcenv->check(
+ $authuser,
+ "/sdn/zones/$network->{network}",
+ ['SDN.Audit'],
+ 1,
+ );
+ }
+
+ # unknown type, so most likely introduced in a newer
+ # version - avoid leaking information by suppressing any
+ # unknown sdn types in the returned array.
+ return 0;
+}
+
__PACKAGE__->register_method({
name => 'resources',
path => 'resources',
@@ -251,7 +277,8 @@ __PACKAGE__->register_method({
type => {
description => "Resource type.",
type => 'string',
- enum => ['node', 'storage', 'pool', 'qemu', 'lxc', 'openvz', 'sdn'],
+ enum =>
+ ['node', 'storage', 'pool', 'qemu', 'lxc', 'openvz', 'sdn', 'network'],
},
status => {
description => "Resource type dependent status.",
@@ -431,6 +458,23 @@ __PACKAGE__->register_method({
optional => 1,
default => 0,
},
+ network => {
+ description => "The name of a Network entity (for type 'network').",
+ type => "string",
+ optional => 1,
+ },
+ 'network-type' => {
+ description => "The type of network resource (for type 'network').",
+ type => "string",
+ enum => ["fabric", "zone"],
+ optional => 1,
+ },
+ protocol => {
+ description =>
+ "The protocol of a fabric (for type 'network', network-type 'fabric').",
+ type => "string",
+ optional => 1,
+ },
},
},
},
@@ -584,25 +628,15 @@ __PACKAGE__->register_method({
}
if (!$param->{type} || $param->{type} eq 'sdn') {
- #add default "localnetwork" zone
- if ($rpcenv->check($authuser, "/sdn/zones/localnetwork", ['SDN.Audit'], 1)) {
- foreach my $node (@$nodelist) {
- my $local_sdn = {
- id => "sdn/$node/localnetwork",
- sdn => 'localnetwork',
- node => $node,
- type => 'sdn',
- status => 'ok',
- };
- push @$res, $local_sdn;
- }
- }
+ my $nodes = PVE::Cluster::get_node_kv("sdn");
+ my $network_nodes = PVE::Cluster::get_node_kv("network");
- if ($have_sdn) {
- my $nodes = PVE::Cluster::get_node_kv("sdn");
+ for my $node (sort keys %{$nodes}) {
+ # host is already sending the new network resource, so ignore
+ # its sdn resources
+ next if defined $network_nodes->{$node};
- for my $node (sort keys %{$nodes}) {
- my $sdns = decode_json($nodes->{$node});
+ my $sdns = decode_json($nodes->{$node});
for my $id (sort keys %{$sdns}) {
next if !$rpcenv->check($authuser, "/sdn/zones/$id", ['SDN.Audit'], 1);
@@ -620,6 +654,42 @@ __PACKAGE__->register_method({
}
}
+ if (!$param->{type} || $param->{type} eq 'network') {
+ my $nodes = PVE::Cluster::get_node_kv("network");
+
+ # add default "localnetwork" zone
+ if ($rpcenv->check($authuser, "/sdn/zones/localnetwork", ['SDN.Audit'], 1)) {
+ foreach my $node (@$nodelist) {
+ my $local_sdn = {
+ id => "network/$node/zone/localnetwork",
+ type => 'network',
+ 'network-type' => 'zone',
+ network => 'localnetwork',
+ node => $node,
+ status => 'ok',
+ };
+ push $res->@*, $local_sdn;
+ }
+ }
+
+ for my $node (sort keys $nodes->%*) {
+ my $node_config = decode_json($nodes->{$node});
+
+ for my $id (sort keys $node_config->%*) {
+ my $entry = $node_config->{$id};
+
+ next if !can_access_network($rpcenv, $entry);
+
+ push $res->@*,
+ {
+ "id" => "network/$node/$entry->{'network-type'}/$entry->{network}",
+ "node" => $node,
+ $entry->%*,
+ };
+ }
+ }
+ }
+
return $res;
},
});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 05/10] pvestatd: sdn: adapt to changes in status reporting
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (14 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 04/10] api: cluster: add support for network resource type Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 06/10] ui: resource tree: add network resource Stefan Hanreich
` (5 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
Since pve-network now includes the fabric status in its top-level
status function call (SDN::status), move pvestatd over to use the
zone-specific function for generating SDN resources instead.
Additionally, the zone_type field has been added in the output of the
zone status, so broadcast and return that field as well. Main use-case
for now is discerning the type of zones, to decide which panels to
show in the SDN browser.
Also, the have_sdn guard can be removed since SDN is pre-installed and
therefore the guard is no longer needed.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
PVE/API2/Cluster.pm | 31 +++++++++++++++++++------------
PVE/Service/pvestatd.pm | 16 ++++------------
2 files changed, 23 insertions(+), 24 deletions(-)
diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
index eb9ddcc39..4f41a005c 100644
--- a/PVE/API2/Cluster.pm
+++ b/PVE/API2/Cluster.pm
@@ -469,6 +469,11 @@ __PACKAGE__->register_method({
enum => ["fabric", "zone"],
optional => 1,
},
+ 'zone-type' => {
+ description => "The type of an SDN zone (for type 'sdn').",
+ type => "string",
+ optional => 1,
+ },
protocol => {
description =>
"The protocol of a fabric (for type 'network', network-type 'fabric').",
@@ -638,18 +643,20 @@ __PACKAGE__->register_method({
my $sdns = decode_json($nodes->{$node});
- for my $id (sort keys %{$sdns}) {
- next if !$rpcenv->check($authuser, "/sdn/zones/$id", ['SDN.Audit'], 1);
- my $sdn = $sdns->{$id};
- my $entry = {
- id => "sdn/$node/$id",
- sdn => $id,
- node => $node,
- type => 'sdn',
- status => $sdn->{'status'},
- };
- push @$res, $entry;
- }
+ for my $id (sort keys %{$sdns}) {
+ next if !$rpcenv->check($authuser, "/sdn/zones/$id", ['SDN.Audit'], 1);
+ my $sdn = $sdns->{$id};
+ my $entry = {
+ id => "sdn/$node/$id",
+ sdn => $id,
+ node => $node,
+ type => 'sdn',
+ status => $sdn->{'status'},
+ };
+
+ $entry->{'zone-type'} = $sdn->{'zone-type'} if defined($sdn->{'zone-type'});
+
+ push @$res, $entry;
}
}
}
diff --git a/PVE/Service/pvestatd.pm b/PVE/Service/pvestatd.pm
index 572eb7eb5..98d421f48 100755
--- a/PVE/Service/pvestatd.pm
+++ b/PVE/Service/pvestatd.pm
@@ -15,6 +15,7 @@ use PVE::CpuSet;
use Filesys::Df;
use PVE::INotify;
use PVE::Network;
+use PVE::Network::SDN::Zones;
use PVE::RS::SDN::Fabrics;
use PVE::NodeConfig;
use PVE::Cluster qw(cfs_read_file);
@@ -38,12 +39,6 @@ use PVE::Status::Plugin;
use base qw(PVE::Daemon);
-my $have_sdn;
-eval {
- require PVE::Network::SDN;
- $have_sdn = 1;
-};
-
my $opt_debug;
my $restart_request;
@@ -767,13 +762,10 @@ sub update_ceph_metadata {
}
sub update_sdn_status {
+ my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
- if ($have_sdn) {
- my ($transport_status, $vnet_status) = PVE::Network::SDN::status();
-
- my $status = $transport_status ? encode_json($transport_status) : undef;
- PVE::Cluster::broadcast_node_kv("sdn", $status);
- }
+ my $status = $zone_status ? encode_json($zone_status) : undef;
+ PVE::Cluster::broadcast_node_kv("sdn", $status);
}
sub update_network_status {
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 06/10] ui: resource tree: add network resource
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (15 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 05/10] pvestatd: sdn: adapt to changes in status reporting Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 07/10] ui: network browser: Add ip-vrf panel for evpn zones Stefan Hanreich
` (4 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
From: Gabriel Goller <g.goller@proxmox.com>
Add the newly introduced network resource to the resource tree, so the
the status of network resources 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 old SDN browser is
still kept around, so the UI can handle nodes that are still sending
the old sdn resource type.
Co-authored-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/Makefile | 2 +
www/manager6/Utils.js | 12 ++
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, 265 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..a8f2925c1 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1276,6 +1276,13 @@ Ext.define('PVE.Utils', {
// templates
objType = 'template';
status = type;
+ } else if (type === 'network') {
+ const networkTypeMapping = {
+ fabric: 'fa fa-road',
+ zone: 'fa fa-th',
+ };
+
+ return networkTypeMapping[record['network-type']] ?? '';
} else if (type === 'storage' && record.content === 'import') {
return 'fa fa-cloud-download';
} else {
@@ -1299,6 +1306,11 @@ Ext.define('PVE.Utils', {
var cls = PVE.Utils.get_object_icon_class(value, record.data);
var fa = '<i class="fa-fw x-grid-icon-custom ' + cls + '"></i> ';
+
+ 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 60c499cbb..51fb2d817 100644
--- a/www/manager6/Workspace.js
+++ b/www/manager6/Workspace.js
@@ -252,6 +252,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('<br>');
+ }
+ 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..f94b27d35
--- /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 (!networkType) {
+ throw 'no type specified';
+ }
+
+ 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 68611a420..770f75559 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'),
@@ -88,6 +92,8 @@ Ext.define('PVE.tree.ResourceTree', {
return 2;
case 'sdn':
return 3;
+ case 'network':
+ return 3.5;
case 'storage':
return 4;
default:
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 07/10] ui: network browser: Add ip-vrf panel for evpn zones
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (16 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 06/10] ui: resource tree: add network resource Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 08/10] ui: network browser: add mac vrf panel Stefan Hanreich
` (3 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This panel shows the full state of the VRF of an EVPN zone on a given
node. It is integrated into the Network browser and only shown for
EVPN zones.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/sdn/Browser.js | 11 ++++
www/manager6/sdn/EvpnZoneIpVrfPanel.js | 84 ++++++++++++++++++++++++++
3 files changed, 96 insertions(+)
create mode 100644 www/manager6/sdn/EvpnZoneIpVrfPanel.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index ba762578e..6abc77469 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -290,6 +290,7 @@ JSSRC= \
sdn/SubnetView.js \
sdn/ZoneContentView.js \
sdn/ZoneContentPanel.js \
+ sdn/EvpnZoneIpVrfPanel.js \
sdn/FirewallPanel.js \
sdn/FirewallVnetView.js \
sdn/ZoneView.js \
diff --git a/www/manager6/sdn/Browser.js b/www/manager6/sdn/Browser.js
index f7694ae91..c55d6296b 100644
--- a/www/manager6/sdn/Browser.js
+++ b/www/manager6/sdn/Browser.js
@@ -48,6 +48,17 @@ Ext.define('PVE.sdn.Browser', {
});
}
+ if (me.pveSelNode.data['zone-type'] && me.pveSelNode.data['zone-type'] === 'evpn') {
+ me.items.push({
+ nodename: nodename,
+ zone: sdnId,
+ xtype: 'pveSDNEvpnZoneIpVrfPanel',
+ title: gettext('IP-VRF'),
+ iconCls: 'fa fa-th-list',
+ itemId: 'ip-vrf',
+ });
+ }
+
me.callParent();
},
});
diff --git a/www/manager6/sdn/EvpnZoneIpVrfPanel.js b/www/manager6/sdn/EvpnZoneIpVrfPanel.js
new file mode 100644
index 000000000..2b9ded537
--- /dev/null
+++ b/www/manager6/sdn/EvpnZoneIpVrfPanel.js
@@ -0,0 +1,84 @@
+Ext.define('IpVrfRoute', {
+ extend: 'Ext.data.Model',
+ fields: ['ip', 'metric', 'nexthops', 'protocol'],
+});
+
+Ext.define('PVE.sdn.EvpnZoneIpVrfPanel', {
+ extend: 'Ext.grid.GridPanel',
+ alias: 'widget.pveSDNEvpnZoneIpVrfPanel',
+
+ title: gettext('IP-VRF'),
+ onlineHelp: 'pvesdn_zone_plugin_evpn',
+
+ stateful: true,
+ stateId: 'grid-sdn-ip-vrf',
+
+ columns: [
+ {
+ text: gettext('CIDR'),
+ flex: 2,
+ sortable: true,
+ dataIndex: 'ip',
+ },
+ {
+ text: gettext('Nexthop'),
+ flex: 3,
+ dataIndex: 'nexthops',
+ renderer: (value) => {
+ if (Ext.isArray(value)) {
+ return value.join('<br>');
+ }
+ return value || '';
+ },
+ },
+ {
+ text: gettext('Protocol'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'protocol',
+ },
+ {
+ text: gettext('Metric'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'metric',
+ },
+ ],
+
+ initComponent: function () {
+ let me = this;
+
+ let store = new Ext.data.Store({
+ model: 'IpVrfRoute',
+ proxy: {
+ type: 'proxmox',
+ url: `/api2/json/nodes/${me.nodename}/sdn/zones/${me.zone}/ip-vrf`,
+ reader: {
+ type: 'json',
+ rootProperty: 'data',
+ },
+ },
+ sorters: [
+ {
+ property: 'ip',
+ direction: 'ASC',
+ },
+ {
+ property: 'nexthop',
+ direction: 'ASC',
+ },
+ {
+ property: 'metric',
+ direction: 'ASC',
+ },
+ ],
+ autoLoad: true,
+ });
+
+ Ext.apply(me, {
+ store,
+ });
+
+ me.callParent();
+ },
+});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 08/10] ui: network browser: add mac vrf panel
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (17 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 07/10] ui: network browser: Add ip-vrf panel for evpn zones Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 09/10] ui: network browser: add zone bridge view Stefan Hanreich
` (2 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This panel shows the full state of the neighbor table of an EVPN vnet.
It is integrated into the SDN browser and only shown for EVPN zones.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/Makefile | 1 +
www/manager6/sdn/Browser.js | 9 ++
www/manager6/sdn/EvpnZoneMacVrfPanel.js | 130 ++++++++++++++++++++++++
3 files changed, 140 insertions(+)
create mode 100644 www/manager6/sdn/EvpnZoneMacVrfPanel.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 6abc77469..3f7125e1f 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -291,6 +291,7 @@ JSSRC= \
sdn/ZoneContentView.js \
sdn/ZoneContentPanel.js \
sdn/EvpnZoneIpVrfPanel.js \
+ sdn/EvpnZoneMacVrfPanel.js \
sdn/FirewallPanel.js \
sdn/FirewallVnetView.js \
sdn/ZoneView.js \
diff --git a/www/manager6/sdn/Browser.js b/www/manager6/sdn/Browser.js
index c55d6296b..840105d3d 100644
--- a/www/manager6/sdn/Browser.js
+++ b/www/manager6/sdn/Browser.js
@@ -57,6 +57,15 @@ Ext.define('PVE.sdn.Browser', {
iconCls: 'fa fa-th-list',
itemId: 'ip-vrf',
});
+
+ me.items.push({
+ nodename: nodename,
+ zone: sdnId,
+ xtype: 'pveSDNEvpnZoneMacVrfPanel',
+ title: gettext('MAC-VRFs'),
+ iconCls: 'fa fa-th-list',
+ itemId: 'mac-vrfs',
+ });
}
me.callParent();
diff --git a/www/manager6/sdn/EvpnZoneMacVrfPanel.js b/www/manager6/sdn/EvpnZoneMacVrfPanel.js
new file mode 100644
index 000000000..0984fdbdc
--- /dev/null
+++ b/www/manager6/sdn/EvpnZoneMacVrfPanel.js
@@ -0,0 +1,130 @@
+Ext.define('PVE.sdn.EvpnZoneMacVrfPanel', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.pveSDNEvpnZoneMacVrfPanel',
+
+ title: 'MAC-VRFs',
+ onlineHelp: 'pvesdn_zone_plugin_evpn',
+
+ initComponent: function () {
+ var me = this;
+ let nodename = me.nodename;
+
+ var mac_vrf_panel = Ext.createWidget('pveSDNEvpnZoneMacVrfGridPanel', {
+ title: gettext('VNet MAC-VRF'),
+ region: 'center',
+ border: false,
+ });
+
+ var vnetview_panel = Ext.createWidget('pveSDNZoneContentView', {
+ title: gettext('VNets'),
+ region: 'west',
+ sub_panel: mac_vrf_panel,
+ nodename: me.nodename,
+ zone: me.zone,
+
+ width: '50%',
+ border: false,
+ split: true,
+
+ on_select: function (_sm, rec) {
+ mac_vrf_panel.setVnet(rec.data.vnet, nodename);
+ },
+
+ on_deselect: function () {
+ mac_vrf_panel.clearVnet();
+ },
+ });
+
+ Ext.apply(me, {
+ layout: 'border',
+ items: [vnetview_panel, mac_vrf_panel],
+ });
+
+ me.callParent();
+ },
+});
+
+Ext.define('MacVrfRoute', {
+ extend: 'Ext.data.Model',
+ fields: ['ip', 'metric', 'nexthops', 'protocol'],
+});
+
+Ext.define('PVE.sdn.EvpnZoneMacVrfGridPanel', {
+ extend: 'Ext.grid.GridPanel',
+ alias: 'widget.pveSDNEvpnZoneMacVrfGridPanel',
+
+ title: gettext('MAC-VRF'),
+
+ stateful: true,
+ stateId: 'grid-sdn-mac-vrf',
+
+ columns: [
+ {
+ text: gettext('IP'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'ip',
+ },
+ {
+ text: gettext('MAC-Address'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'mac',
+ },
+ {
+ text: gettext('Nexthop'),
+ flex: 1,
+ dataIndex: 'nexthop',
+ },
+ ],
+
+ clearVnet: function () {
+ let me = this;
+
+ me.getStore().removeAll();
+ },
+
+ setVnet: function (vnet, node) {
+ let me = this;
+
+ let store = me.getStore();
+
+ store.getProxy().setUrl(`/api2/json/nodes/${node}/sdn/vnets/${vnet}/mac-vrf`);
+ store.load();
+ },
+
+ initComponent: function () {
+ let me = this;
+
+ let store = new Ext.data.Store({
+ model: 'MacVrfRoute',
+ proxy: {
+ type: 'proxmox',
+ reader: {
+ type: 'json',
+ rootProperty: 'data',
+ },
+ },
+ sorters: [
+ {
+ property: 'ip',
+ direction: 'ASC',
+ },
+ {
+ property: 'mac',
+ direction: 'ASC',
+ },
+ {
+ property: 'nexthop',
+ direction: 'ASC',
+ },
+ ],
+ });
+
+ Ext.apply(me, {
+ store,
+ });
+
+ me.callParent();
+ },
+});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 09/10] ui: network browser: add zone bridge view
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (18 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 08/10] ui: network browser: add mac vrf panel Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 10/10] ui: sdn: status view: adapt to new network resource Stefan Hanreich
2025-11-14 1:07 ` [pve-devel] applied: [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Thomas Lamprecht
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
This shows a list of all bridges, that are part of an SDN zone
(including the pseudo localnetwork zone, that corresponds to the local
network of a node). It also shows additional information about which
ports are currently members of the bridge, as well as their VLAN
configuration and which guest they belong to.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/Makefile | 2 +
www/manager6/sdn/ZoneBridgeView.js | 88 ++++++++++++++++++
www/manager6/sdn/ZoneBridgesPanel.js | 131 +++++++++++++++++++++++++++
3 files changed, 221 insertions(+)
create mode 100644 www/manager6/sdn/ZoneBridgeView.js
create mode 100644 www/manager6/sdn/ZoneBridgesPanel.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 3f7125e1f..68c3f4457 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -290,6 +290,8 @@ JSSRC= \
sdn/SubnetView.js \
sdn/ZoneContentView.js \
sdn/ZoneContentPanel.js \
+ sdn/ZoneBridgesPanel.js \
+ sdn/ZoneBridgeView.js \
sdn/EvpnZoneIpVrfPanel.js \
sdn/EvpnZoneMacVrfPanel.js \
sdn/FirewallPanel.js \
diff --git a/www/manager6/sdn/ZoneBridgeView.js b/www/manager6/sdn/ZoneBridgeView.js
new file mode 100644
index 000000000..316ce86f2
--- /dev/null
+++ b/www/manager6/sdn/ZoneBridgeView.js
@@ -0,0 +1,88 @@
+Ext.define('ZoneBridge', {
+ extend: 'Ext.data.Model',
+ fields: ['name', 'vlan_filtering', 'ports'],
+});
+
+Ext.define('PVE.sdn.ZoneBridgeView', {
+ extend: 'Ext.grid.GridPanel',
+ alias: 'widget.pveSDNZoneBridgeView',
+
+ stateful: true,
+ stateId: 'grid-sdnzone-bridges',
+
+ viewConfig: {
+ trackOver: false,
+ loadMask: false,
+ },
+
+ columns: [
+ {
+ header: gettext('Bridge'),
+ width: 100,
+ sortable: true,
+ dataIndex: 'name',
+ flex: 1,
+ },
+ {
+ header: gettext('VLAN-aware'),
+ width: 300,
+ sortable: true,
+ dataIndex: 'vlan_filtering',
+ flex: 1,
+ renderer: function (value) {
+ return value === 1 ? gettext('Yes') : gettext('No');
+ },
+ },
+ ],
+
+ on_select: function (selectionModel, record) {
+ // do nothing by default
+ },
+
+ on_deselect: function () {
+ // do nothing by default
+ },
+
+ initComponent: function () {
+ var me = this;
+
+ if (!me.nodename) {
+ throw 'no node name specified';
+ }
+
+ if (!me.zone) {
+ throw 'no zone ID specified';
+ }
+
+ let baseUrl = `/nodes/${me.nodename}/sdn/zones/${me.zone}/bridges`;
+
+ let store = Ext.create('Ext.data.Store', {
+ model: 'ZoneBridge',
+ proxy: {
+ type: 'proxmox',
+ url: '/api2/json' + baseUrl,
+ },
+ sorters: {
+ property: 'name',
+ direction: 'ASC',
+ },
+ });
+
+ let reload = function () {
+ store.load();
+ };
+
+ Proxmox.Utils.monStoreErrors(me, store);
+ Ext.apply(me, {
+ store: store,
+ listeners: {
+ activate: reload,
+ show: reload,
+ select: me.on_select,
+ deselect: me.on_deselect,
+ },
+ });
+ store.load();
+ me.callParent();
+ },
+});
diff --git a/www/manager6/sdn/ZoneBridgesPanel.js b/www/manager6/sdn/ZoneBridgesPanel.js
new file mode 100644
index 000000000..600b23b0a
--- /dev/null
+++ b/www/manager6/sdn/ZoneBridgesPanel.js
@@ -0,0 +1,131 @@
+Ext.define('PVE.sdn.ZoneBridgePanel', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.pveSDNZoneBridgePanel',
+
+ title: gettext('Bridges'),
+ onlineHelp: 'pvesdn_zone_plugin_evpn',
+
+ stateful: true,
+ stateId: 'grid-sdn-zone-bridges',
+
+ initComponent: function () {
+ var me = this;
+ let nodename = me.nodename;
+
+ var bridge_ports_panel = Ext.createWidget('pveSDNZoneBridgePortsPanel', {
+ title: gettext('Bridge Ports'),
+ region: 'center',
+ border: false,
+ });
+
+ var vnetview_panel = Ext.createWidget('pveSDNZoneBridgeView', {
+ title: gettext('VNets'),
+ region: 'west',
+ nodename: me.nodename,
+ zone: me.zone,
+
+ width: '50%',
+ border: false,
+ split: true,
+
+ on_select: function (_sm, rec) {
+ let deepCopy = structuredClone(rec.data.ports);
+ bridge_ports_panel.setPorts(deepCopy, nodename);
+ },
+
+ on_deselect: function () {
+ bridge_ports_panel.clearPorts();
+ },
+ });
+
+ Ext.apply(me, {
+ layout: 'border',
+ items: [vnetview_panel, bridge_ports_panel],
+ });
+
+ me.callParent();
+ },
+});
+
+Ext.define('ZoneBridgePort', {
+ extend: 'Ext.data.Model',
+ fields: ['index', 'name', 'primary_vlan', 'vlans', 'vmid'],
+});
+
+Ext.define('PVE.sdn.ZoneBridgePortsPanel', {
+ extend: 'Ext.grid.GridPanel',
+ alias: 'widget.pveSDNZoneBridgePortsPanel',
+
+ title: gettext('IP-VRF'),
+ onlineHelp: 'pvesdn_zone_plugin_evpn',
+
+ stateful: true,
+ stateId: 'grid-sdn-zone-ports',
+
+ columns: [
+ {
+ text: gettext('Name'),
+ flex: 2,
+ sortable: true,
+ dataIndex: 'name',
+ },
+ {
+ text: gettext('VMID'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'vmid',
+ },
+ {
+ text: gettext('Network Device Index'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'index',
+ },
+ {
+ text: gettext('Primary VLAN'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'primary_vlan',
+ },
+ {
+ text: gettext('VLANs'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'vlans',
+ },
+ ],
+
+ initComponent: function () {
+ let me = this;
+
+ let store = new Ext.data.Store({
+ model: 'ZoneBridge',
+ sorters: [
+ {
+ property: 'vmid',
+ direction: 'ASC',
+ },
+ {
+ property: 'index',
+ direction: 'ASC',
+ },
+ ],
+ });
+
+ Ext.apply(me, {
+ store,
+ });
+
+ me.callParent();
+ },
+
+ setPorts: function (ports) {
+ let me = this;
+ me.getStore().setData(ports);
+ },
+
+ clearPorts: function (ports) {
+ let me = this;
+ me.getStore().removeAll();
+ },
+});
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] [PATCH pve-manager v4 10/10] ui: sdn: status view: adapt to new network resource
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (19 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 09/10] ui: network browser: add zone bridge view Stefan Hanreich
@ 2025-11-13 16:19 ` Stefan Hanreich
2025-11-14 1:07 ` [pve-devel] applied: [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Thomas Lamprecht
21 siblings, 0 replies; 23+ messages in thread
From: Stefan Hanreich @ 2025-11-13 16:19 UTC (permalink / raw)
To: pve-devel
Adapt the SDN status overview to use the new network resource over the
old SDN resource type. Also display the network_type field in addition
to the existing fields - so users can discern between different types
of network entities.
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
www/manager6/sdn/StatusView.js | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/www/manager6/sdn/StatusView.js b/www/manager6/sdn/StatusView.js
index dd05c73fd..fbc712c6c 100644
--- a/www/manager6/sdn/StatusView.js
+++ b/www/manager6/sdn/StatusView.js
@@ -33,7 +33,7 @@ Ext.define(
],
filters: {
property: 'type',
- value: 'sdn',
+ value: 'network',
operator: '==',
},
});
@@ -77,13 +77,18 @@ Ext.define(
{
header: 'SDN',
width: 80,
- dataIndex: 'sdn',
+ dataIndex: 'network',
},
{
header: gettext('Node'),
width: 80,
dataIndex: 'node',
},
+ {
+ header: gettext('Type'),
+ width: 80,
+ dataIndex: 'network-type',
+ },
{
header: gettext('Status'),
width: 80,
@@ -102,7 +107,7 @@ Ext.define(
function () {
Ext.define('pve-sdn-status', {
extend: 'Ext.data.Model',
- fields: ['id', 'type', 'node', 'status', 'sdn'],
+ fields: ['id', 'type', 'node', 'status', 'network'],
idProperty: 'id',
});
},
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [pve-devel] applied: [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
` (20 preceding siblings ...)
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 10/10] ui: sdn: status view: adapt to new network resource Stefan Hanreich
@ 2025-11-14 1:07 ` Thomas Lamprecht
21 siblings, 0 replies; 23+ messages in thread
From: Thomas Lamprecht @ 2025-11-14 1:07 UTC (permalink / raw)
To: Proxmox VE development discussion, Stefan Hanreich
Am 13.11.25 um 17:19 schrieb Stefan Hanreich:> proxmox-perl-rs:
>
> Stefan Hanreich (2):
> pve-rs: update proxmox-frr dependency
> pve-rs: sdn status: rename network_type to network-type
>
> pve-rs/Cargo.toml | 2 +-
> pve-rs/debian/control | 2 +-
> pve-rs/src/sdn/status.rs | 1 +
> 3 files changed, 3 insertions(+), 2 deletions(-)
>
>
> pve-network:
>
> Gabriel Goller (3):
> fabrics: add fabrics status to SDN::status function
> api: nodes: fabrics: add endpoint for querying route status
> api: nodes: fabrics: add endpoint for querying neighbor information
>
> Stefan Hanreich (6):
> refactor: rework api module structure for the /nodes/{node}/sdn subdir
> sdn: status: add zone type to sdn resource
> api: nodes: fabrics: add endpoint for querying interface status
> api: nodes: zones: add bridge status
> api: nodes: zones: add ip vrf endpoint for evpn zones
> api: nodes: vnets: add mac-vrf endpoint for evpn vnets
>
> src/PVE/API2/Network/SDN/Makefile | 2 +-
> src/PVE/API2/Network/SDN/Nodes/Fabric.pm | 187 +++++++++
> src/PVE/API2/Network/SDN/Nodes/Fabrics.pm | 16 +
> .../Network/SDN/{Zones => Nodes}/Makefile | 12 +-
> src/PVE/API2/Network/SDN/Nodes/Status.pm | 61 +++
> src/PVE/API2/Network/SDN/Nodes/Vnet.pm | 147 +++++++
> src/PVE/API2/Network/SDN/Nodes/Vnets.pm | 16 +
> src/PVE/API2/Network/SDN/Nodes/Zone.pm | 379 ++++++++++++++++++
> .../SDN/{Zones/Status.pm => Nodes/Zones.pm} | 58 +--
> src/PVE/API2/Network/SDN/Vnets.pm | 2 +-
> src/PVE/API2/Network/SDN/Zones/Content.pm | 88 ----
> src/PVE/Network/SDN.pm | 6 +-
> src/PVE/Network/SDN/Zones.pm | 2 +
> src/test/debug/statuscheck.pl | 3 +-
> 14 files changed, 833 insertions(+), 146 deletions(-)
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabric.pm
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Fabrics.pm
> rename src/PVE/API2/Network/SDN/{Zones => Nodes}/Makefile (51%)
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Status.pm
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnet.pm
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Vnets.pm
> create mode 100644 src/PVE/API2/Network/SDN/Nodes/Zone.pm
> rename src/PVE/API2/Network/SDN/{Zones/Status.pm => Nodes/Zones.pm} (56%)
> delete mode 100644 src/PVE/API2/Network/SDN/Zones/Content.pm
>
>
> pve-manager:
>
> Gabriel Goller (2):
> pvestatd: add network resource to status reporting
> ui: resource tree: add network resource
>
> Stefan Hanreich (8):
> api: nodes: use new status module for sdn subdirectory
> refactor: ui: sdn browser: parametrize zone content panel
> api: cluster: add support for network resource type
> pvestatd: sdn: adapt to changes in status reporting
> ui: network browser: Add ip-vrf panel for evpn zones
> ui: network browser: add mac vrf panel
> ui: network browser: add zone bridge view
> ui: sdn: status view: adapt to new network resource
>
> PVE/API2/Cluster.pm | 123 +++++++++++++----
> PVE/API2/Nodes.pm | 50 +------
> PVE/Service/pvestatd.pm | 39 ++++--
> www/manager6/Makefile | 6 +
> www/manager6/Utils.js | 12 ++
> www/manager6/Workspace.js | 1 +
> www/manager6/sdn/Browser.js | 20 +++
> www/manager6/sdn/EvpnZoneIpVrfPanel.js | 84 ++++++++++++
> www/manager6/sdn/EvpnZoneMacVrfPanel.js | 130 ++++++++++++++++++
> www/manager6/sdn/FabricsContentView.js | 77 +++++++++++
> www/manager6/sdn/NetworkBrowser.js | 167 ++++++++++++++++++++++++
> www/manager6/sdn/StatusView.js | 11 +-
> www/manager6/sdn/ZoneBridgeView.js | 88 +++++++++++++
> www/manager6/sdn/ZoneBridgesPanel.js | 131 +++++++++++++++++++
> www/manager6/sdn/ZoneContentPanel.js | 11 +-
> www/manager6/sdn/ZoneContentView.js | 75 ++++++-----
> www/manager6/tree/ResourceTree.js | 6 +
> 17 files changed, 914 insertions(+), 117 deletions(-)
> create mode 100644 www/manager6/sdn/EvpnZoneIpVrfPanel.js
> create mode 100644 www/manager6/sdn/EvpnZoneMacVrfPanel.js
> create mode 100644 www/manager6/sdn/FabricsContentView.js
> create mode 100644 www/manager6/sdn/NetworkBrowser.js
> create mode 100644 www/manager6/sdn/ZoneBridgeView.js
> create mode 100644 www/manager6/sdn/ZoneBridgesPanel.js
>
>
> Summary over all repositories:
> 34 files changed, 1750 insertions(+), 265 deletions(-)
>
applied series, nice stuff, many thanks!
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-11-14 1:07 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-13 16:19 [pve-devel] [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 1/2] pve-rs: update proxmox-frr dependency Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH proxmox-perl-rs v4 2/2] pve-rs: sdn status: rename network_type to network-type Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 1/9] refactor: rework api module structure for the /nodes/{node}/sdn subdir Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 2/9] fabrics: add fabrics status to SDN::status function Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 3/9] sdn: status: add zone type to sdn resource Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 4/9] api: nodes: fabrics: add endpoint for querying route status Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 5/9] api: nodes: fabrics: add endpoint for querying neighbor information Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 6/9] api: nodes: fabrics: add endpoint for querying interface status Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 7/9] api: nodes: zones: add bridge status Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 8/9] api: nodes: zones: add ip vrf endpoint for evpn zones Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-network v4 9/9] api: nodes: vnets: add mac-vrf endpoint for evpn vnets Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 01/10] api: nodes: use new status module for sdn subdirectory Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 02/10] refactor: ui: sdn browser: parametrize zone content panel Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 03/10] pvestatd: add network resource to status reporting Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 04/10] api: cluster: add support for network resource type Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 05/10] pvestatd: sdn: adapt to changes in status reporting Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 06/10] ui: resource tree: add network resource Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 07/10] ui: network browser: Add ip-vrf panel for evpn zones Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 08/10] ui: network browser: add mac vrf panel Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 09/10] ui: network browser: add zone bridge view Stefan Hanreich
2025-11-13 16:19 ` [pve-devel] [PATCH pve-manager v4 10/10] ui: sdn: status view: adapt to new network resource Stefan Hanreich
2025-11-14 1:07 ` [pve-devel] applied: [PATCH manager/network/proxmox-perl-rs v4 00/21] Improve status reporting for SDN / networking Thomas Lamprecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox