---
 PVE/API2/Network/SDN/Subnets.pm       | 31 +-------------
 PVE/Network/SDN/SubnetPlugin.pm       | 59 ++++++++++++++++++++-------
 PVE/Network/SDN/Subnets.pm            | 34 +++++++++------
 PVE/Network/SDN/VnetPlugin.pm         | 23 ++++-------
 PVE/Network/SDN/Vnets.pm              | 43 ++++++++++++-------
 PVE/Network/SDN/Zones/EvpnPlugin.pm   | 10 ++---
 PVE/Network/SDN/Zones/SimplePlugin.pm | 16 ++++----
 7 files changed, 117 insertions(+), 99 deletions(-)

diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subnets.pm
index 094401c..728b939 100644
--- a/PVE/API2/Network/SDN/Subnets.pm
+++ b/PVE/API2/Network/SDN/Subnets.pm
@@ -135,17 +135,7 @@ __PACKAGE__->register_method ({
                }
 
                $cfg->{ids}->{$id} = $opts;
-               PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $cfg);
-
-               my $ipam_cfg = PVE::Network::SDN::Ipams::config();
-               my $ipam = $cfg->{ids}->{$id}->{ipam};
-               if ($ipam) {
-                   raise_param_exc({ ipam => "$ipam not existing"}) if 
!$ipam_cfg->{ids}->{$ipam};
-                   my $plugin_config = $ipam_cfg->{ids}->{$ipam};
-                   my $plugin = 
PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
-                   $plugin->add_subnet($plugin_config, $id, 
$cfg->{ids}->{$id});
-                   $plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) 
if $opts->{gateway};
-               }
+               PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $opts);
 
                PVE::Network::SDN::Subnets::write_config($cfg);
 
@@ -182,24 +172,7 @@ __PACKAGE__->register_method ({
            my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, 
$param, 0, 1);
            $cfg->{ids}->{$id} = $opts;
 
-           PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $cfg);
-
-            my $ipam_cfg = PVE::Network::SDN::Ipams::config();
-            my $ipam = $cfg->{ids}->{$id}->{ipam};
-           if ($ipam) {
-               raise_param_exc({ ipam => "$ipam not existing"}) if 
!$ipam_cfg->{ids}->{$ipam};
-               my $plugin_config = $ipam_cfg->{ids}->{$ipam};
-               my $plugin = 
PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
-               $plugin->add_subnet($plugin_config, $id, $cfg->{ids}->{$id});
-
-               if($opts->{gateway} && $scfg->{gateway} && $opts->{gateway} ne 
$scfg->{gateway}) {
-                   $plugin->del_ip($plugin_config, $id, $scfg->{gateway});
-               }
-               if (!defined($opts->{gateway}) && $scfg->{gateway}) {
-                   $plugin->del_ip($plugin_config, $id, $scfg->{gateway});
-               } 
-               $plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) if 
$opts->{gateway};
-           }
+           PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $opts, $scfg);
 
            PVE::Network::SDN::Subnets::write_config($cfg);
 
diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm
index bc66b82..84303d1 100644
--- a/PVE/Network/SDN/SubnetPlugin.pm
+++ b/PVE/Network/SDN/SubnetPlugin.pm
@@ -8,6 +8,8 @@ use base qw(PVE::SectionConfig);
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::Exception qw(raise raise_param_exc);
 use Net::Subnet qw(subnet_matcher);
