From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id E825B628D1 for ; Sun, 7 Feb 2021 15:07:34 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id DDA9A19A3B for ; Sun, 7 Feb 2021 15:07:34 +0100 (CET) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1AE8819A33 for ; Sun, 7 Feb 2021 15:07:33 +0100 (CET) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id AFF1DF9DFC; Sun, 7 Feb 2021 15:07:32 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Sun, 7 Feb 2021 15:07:31 +0100 Message-Id: <20210207140731.3276227-1-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.191 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.25 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.4 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [prefix=PATCH V2 pve-network] tests: add subnets tests X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Feb 2021 14:07:34 -0000 Signed-off-by: Alexandre Derumier --- PVE/Network/SDN/Subnets.pm | 2 + test/Makefile | 5 +- test/run_test_subnets.pl | 273 ++++++++++++++++++++++++++++++++++ test/subnets/ipv4/ipam_config | 18 +++ test/subnets/ipv4/sdn_config | 20 +++ test/subnets/ipv6/ipam_config | 18 +++ test/subnets/ipv6/sdn_config | 20 +++ 7 files changed, 355 insertions(+), 1 deletion(-) create mode 100755 test/run_test_subnets.pl create mode 100644 test/subnets/ipv4/ipam_config create mode 100644 test/subnets/ipv4/sdn_config create mode 100644 test/subnets/ipv6/ipam_config create mode 100644 test/subnets/ipv6/sdn_config diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm index 0cbf5fd..56dcd28 100644 --- a/PVE/Network/SDN/Subnets.pm +++ b/PVE/Network/SDN/Subnets.pm @@ -251,9 +251,11 @@ sub add_ip { verify_dns_zone($reversednszone, $reversedns); if ($ipamid) { + 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}); + eval { $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description); }; diff --git a/test/Makefile b/test/Makefile index ca05cf7..eedc4e0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ all: test -test: test_zones test_ipams test_dns +test: test_zones test_ipams test_dns test_subnets test_zones: run_test_zones.pl ./run_test_zones.pl @@ -10,3 +10,6 @@ test_ipams: run_test_ipams.pl test_dns: run_test_dns.pl ./run_test_dns.pl + +test_subnets: run_test_subnets.pl + ./run_test_subnets.pl diff --git a/test/run_test_subnets.pl b/test/run_test_subnets.pl new file mode 100755 index 0000000..6ffa6a3 --- /dev/null +++ b/test/run_test_subnets.pl @@ -0,0 +1,273 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use lib qw(..); +use File::Slurp; + +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( './subnets/', prefix => 1 ) ; + +foreach my $path (@plugins) { + + my (undef, $testid) = split(/\//, $path); + + my $sdn_config = read_sdn_config ("$path/sdn_config"); + + + 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; + my $subnets = $sdn_config->{subnets}->{ids}; + my $subnetid = (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); + $iplist++; + my $ip = $iplist->canon(); + $iplist++; + my $ipnextfree = $iplist->canon(); + $iplist++; + my $ip2 = $iplist->canon(); + + my $ip3 = undef; + my $hostname = "myhostname"; + my $mac = "da:65:8f:18:9b:6f"; + my $description = "mydescription"; + my $is_gateway = 1; + my $ipamdb = {}; + + my $zone = $sdn_config->{zones}->{ids}->{"myzone"}; + + my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve'); + my $sdn_ipam_plugin = Test::MockModule->new($plugin); + $sdn_ipam_plugin->mock( + read_db => sub { + return $ipamdb; + }, + write_db => sub { + my ($cfg) = @_; + $ipamdb = $cfg; + } + ); + + ## add_subnet + my $test = "add_subnet"; + my $name = "$testid $test"; + my $result = undef; + my $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{}}}}}}'; + + eval { + $plugin->add_subnet(undef, $subnetid, $subnet, 1); + }; + + if ($@) { + fail($name); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + + ## add_ip + $test = "add_ip"; + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{}}}}}}}'; + + eval { + PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description); + }; + + if ($@) { + fail("$name : $@"); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + + ## add_already_exist_ip + $test = "add_already_exist_ip"; + $name = "$testid $test"; + + eval { + PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description); + }; + + if ($@) { + is (undef, undef, $name); + } else { + fail("$name : $@"); + } + + ## add_second_ip + $test = "add_second_ip"; + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ip2.'":{}}}}}}}'; + + eval { + PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip2, $hostname, $mac, $description); + }; + + if ($@) { + fail("$name : $@"); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + + + ## add_next_free + $test = "add_next_freeip"; + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}'; + + eval { + $ip3 = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description); + }; + + if ($@) { + fail("$name : $@"); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + + ## del_ip + $test = "del_ip"; + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}'; + + eval { + PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname); + }; + + if ($@) { + fail("$name : $@"); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + + ## del_subnet_not_empty + $test = "del_subnet_not_empty"; + $name = "$testid $test"; + $result = undef; + $expected = undef; + + eval { + PVE::Network::SDN::Subnets::del_subnet($zone, $subnetid, $subnet); + }; + + if ($@) { + is ($result, $expected, $name); + } else { + fail("$name : $@"); + } + + + + ## add_ip_rollback_failing_dns + $test = "add_ip_rollback_failing_dns"; + + $pve_sdn_subnets->mock( + config => sub { + return $sdn_config->{subnets}; + }, + verify_dns_zone => sub { + return; + }, + add_dns_record => sub { + die "error add dns record"; + return; + } + ); + + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}'; + + eval { + PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description); + }; + + if ($@) { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } else { + fail("$name : $@"); + } + + + ## del_empty_subnet + $test = "del_empty_subnet"; + $name = "$testid $test"; + $result = undef; + $expected = '{"zones":{"myzone":{"subnets":{}}}}'; + + PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip2, $hostname); + PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip3, $hostname); + + eval { + PVE::Network::SDN::Subnets::del_subnet($zone, $subnetid, $subnet); + }; + + if ($@) { + fail("$name : $@"); + } else { + $result = $js->encode($plugin->read_db()); + is ($result, $expected, $name); + } + +} + +done_testing(); + + diff --git a/test/subnets/ipv4/ipam_config b/test/subnets/ipv4/ipam_config new file mode 100644 index 0000000..a33be30 --- /dev/null +++ b/test/subnets/ipv4/ipam_config @@ -0,0 +1,18 @@ +{ + 'ids' => { + 'phpipam' => { + 'url' => 'https://localhost/api/apiadmin', + 'type' => 'phpipam', + 'section' => 1, + 'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw' + }, + 'pve' => { + 'type' => 'pve' + }, + 'netbox' => { + 'token' => '0123456789abcdef0123456789abcdef01234567', + 'type' => 'netbox', + 'url' => 'http://localhost:8000/api' + } + }, +} diff --git a/test/subnets/ipv4/sdn_config b/test/subnets/ipv4/sdn_config new file mode 100644 index 0000000..72697d4 --- /dev/null +++ b/test/subnets/ipv4/sdn_config @@ -0,0 +1,20 @@ +{ + version => 1, + vnets => { + ids => { + myvnet => { type => "vnet", zone => "myzone" }, + }, + }, + + zones => { + ids => { myzone => { ipam => "pve", type =>"simple" } }, + }, + + subnets => { + ids => { 'myzone-10.0.0.0-24' => { + 'type' => 'subnet', + 'vnet' => 'myvnet', + } + } + } +} diff --git a/test/subnets/ipv6/ipam_config b/test/subnets/ipv6/ipam_config new file mode 100644 index 0000000..a33be30 --- /dev/null +++ b/test/subnets/ipv6/ipam_config @@ -0,0 +1,18 @@ +{ + 'ids' => { + 'phpipam' => { + 'url' => 'https://localhost/api/apiadmin', + 'type' => 'phpipam', + 'section' => 1, + 'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw' + }, + 'pve' => { + 'type' => 'pve' + }, + 'netbox' => { + 'token' => '0123456789abcdef0123456789abcdef01234567', + 'type' => 'netbox', + 'url' => 'http://localhost:8000/api' + } + }, +} diff --git a/test/subnets/ipv6/sdn_config b/test/subnets/ipv6/sdn_config new file mode 100644 index 0000000..618f234 --- /dev/null +++ b/test/subnets/ipv6/sdn_config @@ -0,0 +1,20 @@ +{ + version => 1, + vnets => { + ids => { + myvnet => { type => "vnet", zone => "myzone" }, + }, + }, + + zones => { + ids => { myzone => { ipam => "pve", type =>"simple" } }, + }, + + subnets => { + ids => { 'myzone-2a0a:1580:2000::-56' => { + 'type' => 'subnet', + 'vnet' => 'myvnet', + } + } + } +} -- 2.20.1