summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Hanreich <s.hanreich@proxmox.com>2025-07-16 15:08:14 +0200
committerThomas Lamprecht <t.lamprecht@proxmox.com>2025-07-17 00:10:48 +0200
commit472f28f924de9253acaef70a9cb78ff3869d577a (patch)
tree30f51dcb914a7d431aa7bdba4ea5894c26d985dc /src
parent9794f3a7de8863d182f24b5fa676b8ad376cc26d (diff)
zone: vxlan: add fabrics integration
Add a new property to the VXLAN zone, that can contain the name of a fabric. This automatically generates the peer-list from the fabric, instead of having to manually write a comma-separated IP list. This changes the peer field to optional from required. Either the peers or the fabric field needs to be set, and this is now validated in the update hook of the VXLAN zone. Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com> Link: https://lore.proxmox.com/20250716130837.585796-54-g.goller@proxmox.com
Diffstat (limited to 'src')
-rw-r--r--src/PVE/API2/Network/SDN/Fabrics/Fabric.pm9
-rw-r--r--src/PVE/Network/SDN/Zones/VxlanPlugin.pm61
2 files changed, 64 insertions, 6 deletions
diff --git a/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm b/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm
index d59b134..8c47b1b 100644
--- a/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm
+++ b/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm
@@ -237,6 +237,15 @@ __PACKAGE__->register_method({
}
}
+ # check if this fabric is used in a vxlan zone
+ my $zone_cfg = PVE::Network::SDN::Zones::config();
+ for my $key (keys %{ $zone_cfg->{ids} }) {
+ my $zone = $zone_cfg->{ids}->{$key};
+ if ($zone->{type} eq "vxlan" && $zone->{fabric} eq $id) {
+ die "this fabric is still used in the VXLAN zone \"$key\"";
+ }
+ }
+
my $digest = extract_param($param, 'digest');
PVE::Tools::assert_if_modified($config->digest(), $digest) if $digest;
diff --git a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
index 018d412..8f6fba0 100644
--- a/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/src/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -31,6 +31,11 @@ sub properties {
type => 'string',
format => 'ip-list',
},
+ fabric => {
+ description => "SDN fabric to use as underlay for this VXLAN zone.",
+ type => 'string',
+ format => 'pve-sdn-fabric-id',
+ },
'vxlan-port' => {
description => "Vxlan tunnel udp port (default 4789).",
minimum => 1,
@@ -43,13 +48,14 @@ sub properties {
sub options {
return {
nodes => { optional => 1 },
- peers => { optional => 0 },
+ peers => { optional => 1 },
'vxlan-port' => { optional => 1 },
mtu => { optional => 1 },
dns => { optional => 1 },
reversedns => { optional => 1 },
dnszone => { optional => 1 },
ipam => { optional => 1 },
+ fabric => { optional => 1 },
};
}
@@ -72,17 +78,47 @@ sub generate_sdn_config {
my $alias = $vnet->{alias};
my $multicastaddress = $plugin_config->{'multicast-address'};
my $vxlanport = $plugin_config->{'vxlan-port'};
- my @peers;
- @peers = PVE::Tools::split_list($plugin_config->{'peers'}) if $plugin_config->{'peers'};
my $vxlan_iface = "vxlan_$vnetid";
die "missing vxlan tag" if !$tag;
- my ($ifaceip, $iface) =
- PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
+ my @peers;
+ my $ifaceip;
+ my $iface;
+
+ if ($plugin_config->{peers}) {
+ @peers = PVE::Tools::split_list($plugin_config->{'peers'}) if $plugin_config->{'peers'};
+ ($ifaceip, $iface) =
+ PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
+ } elsif ($plugin_config->{fabric}) {
+ my $local_node = PVE::INotify::nodename();
+ my $config = PVE::Network::SDN::Fabrics::config(1);
+
+ my $fabric = eval { $config->get_fabric($plugin_config->{fabric}) };
+ die "could not configure VXLAN zone $plugin_config->{id}: $@" if $@;
+
+ my $nodes = $config->list_nodes_fabric($plugin_config->{fabric});
+
+ my $current_node = eval { $config->get_node($plugin_config->{fabric}, $local_node) };
+ die "could not configure VXLAN zone $plugin_config->{id}: $@" if $@;
+
+ die
+ "Node $local_node requires an IP in the fabric $fabric->{id} to configure the VXLAN zone $plugin_config->{id}"
+ if !$current_node->{ip};
+
+ for my $node (values %$nodes) {
+ push @peers, $node->{ip} if $node->{ip};
+ }
+
+ $ifaceip = $current_node->{ip};
+ } else {
+ die "neither peers nor fabric configured for VXLAN zone $plugin_config->{id}";
+ }
my $mtu = 1450;
- $mtu = $interfaces_config->{$iface}->{mtu} - 50 if $interfaces_config->{$iface}->{mtu};
+ if ($iface) {
+ $mtu = $interfaces_config->{$iface}->{mtu} - 50 if $interfaces_config->{$iface}->{mtu};
+ }
$mtu = $plugin_config->{mtu} if $plugin_config->{mtu};
#vxlan interface
@@ -114,6 +150,19 @@ sub generate_sdn_config {
return $config;
}
+sub on_update_hook {
+ my ($class, $zoneid, $zone_cfg, $controller_cfg) = @_;
+
+ my $zone = $zone_cfg->{ids}->{$zoneid};
+
+ if (($zone->{peers} && $zone->{fabric}) || !($zone->{peers} || $zone->{fabric})) {
+ raise_param_exc({
+ peers => "must have exactly one of peers / fabric defined",
+ fabric => "must have exactly one of peers / fabric defined",
+ });
+ }
+}
+
sub vnet_update_hook {
my ($class, $vnet_cfg, $vnetid, $zone_cfg) = @_;