all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [pve-network 0/4] updates
@ 2021-06-04 11:24 Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 1/4] sdn: get_local_vnets : add ipam && vlanaware values Alexandre Derumier
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Alexandre Derumier @ 2021-06-04 11:24 UTC (permalink / raw)
  To: pve-devel

This is a resend of previous sended patches
+ a new patch fixing subnets/ipam is_gateway value

Alexandre Derumier (4):
  sdn: get_local_vnets : add ipam && vlanaware values
  add vnets test + ipam fixes
  vnets: subroutines: return if !$vnetid
  subnets/ipam : fix is_gateway

 PVE/Network/SDN.pm                            |   4 +-
 PVE/Network/SDN/Ipams/NetboxPlugin.pm         |  14 +-
 PVE/Network/SDN/Ipams/PVEPlugin.pm            |  17 +-
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm        |  18 +-
 PVE/Network/SDN/SubnetPlugin.pm               |   2 +-
 PVE/Network/SDN/Subnets.pm                    |   4 +-
 PVE/Network/SDN/Vnets.pm                      |  23 +-
 test/ipams/netbox/expected.add_ip_notgateway  |   9 +
 test/ipams/phpipam/expected.add_ip_notgateway |  12 +
 test/run_test_ipams.pl                        |  18 +-
 test/run_test_subnets.pl                      |  24 +-
 test/run_test_vnets.pl                        | 355 ++++++++++++++++++
 test/vnets/ipv4/ipam.db                       |  17 +
 test/vnets/ipv4/ipam_config                   |   7 +
 test/vnets/ipv4/sdn_config                    |  26 ++
 test/vnets/ipv4noipam/ipam.db                 |  17 +
 test/vnets/ipv4noipam/ipam_config             |   7 +
 test/vnets/ipv4noipam/sdn_config              |  26 ++
 test/vnets/ipv6/ipam.db                       |  16 +
 test/vnets/ipv6/ipam_config                   |   7 +
 test/vnets/ipv6/sdn_config                    |  26 ++
 21 files changed, 614 insertions(+), 35 deletions(-)
 create mode 100644 test/ipams/netbox/expected.add_ip_notgateway
 create mode 100644 test/ipams/phpipam/expected.add_ip_notgateway
 create mode 100755 test/run_test_vnets.pl
 create mode 100644 test/vnets/ipv4/ipam.db
 create mode 100644 test/vnets/ipv4/ipam_config
 create mode 100644 test/vnets/ipv4/sdn_config
 create mode 100644 test/vnets/ipv4noipam/ipam.db
 create mode 100644 test/vnets/ipv4noipam/ipam_config
 create mode 100644 test/vnets/ipv4noipam/sdn_config
 create mode 100644 test/vnets/ipv6/ipam.db
 create mode 100644 test/vnets/ipv6/ipam_config
 create mode 100644 test/vnets/ipv6/sdn_config

-- 
2.20.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [pve-network 1/4] sdn: get_local_vnets : add ipam && vlanaware values
  2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
@ 2021-06-04 11:24 ` Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 2/4] add vnets test + ipam fixes Alexandre Derumier
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2021-06-04 11:24 UTC (permalink / raw)
  To: pve-devel

to be able to use them in ui bridgeselector
---
 PVE/Network/SDN.pm | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 314b515..d3399ce 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -198,7 +198,9 @@ sub get_local_vnets {
 	my $zone_config = PVE::Network::SDN::Zones::sdn_zones_config($zones_cfg, $zoneid);
 
 	next if defined($zone_config->{nodes}) && !$zone_config->{nodes}->{$nodename};
-	$vnets->{$vnetid} = { type => 'vnet', active => '1', comments => $comments };
+	my $ipam = $zone_config->{ipam} ? 1 : 0;
+	my $vlanaware = $vnet->{vlanaware} ? 1 : 0;
+	$vnets->{$vnetid} = { type => 'vnet', active => '1', ipam => $ipam, vlanaware => $vlanaware, comments => $comments };
     }
 
     return $vnets;
-- 
2.20.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [pve-network 2/4] add vnets test + ipam fixes
  2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 1/4] sdn: get_local_vnets : add ipam && vlanaware values Alexandre Derumier
@ 2021-06-04 11:24 ` Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 3/4] vnets: subroutines: return if !$vnetid Alexandre Derumier
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2021-06-04 11:24 UTC (permalink / raw)
  To: pve-devel

