[pve-devel] [PATCH pve-network 36/38] zones: auto find controller

Alexandre Derumier aderumier at odiso.com
Sun Nov 8 15:19:38 CET 2020


We can have only 1 controller of same type by node, avoid to define it in zone plugin.

This allow to define a global controller definition for all nodes,

and if needed, allow to redefine a controller for a specific node.
(for evpn with Ebgp, where we need to be able change peers/AS or other options by node)
---
 PVE/Network/SDN/Controllers.pm            | 33 +++++++++++++++--------
 PVE/Network/SDN/Controllers/EvpnPlugin.pm | 10 ++++++-
 PVE/Network/SDN/Controllers/Plugin.pm     |  1 +
 PVE/Network/SDN/Zones.pm                  |  6 ++++-
 PVE/Network/SDN/Zones/EvpnPlugin.pm       | 28 ++++++++++++-------
 PVE/Network/SDN/Zones/Plugin.pm           |  5 ++++
 6 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/PVE/Network/SDN/Controllers.pm b/PVE/Network/SDN/Controllers.pm
index f652d7f..be110b7 100644
--- a/PVE/Network/SDN/Controllers.pm
+++ b/PVE/Network/SDN/Controllers.pm
@@ -95,19 +95,25 @@ sub generate_controller_config {
     #generate configuration
     my $config = {};
 
-    foreach my $id (keys %{$controller_cfg->{ids}}) {
-	my $plugin_config = $controller_cfg->{ids}->{$id};
-	my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
-	$plugin->generate_controller_config($plugin_config, $plugin_config, $id, $uplinks, $config);
-    }
+    my $nodename = PVE::INotify::nodename();
 
+    my $generated_controller_config = {};
     foreach my $id (keys %{$zone_cfg->{ids}}) {
 	my $plugin_config = $zone_cfg->{ids}->{$id};
-	my $controllerid = $plugin_config->{controller};
-	next if !$controllerid;
-	my $controller = $controller_cfg->{ids}->{$controllerid};
+	my $controller;
+	my $controllerid;
+        if ($controllerid = $plugin_config->{controller}) {
+            $controller = $controller_cfg->{ids}->{$controllerid};
+        } else {
+	    my $zone_plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+            $controllerid = $zone_plugin->find_controller($plugin_config, $nodename, $controller_cfg);
+            $controller = $controller_cfg->{ids}->{$controllerid} if $controllerid;
+        }
 	if ($controller) {
 	    my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
+
+	    $controller_plugin->generate_controller_config($controller, $controller, $controllerid, $uplinks, $config) if !$generated_controller_config->{$controllerid};
+	    $generated_controller_config->{$controllerid} = 1;
 	    $controller_plugin->generate_controller_zone_config($plugin_config, $controller, $id, $uplinks, $config);
 	}
     }
@@ -118,9 +124,14 @@ sub generate_controller_config {
 	next if !$zoneid;
 	my $zone = $zone_cfg->{ids}->{$zoneid};
 	next if !$zone;
-	my $controllerid = $zone->{controller};
-	next if !$controllerid;
-	my $controller = $controller_cfg->{ids}->{$controllerid};
+	my $controller;
+        if (my $controllerid = $plugin_config->{controller}) {
+            $controller = $controller_cfg->{ids}->{$controllerid};
+        } else {
+	    my $zone_plugin = PVE::Network::SDN::Zones::Plugin->lookup($zone->{type});
+            my $controllerid = $zone_plugin->find_controller($zone, $nodename, $controller_cfg);
+            $controller = $controller_cfg->{ids}->{$controllerid} if $controllerid;
+        }
 	if ($controller) {
 	    my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
 	    $controller_plugin->generate_controller_vnet_config($plugin_config, $controller, $zoneid, $id, $config);
diff --git a/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index d82de2a..ca7be5b 100644
--- a/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -36,6 +36,7 @@ sub properties {
 
 sub options {
     return {
+	'node' => { optional => 1 },
 	'asn' => { optional => 0 },
 	'peers' => { optional => 0 },
 	'gateway-nodes' => { optional => 1 },
@@ -165,10 +166,17 @@ sub on_update_hook {
 
     # we can only have 1 evpn controller / 1 asn by server
 
+    my $current_controller = $controller_cfg->{ids}->{$controllerid};
+
     foreach my $id (keys %{$controller_cfg->{ids}}) {
 	next if $id eq $controllerid;
 	my $controller = $controller_cfg->{ids}->{$id};
-	die "only 1 evpn controller can be defined" if $controller->{type} eq "evpn";
+	next if $controller->{type} ne "evpn";
+	if(!$controller->{node} &&  !$current_controller->{node}) {
+	    die "only 1 global evpn controller can be defined";
+        } else {
+	    die "only 1 evpn controller can be defined for a specific node" if $controller->{node} eq $current_controller->{node};
+        }
     }
 }
 
diff --git a/PVE/Network/SDN/Controllers/Plugin.pm b/PVE/Network/SDN/Controllers/Plugin.pm
index 06cd576..acdfda0 100644
--- a/PVE/Network/SDN/Controllers/Plugin.pm
+++ b/PVE/Network/SDN/Controllers/Plugin.pm
@@ -40,6 +40,7 @@ my $defaultData = {
 	    type => 'string', format => 'pve-configid',
 	    type => 'string',
 	},
+        node => get_standard_option('pve-node', { optional => 1 }),
         controller => get_standard_option('pve-sdn-controller-id',
             { completion => \&PVE::Network::SDN::complete_sdn_controller }),
     },
diff --git a/PVE/Network/SDN/Zones.pm b/PVE/Network/SDN/Zones.pm
index 1f225dc..bff5cd7 100644
--- a/PVE/Network/SDN/Zones.pm
+++ b/PVE/Network/SDN/Zones.pm
@@ -124,12 +124,16 @@ sub generate_etc_network_config {
 
 	next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
 
+	my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
+
 	my $controller;
 	if (my $controllerid = $plugin_config->{controller}) {
 	    $controller = $controller_cfg->{ids}->{$controllerid};
+	} else {
+	    my $controllerid = $plugin->find_controller($plugin_config, $nodename, $controller_cfg);
+	    $controller = $controller_cfg->{ids}->{$controllerid} if $controllerid;
 	}
 
-	my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
 	eval {
 	    $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $controller, $subnet_cfg, $interfaces_config, $config);
 	};
diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm b/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 5338a1b..495d134 100644
--- a/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -35,7 +35,6 @@ sub options {
     return {
         nodes => { optional => 1},
         'vrf-vxlan' => { optional => 0 },
-        'controller' => { optional => 0 },
 	mtu => { optional => 1 },
 	dns => { optional => 1 },
 	reversedns => { optional => 1 },
@@ -156,17 +155,28 @@ sub generate_sdn_config {
     return $config;
 }
 
+sub find_controller {
+    my ($class, $plugin_config, $nodename, $controller_cfg) = @_;
+
+    #return global controller or more precise if node is defined
+    my $found_controller = undef;
+    foreach my $id  (keys %{$controller_cfg->{ids}}) {
+	my $controller = $controller_cfg->{ids}->{$id};
+	next if $controller->{type} ne 'evpn';
+	if(!$controller->{node}) {
+	    $found_controller = $id if !$found_controller;
+	} else {
+	    next if $controller->{node} ne $nodename;
+	    $found_controller = $id;
+	}
+    }
+    die "can't find any evpn controller" if !$found_controller;
+    return $found_controller;
+}
+
 sub on_update_hook {
     my ($class, $zoneid, $zone_cfg, $controller_cfg) = @_;
 
-    # verify that controller exist
-    my $controller = $zone_cfg->{ids}->{$zoneid}->{controller};
-    if (!defined($controller_cfg->{ids}->{$controller})) {
-	die "controller $controller don't exist";
-    } else {
-	die "$controller is not a evpn controller type" if $controller_cfg->{ids}->{$controller}->{type} ne 'evpn';
-    }
-
     #vrf-vxlan need to be defined
 
     my $vrfvxlan = $zone_cfg->{ids}->{$zoneid}->{'vrf-vxlan'};
diff --git a/PVE/Network/SDN/Zones/Plugin.pm b/PVE/Network/SDN/Zones/Plugin.pm
index 6fc13eb..bd46e45 100644
--- a/PVE/Network/SDN/Zones/Plugin.pm
+++ b/PVE/Network/SDN/Zones/Plugin.pm
@@ -126,6 +126,11 @@ sub controller_reload {
     die "please implement inside plugin";
 }
 
+sub find_controller {
+    my ($class, $plugin_config, $nodename, $controller_cfg) = @_;
+    return undef;
+}
+
 sub on_delete_hook {
     my ($class, $zoneid, $vnet_cfg) = @_;
 
-- 
2.20.1





More information about the pve-devel mailing list