+use PVE::Network::SDN::Vnets;
+use PVE::Network::SDN::Ipams;
 
 PVE::Cluster::cfs_register_file('sdn/subnets.cfg',
                                  sub { __PACKAGE__->parse_config(@_); },
@@ -52,6 +54,10 @@ sub private {
 
 sub properties {
     return {
+        vnet => {
+            type => 'string',
+            description => "associated vnet",
+        },
         gateway => {
             type => 'string', format => 'ip',
             description => "Subnet Gateway: Will be assign on vnet for layer3 
zones",
@@ -94,6 +100,7 @@ sub properties {
 
 sub options {
     return {
+       vnet => { optional => 1 },
        gateway => { optional => 1 },
        routes => { optional => 1 },
        snat => { optional => 1 },
@@ -107,44 +114,66 @@ sub options {
 }
 
 sub on_update_hook {
-    my ($class, $subnetid, $subnet_cfg) = @_;
+    my ($class, $subnetid, $subnet, $old_subnet) = @_;
 
     my $cidr = $subnetid =~ s/-/\//r;
     my $subnet_matcher = subnet_matcher($cidr);
 
-    my $subnet = $subnet_cfg->{ids}->{$subnetid};
-
+    my $vnetid = $subnet->{vnet};
     my $gateway = $subnet->{gateway};
+    my $ipam = $subnet->{ipam};
     my $dns = $subnet->{dns};
     my $dnszone = $subnet->{dnszone};
     my $reversedns = $subnet->{reversedns};
     my $reversednszone = $subnet->{reversednszone};
 
-    my ($ip, $mask) = split(/\//, $cidr);
+    my $old_gateway = $old_subnet->{gateway} if $old_subnet;
 
+    if($vnetid) {
+       my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+       raise_param_exc({ vnet => "$vnetid don't exist"}) if !$vnet;
+    }
+
+    my ($ip, $mask) = split(/\//, $cidr);
     #for /32 pointopoint, we allow gateway outside the subnet
-    raise_param_exc({ gateway => "$gateway is not in subnet $subnet"}) if 
$gateway && !$subnet_matcher->($gateway) && $mask != 32;
+    raise_param_exc({ gateway => "$gateway is not in subnet $subnetid"}) if 
$gateway && !$subnet_matcher->($gateway) && $mask != 32;
 
     raise_param_exc({ dns => "missing dns provider"}) if $dnszone && !$dns;
     raise_param_exc({ dnszone => "missing dns zone"}) if $dns && !$dnszone;
     raise_param_exc({ reversedns => "missing dns provider"}) if 
$reversednszone && !$reversedns;
     raise_param_exc({ reversednszone => "missing dns zone"}) if $reversedns && 
!$reversednszone;
 
+    if ($ipam) {
+       my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+       my $plugin_config = $ipam_cfg->{ids}->{$ipam};
+       raise_param_exc({ ipam => "$ipam not existing"}) if !$plugin_config;
+       my $plugin = 
PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+       $plugin->add_subnet($plugin_config, $subnetid, $subnet);
+
+       #delete on removal
+       if (!defined($gateway) && $old_gateway) {
+           eval {
+               PVE::Network::SDN::Subnets::del_ip($subnetid, $old_subnet, 
$old_gateway);
+           };
+           warn if $@;
+       }
+        if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
+           PVE::Network::SDN::Subnets::add_ip($subnetid, $subnet, $gateway);
+       }
+
+       #delete old ip after update
+       if($gateway && $old_gateway && $gateway ne $old_gateway) {
+           eval {
+               PVE::Network::SDN::Subnets::del_ip($subnetid, $old_subnet, 
$old_gateway);
+           };
+           warn if $@;
+       }
+    }
 }
 
 sub on_delete_hook {
     my ($class, $subnetid, $subnet_cfg, $vnet_cfg) = @_;
 
-    #verify if vnets have subnet
-    foreach my $vnetid (keys %{$vnet_cfg->{ids}}) {
-       my $vnet = $vnet_cfg->{ids}->{$vnetid};
-       my @subnets = PVE::Tools::split_list($vnet->{subnets}) if 
$vnet->{subnets};
-       foreach my $subnet (@subnets) {
-           my $id = $subnet =~ s/\//-/r;
-           raise_param_exc({ subnet => "$subnet is attached to vnet $vnetid"}) 
if $id eq $subnetid;
-       }
-    }
-
     return;
 }
 
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 4e8353e..d20af9e 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -57,20 +57,18 @@ sub get_subnet {
 }
 
 sub find_ip_subnet {
-    my ($ip, $subnetslist) = @_;
-
-    my $subnets_cfg = PVE::Network::SDN::Subnets::config();
-    my @subnets = PVE::Tools::split_list($subnetslist) if $subnetslist;
+    my ($ip, $subnets) = @_;
 
     my $subnet = undef;
     my $subnetid = undef;
 
-    foreach my $s (@subnets) {
-        my $subnet_matcher = subnet_matcher($s);
-        next if !$subnet_matcher->($ip);
-        $subnetid = $s =~ s/\//-/r;
-        $subnet = $subnets_cfg->{ids}->{$subnetid};
-        last;
+    foreach my $id (sort keys %{$subnets}) {
+       my $cidr = $id =~ s/-/\//r;
+       my $subnet_matcher = subnet_matcher($cidr);
+       next if !$subnet_matcher->($ip);
+       $subnet = $subnets->{$id};
+       $subnetid = $id;
+       last;
     }
     die  "can't find any subnet for ip $ip" if !$subnet;
 
@@ -143,8 +141,11 @@ sub next_free_ip {
        my $ipam_cfg = PVE::Network::SDN::Ipams::config();
        my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
        my $plugin = 
PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
-       $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet);
-       ($ip, undef) = split(/\//, $cidr);
+       eval {
+           $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, 
$subnet);
+           ($ip, undef) = split(/\//, $cidr);
+       };
+       die $@ if $@;
     }
 
     eval {
@@ -167,6 +168,8 @@ sub next_free_ip {
 sub add_ip {
     my ($subnetid, $subnet, $ip, $hostname) = @_;
 
+    return if !$subnet;
+
     my $ipamid = $subnet->{ipam};
     my $dns = $subnet->{dns};
     my $dnszone = $subnet->{dnszone};
@@ -182,7 +185,10 @@ sub add_ip {
        my $ipam_cfg = PVE::Network::SDN::Ipams::config();
        my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
        my $plugin = 
PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
-       $plugin->add_ip($plugin_config, $subnetid, $ip);
+       eval {
+           $plugin->add_ip($plugin_config, $subnetid, $ip);
+       };
+       die $@ if $@;
     }
 
     eval {
@@ -204,6 +210,8 @@ sub add_ip {
 sub del_ip {
     my ($subnetid, $subnet, $ip, $hostname) = @_;
 
+    return if !$subnet;
+
     my $ipamid = $subnet->{ipam};
     my $dns = $subnet->{dns};
     my $dnszone = $subnet->{dnszone};
diff --git a/PVE/Network/SDN/VnetPlugin.pm b/PVE/Network/SDN/VnetPlugin.pm
index 6b2bcc8..47fd4d4 100644
--- a/PVE/Network/SDN/VnetPlugin.pm
+++ b/PVE/Network/SDN/VnetPlugin.pm
@@ -68,11 +68,6 @@ sub properties {
             description => "alias name of the vnet",
            optional => 1,
         },
-        subnets => {
-            type => 'string',
-            description => "Subnets list",
-           optional => 1,
-        },
         mac => {
             type => 'string',
             description => "Anycast router mac address",
@@ -86,16 +81,21 @@ sub options {
         zone => { optional => 0},
         tag => { optional => 1},
         alias => { optional => 1 },
-        subnets => { optional => 1 },
         mac => { optional => 1 },
         vlanaware => { optional => 1 },
     };
 }
 
 sub on_delete_hook {
-    my ($class, $sdnid, $vnet_cfg) = @_;
+    my ($class, $vnetid, $vnet_cfg) = @_;
 
-    return;
+    #verify if subnets are associated
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
+    my @subnetlist = ();
+    foreach my $subnetid (sort keys %{$subnets}) {
+       push @subnetlist, $subnetid;
+    }
+    raise_param_exc({ vnet => "Vnet is attached to following subnets:". 
join(',', @subnetlist)}) if @subnetlist > 0;
 }
 
 sub on_update_hook {
@@ -111,13 +111,6 @@ sub on_update_hook {
            }
        }
     }
-
-    #verify subnet
-    my @subnets = 
PVE::Tools::split_list($vnet_cfg->{ids}->{$vnetid}->{subnets}) if 
$vnet_cfg->{ids}->{$vnetid}->{subnets};
-    foreach my $subnet (@subnets) {
-       my $id = $subnet =~ s/\//-/r;
-       raise_param_exc({ subnet => "$subnet not existing"}) if 
!$subnet_cfg->{ids}->{$id};
-    }
 }
 
 1;
diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index c9916b1..7cec418 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -54,22 +54,35 @@ sub get_vnet {
     return $vnet;
 }
 
+sub get_subnets {
+    my ($vnetid) = @_;
+
+    my $subnets = {};
+    my $subnets_cfg = PVE::Network::SDN::Subnets::config();
+    foreach my $subnetid (sort keys %{$subnets_cfg->{ids}}) {
+       my $subnet = $subnets_cfg->{ids}->{$subnetid};
+       next if !$subnet->{vnet} || $subnet->{vnet} ne $vnetid;
+       $subnets->{$subnetid} = $subnet;
+    }
+    return $subnets;
+
+}
+
 sub get_next_free_ip {
-    my ($vnet, $hostname, $ipversion) = @_;
+    my ($vnetid, $hostname, $ipversion) = @_;
 
     $ipversion = 4 if !$ipversion;
-    my $subnets_cfg = PVE::Network::SDN::Subnets::config();
-    my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets};
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
     my $ip = undef;
-    my $subnet = undef;
     my $subnetcount = 0;
-    foreach my $s (@subnets) {
-       my $subnetid = $s =~ s/\//-/r;
+
+    foreach my $subnetid (sort keys %{$subnets}) {
+        my $subnet = $subnets->{$subnetid};
        my ($network, $mask) = split(/-/, $subnetid);
+
        next if $ipversion != Net::IP::ip_get_version($network);
        $subnetcount++;
-       $subnet = $subnets_cfg->{ids}->{$subnetid};
-       if ($subnet && $subnet->{ipam}) {
+       if ($subnet->{ipam}) {
            eval {
                $ip = PVE::Network::SDN::Subnets::next_free_ip($subnetid, 
$subnet, $hostname);
            };
@@ -83,21 +96,23 @@ sub get_next_free_ip {
 }
 
 sub add_ip {
-    my ($vnet, $cidr, $hostname) = @_;
+    my ($vnetid, $cidr, $hostname) = @_;
+
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
 
     my ($ip, $mask) = split(/\//, $cidr);
-    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, 
$vnet->{subnets});
-    return if !$subnet->{ipam};
+    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, 
$subnets);
 
     PVE::Network::SDN::Subnets::add_ip($subnetid, $subnet, $ip, $hostname);
 }
 
 sub del_ip {
-    my ($vnet, $cidr, $hostname) = @_;
+    my ($vnetid, $cidr, $hostname) = @_;
+
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
 
     my ($ip, $mask) = split(/\//, $cidr);
-    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, 
$vnet->{subnets});
-    return if !$subnet->{ipam};
+    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, 
$subnets);
 
     PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname);
 }
diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm 
b/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 17c9262..ff25f12 100644
--- a/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -76,12 +76,12 @@ sub generate_sdn_config {
     #vnet bridge
     @iface_config = ();
 
-    my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets};
     my $address = {};
-    foreach my $subnet (@subnets) {
-       my $subnetid = $subnet =~ s/\//-/r;
-       next if !defined($subnet_cfg->{ids}->{$subnetid});
-       my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway};
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
+    foreach my $subnetid (sort keys %{$subnets}) {
+       my $subnet = $subnets->{$subnetid};
+       my $cidr = $subnetid =~ s/-/\//r;
+       my $gateway = $subnet->{gateway};
        if ($gateway) {
            push @iface_config, "address $gateway" if 
!defined($address->{$gateway});
            $address->{$gateway} = 1;
diff --git a/PVE/Network/SDN/Zones/SimplePlugin.pm 
b/PVE/Network/SDN/Zones/SimplePlugin.pm
index a1733d5..a4299dd 100644
--- a/PVE/Network/SDN/Zones/SimplePlugin.pm
+++ b/PVE/Network/SDN/Zones/SimplePlugin.pm
@@ -35,19 +35,19 @@ sub generate_sdn_config {
     # vnet bridge
     my @iface_config = ();
 
-    my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets};
     my $address = {};
-    foreach my $subnet (@subnets) {
-       my $subnetid = $subnet =~ s/\//-/r;
-       next if !defined($subnet_cfg->{ids}->{$subnetid});
-        my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway};
-        if ($gateway) {
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid);
+    foreach my $subnetid (sort keys %{$subnets}) {
+       my $subnet = $subnets->{$subnetid};
+       my $cidr = $subnetid =~ s/-/\//r; 
+       my $gateway = $subnet->{gateway};
+       if ($gateway) {
            push @iface_config, "address $gateway" if 
!defined($address->{$gateway});
            $address->{$gateway} = 1;
        }
        #add route for /32 pointtopoint
-       my ($ip, $mask) = split(/\//, $subnet);
-       push @iface_config, "up ip route add $subnet dev $vnetid" if $mask == 
32;
+       my ($ip, $mask) = split(/\//, $cidr);
+       push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32;
     }
 
     push @iface_config, "hwaddress $mac" if $mac;
-- 
2.20.1


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

Reply via email to