- add vnets tests with multiple subnets
- fix pve ipam ipv6 with next_free_ip (ipv6 don't have network && broadcast address)
- fix vnet next_free_ip with no ipam
---
 PVE/Network/SDN/Ipams/PVEPlugin.pm |  13 +-
 PVE/Network/SDN/Vnets.pm           |  13 +-
 test/run_test_subnets.pl           |  16 +-
 test/run_test_vnets.pl             | 355 +++++++++++++++++++++++++++++
 test/vnets/ipv4/ipam.db            |  17 ++
 test/vnets/ipv4/ipam_config        |   7 +
 test/vnets/ipv4/sdn_config         |  26 +++
 test/vnets/ipv4noipam/ipam.db      |  17 ++
 test/vnets/ipv4noipam/ipam_config  |   7 +
 test/vnets/ipv4noipam/sdn_config   |  26 +++
 test/vnets/ipv6/ipam.db            |  16 ++
 test/vnets/ipv6/ipam_config        |   7 +
 test/vnets/ipv6/sdn_config         |  26 +++
 13 files changed, 526 insertions(+), 20 deletions(-)
 create mode 100755 test/run_test_vnets.pl
 create mode 100644 test/vnets/ipv4/ipam.db
 create mode 100644 test/vnets/ipv4/ipam_config
 create mode 100644 test/vnets/ipv4/sdn_config
 create mode 100644 test/vnets/ipv4noipam/ipam.db
 create mode 100644 test/vnets/ipv4noipam/ipam_config
 create mode 100644 test/vnets/ipv4noipam/sdn_config
 create mode 100644 test/vnets/ipv6/ipam.db
 create mode 100644 test/vnets/ipv6/ipam_config
 create mode 100644 test/vnets/ipv6/sdn_config

diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 7e2fb77..8fe5bbb 100644
--- a/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -90,7 +90,6 @@ sub add_ip {
     cfs_lock_file($ipamdb_file, undef, sub {
 
 	my $db = read_db();
-
 	my $dbzone = $db->{zones}->{$zone};
 	die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
 	my $dbsubnet = $dbzone->{subnets}->{$cidr};
@@ -132,13 +131,15 @@ sub add_next_freeip {
 	    $freeip = $network;
 	} else {
 	    my $iplist = NetAddr::IP->new($cidr);
-	    my $broadcast = $iplist->broadcast();
-
+	    my $lastip = $iplist->last()->canon();
+	    $iplist++ if Net::IP::ip_is_ipv4($network); #skip network address for ipv4
 	    while(1) {
-		$iplist++;
-		last if $iplist eq $broadcast;
 		my $ip = $iplist->canon();
-		next if defined($dbsubnet->{ips}->{$ip});
+		if (defined($dbsubnet->{ips}->{$ip})) {
+		    last if $ip eq $lastip;
+		    $iplist++;
+		    next;
+		} 
 		$freeip = $ip;
 		last;
 	    }
diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index 9d9b155..8c9629d 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -102,6 +102,8 @@ sub get_next_free_cidr {
     my $zoneid = $vnet->{zone};
     my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
 
+    return if !$zone->{ipam};
+
     $ipversion = 4 if !$ipversion;
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
     my $ip = undef;
@@ -113,12 +115,11 @@ sub get_next_free_cidr {
 
 	next if $ipversion != Net::IP::ip_get_version($network);
 	$subnetcount++;
-	if ($zone->{ipam}) {
-	    eval {
-		$ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);
-	    };
-	    warn $@ if $@;
-	}
+
+	eval {
+	    $ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);
+	};
+	warn $@ if $@;
 	last if $ip;
     }
     die "can't find any free ip" if !$ip && $subnetcount > 0;
diff --git a/test/run_test_subnets.pl b/test/run_test_subnets.pl
index 364baa6..9fca202 100755
--- a/test/run_test_subnets.pl
+++ b/test/run_test_subnets.pl
@@ -69,7 +69,7 @@ foreach my $path (@plugins) {
 
     my $subnet_cidr = $subnet->{cidr};
     my $iplist = NetAddr::IP->new($subnet_cidr);
-    $iplist++;
+    $iplist++ if Net::IP::ip_is_ipv4($iplist->canon()); #skip network address for ipv4
     my $ip = $iplist->canon();
     $iplist++;
     my $ipnextfree = $iplist->canon();
@@ -112,7 +112,7 @@ foreach my $path (@plugins) {
     );
 
     ## add_subnet
-    my $test = "add_subnet";
+    my $test = "add_subnet $subnetid";
     my $name = "$testid $test";
     my $result = undef;
     my $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{}}}}}}';
@@ -132,7 +132,7 @@ foreach my $path (@plugins) {
     }
 
     ## add_ip
-    $test = "add_ip";
+    $test = "add_ip $ip";
     $name = "$testid $test";
     $result = undef;
     $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{}}}}}}}';
@@ -152,7 +152,7 @@ foreach my $path (@plugins) {
 
     if($ipam) {
 	## add_already_exist_ip
-	$test = "add_already_exist_ip";
+	$test = "add_already_exist_ip $ip";
 	$name = "$testid $test";
 
 	eval {
@@ -167,7 +167,7 @@ foreach my $path (@plugins) {
     }
 
     ## add_second_ip
-    $test = "add_second_ip";
+    $test = "add_second_ip $ip2";
     $name = "$testid $test";
     $result = undef;
     $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ip2.'":{}}}}}}}';
@@ -186,7 +186,7 @@ foreach my $path (@plugins) {
     }
 
     ## add_next_free
-    $test = "add_next_freeip";
+    $test = "find_next_freeip ($ipnextfree)";
     $name = "$testid $test";
     $result = undef;
     $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
@@ -203,7 +203,7 @@ foreach my $path (@plugins) {
     }
 
     ## del_ip
-    $test = "del_ip";
+    $test = "del_ip $ip";
     $name = "$testid $test";
     $result = undef;
     $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
@@ -223,7 +223,7 @@ foreach my $path (@plugins) {
 
     if($ipam){
 	## del_subnet_not_empty
-	$test = "del_subnet_not_empty";
+	$test = "del_subnet_not_empty $subnetid";
 	$name = "$testid $test";
 	$result = undef;
 	$expected = undef;
diff --git a/test/run_test_vnets.pl b/test/run_test_vnets.pl
new file mode 100755
index 0000000..5aeb676
--- /dev/null
+++ b/test/run_test_vnets.pl
@@ -0,0 +1,355 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib qw(..);
+use File::Slurp;
+use NetAddr::IP qw(:lower);
+
+use Test::More;
+use Test::MockModule;
+
+use PVE::Network::SDN;
+use PVE::Network::SDN::Zones;
+use PVE::Network::SDN::Controllers;
+use PVE::INotify;
+use JSON;
+
+use Data::Dumper qw(Dumper);
+$Data::Dumper::Sortkeys = 1;
+
+sub read_sdn_config {
+    my ($file) = @_;
+    # Read structure back in again
+    open my $in, '<', $file or die $!;
+    my $sdn_config;
+    {
+	local $/;    # slurp mode
+	$sdn_config = eval <$in>;
+    }
+    close $in;
+    return $sdn_config;
+}
+
+
+my @plugins = read_dir( './vnets/', prefix => 1 ) ;
+
+foreach my $path (@plugins) {
+
+    my (undef, $testid) = split(/\//, $path);
+
+    print "test: $testid\n";
+    my $sdn_config = read_sdn_config ("$path/sdn_config");
+
+    my $pve_sdn_zones;
+    $pve_sdn_zones = Test::MockModule->new('PVE::Network::SDN::Zones');
+    $pve_sdn_zones->mock(
+	config => sub {
+	    return $sdn_config->{zones};
+	},
+    );
+
+    my $pve_sdn_vnets;
+    $pve_sdn_vnets = Test::MockModule->new('PVE::Network::SDN::Vnets');
+    $pve_sdn_vnets->mock(
+	config => sub {
+	    return $sdn_config->{vnets};
+	},
+    );
+
+    my $pve_sdn_subnets;
+    $pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Subnets');
+    $pve_sdn_subnets->mock(
+	config => sub {
+	    return $sdn_config->{subnets};
+	},
+	verify_dns_zone => sub {
+	    return;
+	},
+	add_dns_record => sub {
+	    return;
+	}
+    );
+
+    my $js = JSON->new;
+    $js->canonical(1);
+  
+    #test params;
+    #test params;
+    my $subnets = $sdn_config->{subnets}->{ids};
+
+    my $subnetid = (sort keys %{$subnets})[0];
+    my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
+    my $subnet_cidr = $subnet->{cidr};
+    my $iplist = NetAddr::IP->new($subnet_cidr);
+    my $mask = $iplist->masklen();
+    my $ipversion = undef;
+
+    if (Net::IP::ip_is_ipv4($iplist->canon())){
+	$iplist++; #skip network address for ipv4
+	$ipversion = 4;
+    } else { 
+	$ipversion = 6;
+    }
+
+    my $cidr1 = $iplist->canon()."/$mask";
+    $iplist++;
+    my $cidr2 = $iplist->canon()."/$mask";
+    my $cidr_outofrange = '8.8.8.8/8';
+
+    my $subnetid2 = (sort keys %{$subnets})[1];
+    my $subnet2 = PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid2, 1);
+    my $subnet2_cidr = $subnet2->{cidr};
+    my $iplist2 = NetAddr::IP->new($subnet2_cidr);
+    $iplist2++;
+    my $cidr3 = $iplist2->canon()."/$mask";
+    $iplist2++;
+    my $cidr4 = $iplist2->canon()."/$mask";
+
+    my $hostname = "myhostname";
+    my $mac = "da:65:8f:18:9b:6f";
+    my $description = "mydescription";
+    my $ipamdb = read_sdn_config ("$path/ipam.db");
+
+    my $zone = $sdn_config->{zones}->{ids}->{"myzone"};
+    my $ipam = $zone->{ipam};
+
+    my $plugin;
+    my $sdn_ipam_plugin;
+    if($ipam) {
+	$plugin = PVE::Network::SDN::Ipams::Plugin->lookup($ipam);
+	$sdn_ipam_plugin = Test::MockModule->new($plugin);
+	$sdn_ipam_plugin->mock(
+	    read_db => sub {
+		return $ipamdb;
+	    },
+	    write_db => sub {
+		my ($cfg) = @_;
+		$ipamdb = $cfg;
+	    }
+	);
+    }
+
+    my $pve_sdn_ipams;
+    $pve_sdn_ipams = Test::MockModule->new('PVE::Network::SDN::Ipams');
+    $pve_sdn_ipams->mock(
+	config => sub {
+	    my $ipam_config = read_sdn_config ("$path/ipam_config");
+	    return $ipam_config;
+	},
+    );
+
+    my $vnetid = "myvnet";
+
+    ## add_ip
+    my $test = "add_cidr $cidr1";
+    my $name = "$testid $test";
+    my $result = undef;
+    my $expected = '';
+
+    eval {
+	PVE::Network::SDN::Vnets::add_cidr($vnetid, $cidr1, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    ## add_ip
+    $test = "add_already_exist_cidr $cidr1";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = '';
+
+    eval {
+	PVE::Network::SDN::Vnets::add_cidr($vnetid, $cidr1, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        is (undef, undef, $name);
+    } elsif($ipam) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    ## add_ip
+    $test = "add_cidr $cidr2";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = '';
+
+    eval {
+	PVE::Network::SDN::Vnets::add_cidr($vnetid, $cidr2, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    ## add_ip
+    $test = "add_ip_out_of_range_subnets $cidr_outofrange";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = '';
+
+    eval {
+	PVE::Network::SDN::Vnets::add_cidr($vnetid, $cidr_outofrange, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        is (undef, undef, $name);
+    } else {
+        fail("$name : $@");
+    }
+
+    ## add_ip
+    $test = "add_cidr $cidr4";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = '';
+
+    eval {
+	PVE::Network::SDN::Vnets::add_cidr($vnetid, $cidr4, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+
+    $test = "find_next_free_cidr_in_second_subnet ($cidr3)";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = $ipam ? $cidr3 : undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::get_next_free_cidr($vnetid, $hostname, $mac, $description, $ipversion);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is ($result, $expected, $name);
+    }
+
+
+    $test = "del_cidr $cidr1";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::del_cidr($vnetid, $cidr1, $hostname);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    $test = "del_cidr $cidr3";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::del_cidr($vnetid, $cidr3, $hostname);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    $test = "del_cidr not exist $cidr1";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::del_cidr($vnetid, $cidr1, $hostname);
+    };
+
+    if ($@) {
+        is (undef, undef, $name);
+    } elsif($ipam) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    $test = "del_cidr outofrange $cidr_outofrange";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::del_cidr($vnetid, $cidr_outofrange, $hostname);
+    };
+
+    if ($@) {
+        is (undef, undef, $name);
+    } else {
+        fail("$name : $@");
+    }
+
+    $test = "find_next_free_cidr_in_first_subnet ($cidr1)";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = $ipam ? $cidr1 : undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::get_next_free_cidr($vnetid, $hostname, $mac, $description, $ipversion);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is ($result, $expected, $name);
+    }
+
+    $test = "update_cidr $cidr1";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::update_cidr($vnetid, $cidr1, $hostname, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+    $test = "update_cidr deleted $cidr3";
+    $name = "$testid $test";
+    $result = undef;
+    $expected = undef;
+
+    eval {
+	$result = PVE::Network::SDN::Vnets::update_cidr($vnetid, $cidr1, $hostname, $hostname, $mac, $description);
+    };
+
+    if ($@) {
+        fail("$name : $@");
+    } else {
+        is (undef, undef, $name);
+    }
+
+}
+
+done_testing();
+
+
diff --git a/test/vnets/ipv4/ipam.db b/test/vnets/ipv4/ipam.db
new file mode 100644
index 0000000..ef3fa93
--- /dev/null
+++ b/test/vnets/ipv4/ipam.db
@@ -0,0 +1,17 @@
+{
+   "zones" => {
+	"myzone" => {
+	    "subnets" => {
+		"192.168.0.0/30" => {
+		    "ips" =>{
+		    }
+		},
+		"192.168.1.0/30" => {
+		    "ips" =>{
+		    }
+		},
+	    }
+	}
+    }
+}
+
diff --git a/test/vnets/ipv4/ipam_config b/test/vnets/ipv4/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/test/vnets/ipv4/ipam_config
@@ -0,0 +1,7 @@
+{
+          'ids' => {
+                     'pve' => {
+                                'type' => 'pve'
+                              },
+                   },
+}
diff --git a/test/vnets/ipv4/sdn_config b/test/vnets/ipv4/sdn_config
new file mode 100644
index 0000000..ee11fd1
--- /dev/null
+++ b/test/vnets/ipv4/sdn_config
@@ -0,0 +1,26 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "pve", type =>"simple" } },
+             },
+
+  subnets => {
+              ids => { 
+			'myzone-192.168.0.0-30' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+			'myzone-192.168.1.0-30' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+                     }
+
+             }
+}
diff --git a/test/vnets/ipv4noipam/ipam.db b/test/vnets/ipv4noipam/ipam.db
new file mode 100644
index 0000000..ef3fa93
--- /dev/null
+++ b/test/vnets/ipv4noipam/ipam.db
@@ -0,0 +1,17 @@
+{
+   "zones" => {
+	"myzone" => {
+	    "subnets" => {
+		"192.168.0.0/30" => {
+		    "ips" =>{
+		    }
+		},
+		"192.168.1.0/30" => {
+		    "ips" =>{
+		    }
+		},
+	    }
+	}
+    }
+}
+
diff --git a/test/vnets/ipv4noipam/ipam_config b/test/vnets/ipv4noipam/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/test/vnets/ipv4noipam/ipam_config
@@ -0,0 +1,7 @@
+{
+          'ids' => {
+                     'pve' => {
+                                'type' => 'pve'
+                              },
+                   },
+}
diff --git a/test/vnets/ipv4noipam/sdn_config b/test/vnets/ipv4noipam/sdn_config
new file mode 100644
index 0000000..470c1ae
--- /dev/null
+++ b/test/vnets/ipv4noipam/sdn_config
@@ -0,0 +1,26 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { type =>"simple" } },
+             },
+
+  subnets => {
+              ids => { 
+			'myzone-192.168.0.0-30' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+			'myzone-192.168.1.0-30' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+                     }
+
+             }
+}
diff --git a/test/vnets/ipv6/ipam.db b/test/vnets/ipv6/ipam.db
new file mode 100644
index 0000000..d3f2ce9
--- /dev/null
+++ b/test/vnets/ipv6/ipam.db
@@ -0,0 +1,16 @@
+{
+   "zones" => {
+	"myzone" => {
+	    "subnets" => {
+		"2001:db8:85a3::8a2e:370:7334/127" => {
+		    "ips" =>{
+		    }
+		},
+		"2001:db8:85a3::8a2e:371:7334/127" => {
+		    "ips" =>{
+		    }
+		},
+	    }
+	}
+    }
+}
diff --git a/test/vnets/ipv6/ipam_config b/test/vnets/ipv6/ipam_config
new file mode 100644
index 0000000..f5f36ad
--- /dev/null
+++ b/test/vnets/ipv6/ipam_config
@@ -0,0 +1,7 @@
+{
+          'ids' => {
+                     'pve' => {
+                                'type' => 'pve'
+                              },
+                   },
+}
diff --git a/test/vnets/ipv6/sdn_config b/test/vnets/ipv6/sdn_config
new file mode 100644
index 0000000..231ca8a
--- /dev/null
+++ b/test/vnets/ipv6/sdn_config
@@ -0,0 +1,26 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "pve", type =>"simple" } },
+             },
+
+  subnets => {
+              ids => { 
+			'myzone-2001:db8:85a3::8a2e:370:7334-127' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+			'myzone-2001:db8:85a3::8a2e:371:7334-127' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  },
+                     }
+
+             }
+}
-- 
2.20.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [pve-network 3/4] vnets: subroutines: return if !$vnetid
  2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 1/4] sdn: get_local_vnets : add ipam && vlanaware values Alexandre Derumier
  2021-06-04 11:24 ` [pve-devel] [pve-network 2/4] add vnets test + ipam fixes Alexandre Derumier
@ 2021-06-04 11:24 ` Alexandre Derumier
  2021-06-04 11:25 ` [pve-devel] [pve-network 4/4] subnets/ipam : fix is_gateway Alexandre Derumier
  2021-06-18 16:30 ` [pve-devel] applied-series: [pve-network 0/4] updates Thomas Lamprecht
  4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2021-06-04 11:24 UTC (permalink / raw)
  To: pve-devel

---
 PVE/Network/SDN/Vnets.pm | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index 8c9629d..86967a3 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -52,6 +52,8 @@ sub complete_sdn_vnet {
 sub get_vnet {
     my ($vnetid, $running) = @_;
 
+    return if !$vnetid;
+
     my $cfg = {};
     if($running) {
 	my $cfg = PVE::Network::SDN::running_config();
@@ -68,6 +70,8 @@ sub get_vnet {
 sub get_subnets {
     my ($vnetid) = @_;
 
+    return if !$vnetid;
+
     my $subnets = undef;
     my $subnets_cfg = PVE::Network::SDN::Subnets::config();
     foreach my $subnetid (sort keys %{$subnets_cfg->{ids}}) {
@@ -130,6 +134,8 @@ sub get_next_free_cidr {
 sub add_cidr {
     my ($vnetid, $cidr, $hostname, $mac, $description) = @_;
 
+    return if !$vnetid;
+    
     my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
     PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
 }
@@ -137,6 +143,8 @@ sub add_cidr {
 sub update_cidr {
     my ($vnetid, $cidr, $hostname, $oldhostname, $mac, $description) = @_;
 
+    return if !$vnetid;
+
     my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
     PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description);
 }
@@ -144,6 +152,8 @@ sub update_cidr {
 sub del_cidr {
     my ($vnetid, $cidr, $hostname) = @_;
 
+    return if !$vnetid;
+
     my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
     PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname);
 }
-- 
2.20.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] [pve-network 4/4] subnets/ipam : fix is_gateway
  2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
                   ` (2 preceding siblings ...)
  2021-06-04 11:24 ` [pve-devel] [pve-network 3/4] vnets: subroutines: return if !$vnetid Alexandre Derumier
@ 2021-06-04 11:25 ` Alexandre Derumier
  2021-06-18 16:30 ` [pve-devel] applied-series: [pve-network 0/4] updates Thomas Lamprecht
  4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2021-06-04 11:25 UTC (permalink / raw)
  To: pve-devel

- add lost is_gateway in subnets subnet when creating subnet
- allow reuse ip as gateway in subnet create if it's already flagged gateway in the ipamdb
- add tests
---
 PVE/Network/SDN/Ipams/NetboxPlugin.pm         | 14 +++++++++++++-
 PVE/Network/SDN/Ipams/PVEPlugin.pm            |  4 ++--
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm        | 18 +++++++++++++++---
 PVE/Network/SDN/SubnetPlugin.pm               |  2 +-
 PVE/Network/SDN/Subnets.pm                    |  4 ++--
 test/ipams/netbox/expected.add_ip_notgateway  |  9 +++++++++
 test/ipams/phpipam/expected.add_ip_notgateway | 12 ++++++++++++
 test/run_test_ipams.pl                        | 18 +++++++++++++++++-
 test/run_test_subnets.pl                      |  8 ++++----
 9 files changed, 75 insertions(+), 14 deletions(-)
 create mode 100644 test/ipams/netbox/expected.add_ip_notgateway
 create mode 100644 test/ipams/phpipam/expected.add_ip_notgateway

diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index 5a03f39..f0e7168 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -93,7 +93,11 @@ sub add_ip {
     };
 
     if ($@) {
-	die "error add subnet ip to ipam: ip already exist: $@" if !$noerr;
+        if($is_gateway) {
+           die "error add subnet ip to ipam: ip $ip already exist: $@" if !is_ip_gateway($url, $ip, $headers) && !$noerr;
+        } else {
+	    die "error add subnet ip to ipam: ip already exist: $@" if !$noerr;
+	}
     }
 }
 
@@ -208,6 +212,14 @@ sub get_ip_id {
     return $ip_id;
 }
 
+sub is_ip_gateway {
+    my ($url, $ip, $headers) = @_;
+    my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
+    my $data = @{$result->{data}}[0];
+    my $description = $data->{description};
+    my $is_gateway = 1 if $description eq 'gateway';
+    return $is_gateway;
+}
 
 1;
 
diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 8fe5bbb..3e8ffc5 100644
--- a/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -95,9 +95,9 @@ sub add_ip {
 	my $dbsubnet = $dbzone->{subnets}->{$cidr};
 	die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
 
-	die "IP '$ip' already exist\n" if defined($dbsubnet->{ips}->{$ip});
-
+	die "IP '$ip' already exist\n" if (!$is_gateway && defined($dbsubnet->{ips}->{$ip})) || ($is_gateway && defined($dbsubnet->{ips}->{$ip}) && !defined($dbsubnet->{ips}->{$ip}->{gateway}));
 	$dbsubnet->{ips}->{$ip} = {};
+	$dbsubnet->{ips}->{$ip} = {gateway => 1} if $is_gateway;
 
 	write_db($db);
     });
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index ed66ea9..ad5286b 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -106,10 +106,10 @@ sub add_ip {
 
     my $params = { ip => $ip,
 		   subnetId => $internalid,
-		   is_gateway => $is_gateway,
 		   hostname => $hostname,
 		   description => $description,
 		  };
+    $params->{is_gateway} = 1 if $is_gateway;
     $params->{mac} = $mac if $mac;
 
     eval {
@@ -117,7 +117,11 @@ sub add_ip {
     };
 
     if ($@) {
-	die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
+	if($is_gateway) {
+	    die "error add subnet ip to ipam: ip $ip already exist: $@" if !is_ip_gateway($url, $ip, $headers) && !$noerr;
+	} else {
+	    die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
+	}
     }
 }
 
@@ -134,10 +138,10 @@ sub update_ip {
     die "can't find ip addresse in ipam" if !$ip_id;
 
     my $params = { 
-		   is_gateway => $is_gateway,
 		   hostname => $hostname,
 		   description => $description,
 		  };
+    $params->{is_gateway} = 1 if $is_gateway;
     $params->{mac} = $mac if $mac;
 
     eval {
@@ -242,6 +246,14 @@ sub get_ip_id {
     return $ip_id;
 }
 
+sub is_ip_gateway {
+    my ($url, $ip, $headers) = @_;
+    my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
+    my $data = @{$result->{data}}[0];
+    my $is_gateway = $data->{is_gateway};
+    return $is_gateway;
+}
+
 1;
 
 
diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm
index b4c8954..15b370f 100644
--- a/PVE/Network/SDN/SubnetPlugin.pm
+++ b/PVE/Network/SDN/SubnetPlugin.pm
@@ -143,7 +143,7 @@ sub on_update_hook {
 	}
         if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
 	    my $hostname = "$vnetid-gw";
-	    my $description = "$vnetid gw";
+	    my $description = "gateway";
 	    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, $description, 1);
 	}
 
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 46d9830..0231822 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -232,7 +232,7 @@ sub next_free_ip {
 }
 
 sub add_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -259,7 +259,7 @@ sub add_ip {
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 
 	eval {
-	    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+	    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway);
 	};
 	die $@ if $@;
     }
diff --git a/test/ipams/netbox/expected.add_ip_notgateway b/test/ipams/netbox/expected.add_ip_notgateway
new file mode 100644
index 0000000..ae876f2
--- /dev/null
+++ b/test/ipams/netbox/expected.add_ip_notgateway
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '{"address":"10.0.0.1/24","description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_headers' => bless( {
+                                         'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
+                                         'content-type' => 'application/json; charset=UTF-8'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'POST',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8000/api/ipam/ip-addresses/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/expected.add_ip_notgateway b/test/ipams/phpipam/expected.add_ip_notgateway
new file mode 100644
index 0000000..7a91359
--- /dev/null
+++ b/test/ipams/phpipam/expected.add_ip_notgateway
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":"mydescription","hostname":"myhostname","ip":"10.0.0.1","mac":"da:65:8f:18:9b:6f","subnetId":1}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'token' => 'Token'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'POST',
+                  '_uri' => bless( do{\(my $o = 'https://localhost/api/apiadmin/addresses/')}, 'URI::https' )
+                }, 'HTTP::Request' );
diff --git a/test/run_test_ipams.pl b/test/run_test_ipams.pl
index 6743eff..27bd441 100755
--- a/test/run_test_ipams.pl
+++ b/test/run_test_ipams.pl
@@ -99,6 +99,9 @@ foreach my $path (@plugins) {
 	},
 	get_ip_id => sub {
 	    return 1;
+	},
+	is_ip_gateway => sub {
+	    return 1;
 	}
     );
 
@@ -146,9 +149,22 @@ foreach my $path (@plugins) {
     $test = "update_ip";
     $expected = Dumper read_sdn_config("$path/expected.$test");
     $name = "$ipamid $test";
-
     $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, 1);
 
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+    ## add_ip_notgateway
+    $is_gateway = undef;
+    $test = "add_ip_notgateway";
+    $expected = Dumper read_sdn_config("$path/expected.$test");
+    $name = "$ipamid $test";
+
+    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, 1);
+
     if ($@) {
 	is ($@, $expected, $name);
     } else {
diff --git a/test/run_test_subnets.pl b/test/run_test_subnets.pl
index 9fca202..f6564e1 100755
--- a/test/run_test_subnets.pl
+++ b/test/run_test_subnets.pl
@@ -135,10 +135,10 @@ foreach my $path (@plugins) {
     $test = "add_ip $ip";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1}}}}}}}';
 
     eval {
-	PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+	PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway);
     };
 
     if ($@) {
@@ -170,7 +170,7 @@ foreach my $path (@plugins) {
     $test = "add_second_ip $ip2";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ip2.'":{}}}}}}}';
 
     eval {
 	PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip2, $hostname, $mac, $description);
@@ -189,7 +189,7 @@ foreach my $path (@plugins) {
     $test = "find_next_freeip ($ipnextfree)";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
 
     eval {
 	$ip3 = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);
-- 
2.20.1




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pve-devel] applied-series:  [pve-network 0/4] updates
  2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
                   ` (3 preceding siblings ...)
  2021-06-04 11:25 ` [pve-devel] [pve-network 4/4] subnets/ipam : fix is_gateway Alexandre Derumier
@ 2021-06-18 16:30 ` Thomas Lamprecht
  4 siblings, 0 replies; 6+ messages in thread
From: Thomas Lamprecht @ 2021-06-18 16:30 UTC (permalink / raw)
  To: Proxmox VE development discussion, Alexandre Derumier

On 04.06.21 13:24, Alexandre Derumier wrote:
> This is a resend of previous sended patches
> + a new patch fixing subnets/ipam is_gateway value
> 
> Alexandre Derumier (4):
>   sdn: get_local_vnets : add ipam && vlanaware values
>   add vnets test + ipam fixes
>   vnets: subroutines: return if !$vnetid
>   subnets/ipam : fix is_gateway


applied series, thanks!




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-06-18 16:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-04 11:24 [pve-devel] [pve-network 0/4] updates Alexandre Derumier
2021-06-04 11:24 ` [pve-devel] [pve-network 1/4] sdn: get_local_vnets : add ipam && vlanaware values Alexandre Derumier
2021-06-04 11:24 ` [pve-devel] [pve-network 2/4] add vnets test + ipam fixes Alexandre Derumier
2021-06-04 11:24 ` [pve-devel] [pve-network 3/4] vnets: subroutines: return if !$vnetid Alexandre Derumier
2021-06-04 11:25 ` [pve-devel] [pve-network 4/4] subnets/ipam : fix is_gateway Alexandre Derumier
2021-06-18 16:30 ` [pve-devel] applied-series: [pve-network 0/4] updates Thomas Lamprecht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal