public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests
@ 2021-01-05  9:35 Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 01/15] sdn: pending_config: initialize empty pending key Alexandre Derumier
                   ` (15 more replies)
  0 siblings, 16 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Hello everybody and Happy new year !


This add unit tests for ipams, dns, subnets
and some bugfixes detected with them.

for external ipam/dns api, I'm testing only the expected http query with param.
I think it should be enough.

I have retested all plugins, all methods, I don't have detected bug anymore.

I have send a new pve-container patches serie too.
(no more in RFC, I think the patch is ok now).

I'll try to look at qemu support now.





Small reminder of other related patches:

pve-cluster:

[PATCH V5 pve-cluster 0/5] sdn : add subnets management

https://lists.proxmox.com/pipermail/pve-devel/2020-September/045284.html


pve-common:

INotify: add support for dummy interfaces type

(this is a small patch for ebgp loopback/dummy interface support)

https://www.mail-archive.com/pve-devel@lists.proxmox.com/msg01755.html


pve-docs:

[PATCH pve-docs] update sdn documentation
https://lists.proxmox.com/pipermail/pve-devel/2020-November/046246.html


pve-manager:

[PATCH v10 pve-manager 00/19] sdn: add subnets management

https://lists.proxmox.com/pipermail/pve-devel/2021-January/046589.html

pve-container:

[PATCH pve-container] add ipam support
https://lists.proxmox.com/pipermail/pve-devel/2021-January/046609.html


Alexandre Derumier (15):
  sdn: pending_config: initialize empty pending key
  ipams: add mac address
  ipam: add update_ip
  dns/ipam : move api_request helper to sdn module
  subnets: fix del_ip rollback
  dns: add update record && fix powerdns
  ipam: phpipam: rename get_internal to get_prefix_id (like netbox)
  ipams: add noerr param
  tests: add ipams tests
  dns: add noerr param
  tests: add dns tests
  subnets: convert dns private function to public sub
  subnets: add add_subnet/del_subnet
  tests: add subnets tests
  fix coding style NetAddr::IP->new

 PVE/API2/Network/SDN/Subnets.pm               |  19 +-
 PVE/Network/SDN.pm                            |  49 +++-
 PVE/Network/SDN/Dns/Plugin.pm                 |  57 ++--
 PVE/Network/SDN/Dns/PowerdnsPlugin.pm         | 119 ++++++--
 PVE/Network/SDN/Ipams/NetboxPlugin.pm         |  61 ++--
 PVE/Network/SDN/Ipams/PVEPlugin.pm            |  11 +-
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm        |  80 +++--
 PVE/Network/SDN/Ipams/Plugin.pm               |  64 ++--
 PVE/Network/SDN/SubnetPlugin.pm               |   9 +-
 PVE/Network/SDN/Subnets.pm                    | 132 ++++++---
 PVE/Network/SDN/Vnets.pm                      |  49 ++--
 test/Makefile                                 |  11 +-
 test/dns/powerdns/dns_config                  |  10 +
 .../expected.add_a_multiple_record.ipv4       |  13 +
 .../expected.add_a_multiple_record.ipv6       |  13 +
 test/dns/powerdns/expected.add_a_record.ipv4  |  12 +
 test/dns/powerdns/expected.add_a_record.ipv6  |  13 +
 .../dns/powerdns/expected.add_ptr_record.ipv4 |  13 +
 .../dns/powerdns/expected.add_ptr_record.ipv6 |  12 +
 .../expected.del_a_multiple_record.ipv4       |  13 +
 .../expected.del_a_multiple_record.ipv6       |  12 +
 test/dns/powerdns/expected.del_a_record.ipv4  |  13 +
 test/dns/powerdns/expected.del_a_record.ipv6  |  12 +
 .../dns/powerdns/expected.del_ptr_record.ipv4 |  12 +
 .../dns/powerdns/expected.del_ptr_record.ipv6 |  13 +
 test/dns/powerdns/expected.verify_zone        |  12 +
 test/dns/powerdns/sdn_config                  |  20 ++
 test/ipams/netbox/expected.add_ip             |   9 +
 test/ipams/netbox/expected.add_next_freeip    |   9 +
 test/ipams/netbox/expected.add_subnet         |   9 +
 test/ipams/netbox/expected.del_ip             |   9 +
 test/ipams/netbox/expected.del_subnet         |   9 +
 test/ipams/netbox/expected.update_ip          |   9 +
 test/ipams/netbox/ipam_config                 |  18 ++
 test/ipams/netbox/sdn_config                  |  20 ++
 test/ipams/phpipam/expected.add_ip            |  12 +
 test/ipams/phpipam/expected.add_next_freeip   |  12 +
 test/ipams/phpipam/expected.add_subnet        |  12 +
 test/ipams/phpipam/expected.del_ip            |  12 +
 test/ipams/phpipam/expected.del_subnet        |  12 +
 test/ipams/phpipam/expected.update_ip         |  12 +
 test/ipams/phpipam/ipam_config                |  18 ++
 test/ipams/phpipam/sdn_config                 |  20 ++
 test/run_test_dns.pl                          | 271 +++++++++++++++++
 test/run_test_ipams.pl                        | 181 ++++++++++++
 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 ++
 50 files changed, 1642 insertions(+), 215 deletions(-)
 create mode 100644 test/dns/powerdns/dns_config
 create mode 100644 test/dns/powerdns/expected.add_a_multiple_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_a_multiple_record.ipv6
 create mode 100644 test/dns/powerdns/expected.add_a_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_a_record.ipv6
 create mode 100644 test/dns/powerdns/expected.add_ptr_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_ptr_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_a_multiple_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_a_multiple_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_a_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_a_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_ptr_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_ptr_record.ipv6
 create mode 100644 test/dns/powerdns/expected.verify_zone
 create mode 100644 test/dns/powerdns/sdn_config
 create mode 100644 test/ipams/netbox/expected.add_ip
 create mode 100644 test/ipams/netbox/expected.add_next_freeip
 create mode 100644 test/ipams/netbox/expected.add_subnet
 create mode 100644 test/ipams/netbox/expected.del_ip
 create mode 100644 test/ipams/netbox/expected.del_subnet
 create mode 100644 test/ipams/netbox/expected.update_ip
 create mode 100644 test/ipams/netbox/ipam_config
 create mode 100644 test/ipams/netbox/sdn_config
 create mode 100644 test/ipams/phpipam/expected.add_ip
 create mode 100644 test/ipams/phpipam/expected.add_next_freeip
 create mode 100644 test/ipams/phpipam/expected.add_subnet
 create mode 100644 test/ipams/phpipam/expected.del_ip
 create mode 100644 test/ipams/phpipam/expected.del_subnet
 create mode 100644 test/ipams/phpipam/expected.update_ip
 create mode 100644 test/ipams/phpipam/ipam_config
 create mode 100644 test/ipams/phpipam/sdn_config
 create mode 100755 test/run_test_dns.pl
 create mode 100755 test/run_test_ipams.pl
 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

-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 01/15] sdn: pending_config: initialize empty pending key
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 02/15] ipams: add mac address Alexandre Derumier
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN.pm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 256a7c8..a20233a 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -104,6 +104,7 @@ sub pending_config {
 		$pending->{$id}->{state} = "changed";
 	    }
 	}
+	$pending->{$id}->{"pending"} = {} if $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
     }
 
    foreach my $id (sort keys %{$config_objects}) {
@@ -124,6 +125,7 @@ sub pending_config {
 		$pending->{$id}->{state} = "changed";
 	    }
 	}
+	$pending->{$id}->{"pending"} = {} if  $pending->{$id}->{state} && !defined($pending->{$id}->{"pending"});
    }
 
    return {ids => $pending};
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 02/15] ipams: add mac address
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 01/15] sdn: pending_config: initialize empty pending key Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 03/15] ipam: add update_ip Alexandre Derumier
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Ipams/NetboxPlugin.pm  | 6 ++++--
 PVE/Network/SDN/Ipams/PVEPlugin.pm     | 4 ++--
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 7 +++++--
 PVE/Network/SDN/Ipams/Plugin.pm        | 4 ++--
 PVE/Network/SDN/SubnetPlugin.pm        | 4 +++-
 PVE/Network/SDN/Subnets.pm             | 8 ++++----
 PVE/Network/SDN/Vnets.pm               | 8 ++++----
 7 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index 298634d..3c99218 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -77,13 +77,14 @@ sub del_subnet {
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
     my $mask = $subnet->{mask};
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $section = $plugin_config->{section};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+    $description .= " mac:$mac" if $mac && $description;
 
     my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
 
@@ -97,7 +98,7 @@ sub add_ip {
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
     my $cidr = $subnet->{cidr};
 
@@ -106,6 +107,7 @@ sub add_next_freeip {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
     my $internalid = get_prefix_id($url, $cidr, $headers);
+    $description .= " mac:$mac" if $mac && $description;
 
     my $params = { dns_name => $hostname, description => $description };
 
diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 4925274..c02b6db 100644
--- a/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -82,7 +82,7 @@ sub del_subnet {
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
     my $cidr = $subnet->{cidr};
     my $zone = $subnet->{zone};
@@ -106,7 +106,7 @@ sub add_ip {
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
     my $cidr = $subnet->{cidr};
     my $network = $subnet->{network};
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index 6261764..ab06f7b 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -95,7 +95,7 @@ sub del_subnet {
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
     my $cidr = $subnet->{cidr};
     my $url = $plugin_config->{url};
@@ -111,6 +111,7 @@ sub add_ip {
 		   hostname => $hostname,
 		   description => $description,
 		  };
+    $params->{mac} = $mac if $mac;
 
     eval {
 	PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/addresses/", $headers, $params);
@@ -122,7 +123,7 @@ sub add_ip {
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
     my $cidr = $subnet->{cidr};  
     my $mask = $subnet->{mask};  
@@ -137,6 +138,8 @@ sub add_next_freeip {
 		   description => $description,
 		  };
 
+    $params->{mac} = $mac if $mac;
+
     my $ip = undef;
     eval {
 	my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/addresses/first_free/$internalid/", $headers, $params);
diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plugin.pm
index 065225c..10e5212 100644
--- a/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/PVE/Network/SDN/Ipams/Plugin.pm
@@ -75,12 +75,12 @@ sub del_subnet {
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 }
 
 sub del_ip {
diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm
index 2d6d808..68efeb6 100644
--- a/PVE/Network/SDN/SubnetPlugin.pm
+++ b/PVE/Network/SDN/SubnetPlugin.pm
@@ -113,11 +113,13 @@ sub on_update_hook {
     my $reversedns = $zone->{reversedns};
 
     my $old_gateway = $old_subnet->{gateway} if $old_subnet;
+    my $mac = undef;
 
     if($vnetid) {
 	my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
 	raise_param_exc({ vnet => "$vnetid don't exist"}) if !$vnet;
 	raise_param_exc({ vnet => "you can't add a subnet on a vlanaware vnet"}) if $vnet->{vlanaware};
+	$mac = $vnet->{mac};
     }
 
     my $pointopoint = 1 if Net::IP::ip_is_ipv4($gateway) && $mask == 32;
@@ -145,7 +147,7 @@ sub on_update_hook {
         if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
 	    my $hostname = "$vnetid-gw";
 	    my $description = "$vnetid gw";
-	    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $description, 1);
+	    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, $description, 1);
 	}
 
 	#delete old gateway after update
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 81970a1..b752e2c 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -162,7 +162,7 @@ my $del_dns_ptr_record = sub {
 };
 
 sub next_free_ip {
-    my ($zone, $subnetid, $subnet, $hostname, $description) = @_;
+    my ($zone, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
     my $cidr = undef;
     my $ip = undef;
@@ -184,7 +184,7 @@ sub next_free_ip {
 	my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 	eval {
-	    $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $description);
+	    $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $description);
 	    ($ip, undef) = split(/\//, $cidr);
 	};
 	die $@ if $@;
@@ -210,7 +210,7 @@ sub next_free_ip {
 }
 
 sub add_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $description) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -235,7 +235,7 @@ sub add_ip {
 	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, $description);
+	    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description);
 	};
 	die $@ if $@;
     }
diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index 1da1d57..d68ffab 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -80,7 +80,7 @@ sub get_subnets {
 }
 
 sub get_next_free_cidr {
-    my ($vnetid, $hostname, $description, $ipversion) = @_;
+    my ($vnetid, $hostname, $mac, $description, $ipversion) = @_;
 
     my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
     my $zoneid = $vnet->{zone};
@@ -99,7 +99,7 @@ sub get_next_free_cidr {
 	$subnetcount++;
 	if ($zone->{ipam}) {
 	    eval {
-		$ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $description);
+		$ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);
 	    };
 	    warn $@ if $@;
 	}
@@ -111,7 +111,7 @@ sub get_next_free_cidr {
 }
 
 sub add_cidr {
-    my ($vnetid, $cidr, $hostname, $description) = @_;
+    my ($vnetid, $cidr, $hostname, $mac, $description) = @_;
 
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
     my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
@@ -122,7 +122,7 @@ sub add_cidr {
     die "ip address is not in cidr format" if !$mask;
     my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
 
-    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $description);
+    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
 }
 
 sub del_cidr {
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 03/15] ipam: add update_ip
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 01/15] sdn: pending_config: initialize empty pending key Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 02/15] ipams: add mac address Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 04/15] dns/ipam : move api_request helper to sdn module Alexandre Derumier
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

used to update ip address options like hostname, mac,...

don't allow to change ip address, as some ipam don't support it.

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Ipams/NetboxPlugin.pm  | 23 ++++++++++++++
 PVE/Network/SDN/Ipams/PVEPlugin.pm     |  5 +++
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 28 +++++++++++++++++
 PVE/Network/SDN/Ipams/Plugin.pm        | 17 ++++++++++
 PVE/Network/SDN/Subnets.pm             | 39 +++++++++++++++++++++++
 PVE/Network/SDN/Vnets.pm               | 43 ++++++++++++++++----------
 6 files changed, 138 insertions(+), 17 deletions(-)

diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index 3c99218..f699daa 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -97,6 +97,29 @@ sub add_ip {
     }
 }
 
+sub update_ip {
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+
+    my $mask = $subnet->{mask};
+    my $url = $plugin_config->{url};
+    my $token = $plugin_config->{token};
+    my $section = $plugin_config->{section};
+    my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+    $description .= " mac:$mac" if $mac && $description;
+
+    my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
+
+    my $ip_id = get_ip_id($url, $ip, $headers);
+    die "can't find ip $ip in ipam" if !$ip_id;
+
+    eval {
+	PVE::Network::SDN::Ipams::Plugin::api_request("PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params);
+    };
+    if ($@) {
+	die "error update ip $ip : $@";
+    }
+}
+
 sub add_next_freeip {
     my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
index c02b6db..2527850 100644
--- a/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -105,6 +105,11 @@ sub add_ip {
     die "$@" if $@;
 }
 
+sub update_ip {
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    return;
+}
+
 sub add_next_freeip {
     my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index ab06f7b..b5ff38c 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -122,6 +122,34 @@ sub add_ip {
     }
 }
 
+sub update_ip {
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+
+    my $cidr = $subnet->{cidr};
+    my $url = $plugin_config->{url};
+    my $token = $plugin_config->{token};
+    my $section = $plugin_config->{section};
+    my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
+
+    my $ip_id = get_ip_id($url, $ip, $headers);
+    die "can't find ip addresse in ipam" if !$ip_id;
+
+    my $params = { 
+		   is_gateway => $is_gateway,
+		   hostname => $hostname,
+		   description => $description,
+		  };
+    $params->{mac} = $mac if $mac;
+
+    eval {
+	PVE::Network::SDN::Ipams::Plugin::api_request("PATCH", "$url/addresses/$ip_id", $headers, $params);
+    };
+
+    if ($@) {
+	die "ipam: error update subnet ip $ip: $@";
+    }
+}
+
 sub add_next_freeip {
     my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plugin.pm
index 10e5212..39675f2 100644
--- a/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/PVE/Network/SDN/Ipams/Plugin.pm
@@ -68,23 +68,40 @@ sub parse_section_header {
 
 sub add_subnet {
     my ($class, $plugin_config, $subnetid, $subnet) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub del_subnet {
     my ($class, $plugin_config, $subnetid, $subnet) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub add_ip {
     my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
+    die "please implement inside plugin";
+}
+
+sub update_ip {
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    # only update ip attributes (mac,hostname,..). Don't change the ip addresses itself, as some ipam
+    # don't allow ip address change without del/add
+
+    die "please implement inside plugin";
 }
 
 sub add_next_freeip {
     my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub del_ip {
     my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub on_update_hook {
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index b752e2c..808c1bf 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -256,6 +256,45 @@ sub add_ip {
     }
 }
 
+sub update_ip {
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_;
+
+    return if !$subnet || !$ip; 
+
+    my $ipaddr = new NetAddr::IP($ip);
+    $ip = $ipaddr->canon();
+
+    my $ipamid = $zone->{ipam};
+    my $dns = $zone->{dns};
+    my $dnszone = $zone->{dnszone};
+    my $reversedns = $zone->{reversedns};
+    my $reversednszone = &$get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+    my $dnszoneprefix = $subnet->{dnszoneprefix};
+
+    $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
+
+    #verify dns zones before ipam
+    &$verify_dns_zone($dnszone, $dns);
+    &$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->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+	};
+	die $@ if $@;
+    }
+
+    eval {
+	#add dns
+	&$add_dns_record($dnszone, $dns, $hostname, $ip);
+	#add reverse dns
+	&$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+    };
+}
+
 sub del_ip {
     my ($zone, $subnetid, $subnet, $ip, $hostname) = @_;
 
diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index d68ffab..7421adf 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -79,6 +79,22 @@ sub get_subnets {
 
 }
 
+sub get_subnet_from_vnet_cidr {
+    my ($vnetid, $cidr) = @_;
+
+    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
+    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    my $zoneid = $vnet->{zone};
+    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+    my ($ip, $mask) = split(/\//, $cidr);
+    die "ip address is not in cidr format" if !$mask;
+
+    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
+
+    return ($zone, $subnetid, $subnet, $ip);
+}
+
 sub get_next_free_cidr {
     my ($vnetid, $hostname, $mac, $description, $ipversion) = @_;
 
@@ -113,31 +129,24 @@ sub get_next_free_cidr {
 sub add_cidr {
     my ($vnetid, $cidr, $hostname, $mac, $description) = @_;
 
-    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
-    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
-    my $zoneid = $vnet->{zone};
-    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+    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);
+}
 
-    my ($ip, $mask) = split(/\//, $cidr);
-    die "ip address is not in cidr format" if !$mask;
-    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
+sub update_cidr {
+    my ($vnetid, $cidr, $hostname, $mac, $description) = @_;
 
-    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+    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, $mac, $description);
 }
 
 sub del_cidr {
     my ($vnetid, $cidr, $hostname) = @_;
 
-    my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
-    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
-    my $zoneid = $vnet->{zone};
-    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
-
-    my ($ip, $mask) = split(/\//, $cidr);
-    die "ip address is not in cidr format" if !$mask;
-    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
-
+    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);
 }
 
+
+
 1;
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 04/15] dns/ipam : move api_request helper to sdn module
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (2 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 03/15] ipam: add update_ip Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 05/15] subnets: fix del_ip rollback Alexandre Derumier
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN.pm                     | 47 +++++++++++++++++++++++++-
 PVE/Network/SDN/Dns/Plugin.pm          | 37 --------------------
 PVE/Network/SDN/Dns/PowerdnsPlugin.pm  | 12 +++----
 PVE/Network/SDN/Ipams/NetboxPlugin.pm  | 18 +++++-----
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 18 +++++-----
 PVE/Network/SDN/Ipams/Plugin.pm        | 37 --------------------
 6 files changed, 70 insertions(+), 99 deletions(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index a20233a..befaaee 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -232,5 +232,50 @@ sub encode_value {
     return $value;
 }
 
-1;
 
+#helpers
+sub api_request {
+    my ($method, $url, $headers, $data) = @_;
+
+    my $encoded_data = to_json($data) if $data;
+
+    my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
+
+    my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
+    my $proxy = undef;
+
+    if ($proxy) {
+        $ua->proxy(['http', 'https'], $proxy);
+    } else {
+        $ua->env_proxy;
+    }
+
+    $ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0x00);
+
+    my $response = $ua->request($req);
+    my $code = $response->code;
+
+    if ($code !~ /^2(\d+)$/) {
+        my $msg = $response->message || 'unknown';
+        die "Invalid response from server: $code $msg\n";
+    }
+
+    my $raw = '';
+    if (defined($response->decoded_content)) {
+	$raw = $response->decoded_content;
+    } else {
+	$raw = $response->content;
+    }
+
+    return if $raw eq '';
+
+    my $json = '';
+    eval {
+	$json = from_json($raw);
+    };
+    die "api response is not a json" if $@;
+
+    return $json;
+}
+
+1;
diff --git a/PVE/Network/SDN/Dns/Plugin.pm b/PVE/Network/SDN/Dns/Plugin.pm
index be399b0..ef866b7 100644
--- a/PVE/Network/SDN/Dns/Plugin.pm
+++ b/PVE/Network/SDN/Dns/Plugin.pm
@@ -8,7 +8,6 @@ use PVE::JSONSchema;
 use PVE::Cluster;
 use HTTP::Request;
 use LWP::UserAgent;
-use JSON;
 
 use Data::Dumper;
 use PVE::JSONSchema qw(get_standard_option);
@@ -79,40 +78,4 @@ sub on_update_hook {
     my ($class, $plugin_config) = @_;
 }
 
-#helpers
-sub api_request {
-    my ($method, $url, $headers, $data) = @_;
-
-    my $encoded_data = to_json($data) if $data;
-
-    my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
-
-    my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
-    my $proxy = undef;
-
-    if ($proxy) {
-        $ua->proxy(['http', 'https'], $proxy);
-    } else {
-        $ua->env_proxy;
-    }
-
-    $ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0x00);
-
-    my $response = $ua->request($req);
-    my $code = $response->code;
-
-    if ($code !~ /^2(\d+)$/) {
-        my $msg = $response->message || 'unknown';
-        die "Invalid response from server: $code $msg\n";
-    }
-
-    my $raw = '';
-    if (defined($response->decoded_content)) {
-	$raw = $response->decoded_content;
-    } else {
-	$raw = $response->content;
-    }
-    return from_json($raw) if $raw ne '';
-}
-
 1;
diff --git a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
index 3fbd595..4c00a26 100644
--- a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
+++ b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
@@ -69,7 +69,7 @@ sub add_a_record {
     my $params = { rrsets => [ $rrset ] };
 
     eval {
-	PVE::Network::SDN::Dns::Plugin::api_request("PATCH", "$url/zones/$zone", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
     };
 
     if ($@) {
@@ -106,7 +106,7 @@ sub add_ptr_record {
     my $params = { rrsets => [ $rrset ] };
 
     eval {
-	PVE::Network::SDN::Dns::Plugin::api_request("PATCH", "$url/zones/$zone", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
     };
 
     if ($@) {
@@ -131,7 +131,7 @@ sub del_a_record {
     my $params = { rrsets => [ $rrset ] };
 
     eval {
-	PVE::Network::SDN::Dns::Plugin::api_request("PATCH", "$url/zones/$zone", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
     };
 
     if ($@) {
@@ -158,7 +158,7 @@ sub del_ptr_record {
     my $params = { rrsets => [ $rrset ] };
 
     eval {
-	PVE::Network::SDN::Dns::Plugin::api_request("PATCH", "$url/zones/$zone", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
     };
 
     if ($@) {
@@ -176,7 +176,7 @@ sub verify_zone {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
 
     eval {
-        PVE::Network::SDN::Dns::Plugin::api_request("GET", "$url/zones/$zone", $headers);
+        PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers);
     };
 
     if ($@) {
@@ -241,7 +241,7 @@ sub on_update_hook {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
 
     eval {
-	PVE::Network::SDN::Dns::Plugin::api_request("GET", "$url", $headers);
+	PVE::Network::SDN::api_request("GET", "$url", $headers);
     };
 
     if ($@) {
diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index f699daa..eae2e59 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -44,7 +44,7 @@ sub add_subnet {
 	my $params = { prefix => $cidr };
 
 	eval {
-		my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/prefixes/", $headers, $params);
+		my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/prefixes/", $headers, $params);
 	};
 	if ($@) {
 	    die "error add subnet to ipam: $@";
@@ -68,7 +68,7 @@ sub del_subnet {
     return; #fixme: check that prefix is empty exluding gateway, before delete
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
+	PVE::Network::SDN::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
     };
     if ($@) {
 	die "error deleting subnet from ipam: $@";
@@ -89,7 +89,7 @@ sub add_ip {
     my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/ip-addresses/", $headers, $params);
+	PVE::Network::SDN::api_request("POST", "$url/ipam/ip-addresses/", $headers, $params);
     };
 
     if ($@) {
@@ -113,7 +113,7 @@ sub update_ip {
     die "can't find ip $ip in ipam" if !$ip_id;
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params);
     };
     if ($@) {
 	die "error update ip $ip : $@";
@@ -136,7 +136,7 @@ sub add_next_freeip {
 
     my $ip = undef;
     eval {
-	my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/prefixes/$internalid/available-ips/", $headers, $params);
+	my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/prefixes/$internalid/available-ips/", $headers, $params);
 	$ip = $result->{address};
     };
 
@@ -160,7 +160,7 @@ sub del_ip {
     die "can't find ip $ip in ipam" if !$ip_id;
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers);
+	PVE::Network::SDN::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers);
     };
     if ($@) {
 	die "error delete ip $ip : $@";
@@ -176,7 +176,7 @@ sub verify_api {
 
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/aggregates/", $headers);
+	PVE::Network::SDN::api_request("GET", "$url/ipam/aggregates/", $headers);
     };
     if ($@) {
 	die "Can't connect to netbox api: $@";
@@ -194,7 +194,7 @@ sub on_update_hook {
 sub get_prefix_id {
     my ($url, $cidr, $headers) = @_;
 
-    my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/prefixes/?q=$cidr", $headers);
+    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/prefixes/?q=$cidr", $headers);
     my $data = @{$result->{results}}[0];
     my $internalid = $data->{id};
     return $internalid;
@@ -202,7 +202,7 @@ sub get_prefix_id {
 
 sub get_ip_id {
     my ($url, $ip, $headers) = @_;
-    my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers);
+    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers);
     my $data = @{$result->{results}}[0];
     my $ip_id = $data->{id};
     return $ip_id;
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index b5ff38c..7147916 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -62,7 +62,7 @@ sub add_subnet {
 		  };
 
 	eval {
-		PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/subnets/", $headers, $params);
+		PVE::Network::SDN::api_request("POST", "$url/subnets/", $headers, $params);
 	};
 	if ($@) {
 	    die "error add subnet to ipam: $@";
@@ -86,7 +86,7 @@ sub del_subnet {
     return; #fixme: check that prefix is empty exluding gateway, before delete
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/subnets/$internalid", $headers);
+	PVE::Network::SDN::api_request("DELETE", "$url/subnets/$internalid", $headers);
     };
     if ($@) {
 	die "error deleting subnet from ipam: $@";
@@ -114,7 +114,7 @@ sub add_ip {
     $params->{mac} = $mac if $mac;
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/addresses/", $headers, $params);
+	PVE::Network::SDN::api_request("POST", "$url/addresses/", $headers, $params);
     };
 
     if ($@) {
@@ -142,7 +142,7 @@ sub update_ip {
     $params->{mac} = $mac if $mac;
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("PATCH", "$url/addresses/$ip_id", $headers, $params);
+	PVE::Network::SDN::api_request("PATCH", "$url/addresses/$ip_id", $headers, $params);
     };
 
     if ($@) {
@@ -170,7 +170,7 @@ sub add_next_freeip {
 
     my $ip = undef;
     eval {
-	my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/addresses/first_free/$internalid/", $headers, $params);
+	my $result = PVE::Network::SDN::api_request("POST", "$url/addresses/first_free/$internalid/", $headers, $params);
 	$ip = $result->{data};
     };
 
@@ -194,7 +194,7 @@ sub del_ip {
     return if !$ip_id;
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/addresses/$ip_id", $headers);
+	PVE::Network::SDN::api_request("DELETE", "$url/addresses/$ip_id", $headers);
     };
     if ($@) {
 	die "error delete ip $ip: $@";
@@ -210,7 +210,7 @@ sub verify_api {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
 
     eval {
-	PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/sections/$sectionid", $headers);
+	PVE::Network::SDN::api_request("GET", "$url/sections/$sectionid", $headers);
     };
     if ($@) {
 	die "Can't connect to phpipam api: $@";
@@ -229,7 +229,7 @@ sub on_update_hook {
 sub get_internalid {
     my ($url, $cidr, $headers) = @_;
 
-    my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/subnets/cidr/$cidr", $headers);
+    my $result = PVE::Network::SDN::api_request("GET", "$url/subnets/cidr/$cidr", $headers);
     my $data = @{$result->{data}}[0];
     my $internalid = $data->{id};
     return $internalid;
@@ -237,7 +237,7 @@ sub get_internalid {
 
 sub get_ip_id {
     my ($url, $ip, $headers) = @_;
-    my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/addresses/search/$ip", $headers);
+    my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
     my $data = @{$result->{data}}[0];
     my $ip_id = $data->{id};
     return $ip_id;
diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plugin.pm
index 39675f2..a4c7dcb 100644
--- a/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/PVE/Network/SDN/Ipams/Plugin.pm
@@ -108,41 +108,4 @@ sub on_update_hook {
     my ($class, $plugin_config)  = @_;
 }
 
-
-#helpers
-sub api_request {
-    my ($method, $url, $headers, $data) = @_;
-
-    my $encoded_data = to_json($data) if $data;
-
-    my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
-
-    my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 30);
-    my $proxy = undef;
-
-    if ($proxy) {
-        $ua->proxy(['http', 'https'], $proxy);
-    } else {
-        $ua->env_proxy;
-    }
-
-    $ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0x00);
-
-    my $response = $ua->request($req);
-    my $code = $response->code;
-
-    if ($code !~ /^2(\d+)$/) {
-        my $msg = $response->message || 'unknown';
-        die "Invalid response from server: $code $msg\n";
-    }
-
-    my $raw = '';
-    if (defined($response->decoded_content)) {
-	$raw = $response->decoded_content;
-    } else {
-	$raw = $response->content;
-    }
-    return from_json($raw) if $raw ne '';
-}
-
 1;
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 05/15] subnets: fix del_ip rollback
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (3 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 04/15] dns/ipam : move api_request helper to sdn module Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 06/15] dns: add update record && fix powerdns Alexandre Derumier
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Subnets.pm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 808c1bf..5446044 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -202,7 +202,7 @@ sub next_free_ip {
 	#rollback
 	my $err = $@;
 	eval {
-	    PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname)
+	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname)
 	};
 	die $err;
     }
@@ -250,7 +250,7 @@ sub add_ip {
 	#rollback
 	my $err = $@;
 	eval {
-	    PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname)
+	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname)
 	};
 	die $err;
     }
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 06/15] dns: add update record && fix powerdns
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (4 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 05/15] subnets: fix del_ip rollback Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 07/15] ipam: phpipam: rename get_internal to get_prefix_id (like netbox) Alexandre Derumier
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Dns/Plugin.pm         | 32 +++++++++-
 PVE/Network/SDN/Dns/PowerdnsPlugin.pm | 87 +++++++++++++++++++++++++--
 PVE/Network/SDN/Subnets.pm            |  7 ++-
 PVE/Network/SDN/Vnets.pm              |  4 +-
 4 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/PVE/Network/SDN/Dns/Plugin.pm b/PVE/Network/SDN/Dns/Plugin.pm
index ef866b7..199c170 100644
--- a/PVE/Network/SDN/Dns/Plugin.pm
+++ b/PVE/Network/SDN/Dns/Plugin.pm
@@ -67,11 +67,39 @@ sub parse_section_header {
 
 
 sub add_a_record {
-    my ($class, $plugin_config, $type, $zone, $reversezone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+
+    die "please implement inside plugin";
+}
+
+sub add_ptr_record {
+    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+
+    die "please implement inside plugin";
+}
+
+sub del_ptr_record {
+    my ($class, $plugin_config, $zone, $ip) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub del_a_record {
-    my ($class, $plugin_config, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+
+    die "please implement inside plugin";
+}
+
+sub verify_zone {
+    my ($class, $plugin_config, $zone) = @_;
+
+    die "please implement inside plugin";
+}
+
+sub get_reversedns_zone {
+    my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
+
+    die "please implement inside plugin";
 }
 
 sub on_update_hook {
diff --git a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
index 4c00a26..d93fb06 100644
--- a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
+++ b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
@@ -52,6 +52,19 @@ sub add_a_record {
     my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
     my $fqdn = $hostname.".".$zone.".";
 
+    my $zonecontent = get_zone_content($plugin_config, $zone);
+    my $existing_rrset = get_zone_rrset($zonecontent, $fqdn);
+
+    my $final_records = [];
+    my $foundrecord = undef;
+    foreach my $record (@{$existing_rrset->{records}}) {
+	if($record->{content} eq $ip) {
+	    $foundrecord = 1;
+	    next;
+	}
+	push @$final_records, $record;
+    }
+    return if $foundrecord;
 
     my $record = { content => $ip, 
                    disabled => JSON::false, 
@@ -59,11 +72,13 @@ sub add_a_record {
                    type => $type, 
                    priority => 0 };
 
+    push @$final_records, $record;
+
     my $rrset = { name => $fqdn, 
 		  type => $type, 
                    ttl =>  $ttl, 
 		  changetype => "REPLACE",
-		  records => [ $record ] };
+		  records => $final_records  };
 
 
     my $params = { rrsets => [ $rrset ] };
@@ -123,10 +138,37 @@ sub del_a_record {
     my $fqdn = $hostname.".".$zone.".";
     my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
 
-    my $rrset = { name => $fqdn, 
-		  type => $type, 
-		  changetype => "DELETE",
-		  records => [] };
+    my $zonecontent = get_zone_content($plugin_config, $zone);
+    my $existing_rrset = get_zone_rrset($zonecontent, $fqdn);
+
+    my $final_records = [];
+    my $foundrecord = undef;
+    foreach my $record (@{$existing_rrset->{records}}) {
+        if ($record->{content} eq $ip) {
+	    $foundrecord = 1;
+	    next;
+	}
+	push @$final_records, $record;
+    }
+    return if !$foundrecord;
+ 
+    my $rrset = {};
+   
+    if (scalar (@{$final_records}) > 0) {
+	#if we still have other records, we rewrite them without removed ip
+	$rrset = { name => $fqdn,
+		   type => $type,
+		   ttl =>  $existing_rrset->{ttl},
+		   changetype => "REPLACE",
+		   records => $final_records  };
+
+    } else {
+
+	$rrset = { name => $fqdn, 
+		   type => $type, 
+		   changetype => "DELETE",
+		    records => [] };
+    }
 
     my $params = { rrsets => [ $rrset ] };
 
@@ -176,7 +218,7 @@ sub verify_zone {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
 
     eval {
-        PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers);
+        PVE::Network::SDN::api_request("GET", "$url/zones/$zone?rrsets=false", $headers);
     };
 
     if ($@) {
@@ -249,6 +291,39 @@ sub on_update_hook {
     }
 }
 
+
+sub get_zone_content {
+    my ($plugin_config, $zone) = @_;
+
+    #verify that api is working              
+
+    my $url = $plugin_config->{url};
+    my $key = $plugin_config->{key};
+    my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
+
+    my $result = undef;
+    eval {
+        $result = PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers);
+    };
+
+    if ($@) {
+        die "can't read zone $zone: $@";
+    }
+    return $result;
+}
+
+sub get_zone_rrset {
+    my ($zonecontent, $name) = @_;
+
+    my $rrsetresult = undef;
+    foreach my $rrset (@{$zonecontent->{rrsets}}) {
+	next if $rrset->{name} ne $name;
+        $rrsetresult = $rrset;
+	last; 
+    }
+    return $rrsetresult;
+}
+
 1;
 
 
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 5446044..25261ac 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -257,7 +257,7 @@ sub add_ip {
 }
 
 sub update_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -287,10 +287,15 @@ sub update_ip {
 	die $@ if $@;
     }
 
+    return if $hostname eq $oldhostname;
+
     eval {
 	#add dns
+	
+	&$del_dns_record($dnszone, $dns, $oldhostname, $ip);
 	&$add_dns_record($dnszone, $dns, $hostname, $ip);
 	#add reverse dns
+	&$del_dns_ptr_record($reversednszone, $reversedns, $ip);
 	&$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
     };
 }
diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm
index 7421adf..ff39eef 100644
--- a/PVE/Network/SDN/Vnets.pm
+++ b/PVE/Network/SDN/Vnets.pm
@@ -134,10 +134,10 @@ sub add_cidr {
 }
 
 sub update_cidr {
-    my ($vnetid, $cidr, $hostname, $mac, $description) = @_;
+    my ($vnetid, $cidr, $hostname, $oldhostname, $mac, $description) = @_;
 
     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, $mac, $description);
+    PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description);
 }
 
 sub del_cidr {
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 07/15] ipam: phpipam: rename get_internal to get_prefix_id (like netbox)
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (5 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 06/15] dns: add update record && fix powerdns Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 08/15] ipams: add noerr param Alexandre Derumier
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index 7147916..235d553 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -51,7 +51,7 @@ sub add_subnet {
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
 
     #search subnet
-    my $internalid = get_internalid($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers);
 
     #create subnet
     if (!$internalid) {
@@ -80,7 +80,7 @@ sub del_subnet {
     my $section = $plugin_config->{section};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
 
-    my $internalid = get_internalid($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers);
     return if !$internalid;
 
     return; #fixme: check that prefix is empty exluding gateway, before delete
@@ -103,7 +103,7 @@ sub add_ip {
     my $section = $plugin_config->{section};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
 
-    my $internalid = get_internalid($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers);
 
     my $params = { ip => $ip,
 		   subnetId => $internalid,
@@ -160,7 +160,7 @@ sub add_next_freeip {
     my $section = $plugin_config->{section};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
 
-    my $internalid = get_internalid($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers);
 
     my $params = { hostname => $hostname,
 		   description => $description,
@@ -226,7 +226,7 @@ sub on_update_hook {
 
 #helpers
 
-sub get_internalid {
+sub get_prefix_id {
     my ($url, $cidr, $headers) = @_;
 
     my $result = PVE::Network::SDN::api_request("GET", "$url/subnets/cidr/$cidr", $headers);
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 08/15] ipams: add noerr param
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (6 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 07/15] ipam: phpipam: rename get_internal to get_prefix_id (like netbox) Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 09/15] tests: add ipams tests Alexandre Derumier
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Ipams/NetboxPlugin.pm  | 24 +++++++++++------------
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 27 +++++++++++++-------------
 PVE/Network/SDN/Ipams/Plugin.pm        | 12 ++++++------
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index eae2e59..5a03f39 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -28,7 +28,7 @@ sub options {
 # Plugin implementation
 
 sub add_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $gateway = $subnet->{gateway};
@@ -47,14 +47,14 @@ sub add_subnet {
 		my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/prefixes/", $headers, $params);
 	};
 	if ($@) {
-	    die "error add subnet to ipam: $@";
+	    die "error add subnet to ipam: $@" if !$noerr;
 	}
     }
    
 }
 
 sub del_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $url = $plugin_config->{url};
@@ -71,13 +71,13 @@ sub del_subnet {
 	PVE::Network::SDN::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
     };
     if ($@) {
-	die "error deleting subnet from ipam: $@";
+	die "error deleting subnet from ipam: $@" if !$noerr;
     }
 
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
 
     my $mask = $subnet->{mask};
     my $url = $plugin_config->{url};
@@ -93,12 +93,12 @@ sub add_ip {
     };
 
     if ($@) {
-	die "error add subnet ip to ipam: ip already exist: $@";
+	die "error add subnet ip to ipam: ip already exist: $@" if !$noerr;
     }
 }
 
 sub update_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
 
     my $mask = $subnet->{mask};
     my $url = $plugin_config->{url};
@@ -116,12 +116,12 @@ sub update_ip {
 	PVE::Network::SDN::api_request("PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params);
     };
     if ($@) {
-	die "error update ip $ip : $@";
+	die "error update ip $ip : $@" if !$noerr;
     }
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
 
@@ -141,14 +141,14 @@ sub add_next_freeip {
     };
 
     if ($@) {
-	die "can't find free ip in subnet $cidr: $@";
+	die "can't find free ip in subnet $cidr: $@" if !$noerr;
     }
 
     return $ip;
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $noerr) = @_;
 
     return if !$ip;
 
@@ -163,7 +163,7 @@ sub del_ip {
 	PVE::Network::SDN::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers);
     };
     if ($@) {
-	die "error delete ip $ip : $@";
+	die "error delete ip $ip : $@" if !$noerr;
     }
 }
 
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index 235d553..ed66ea9 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -38,7 +38,7 @@ sub options {
 # Plugin implementation
 
 sub add_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $network = $subnet->{network};
@@ -55,7 +55,6 @@ sub add_subnet {
 
     #create subnet
     if (!$internalid) {
-
 	my $params = { subnet => $network,
 		   mask => $mask,
 		   sectionId => $section,
@@ -65,14 +64,14 @@ sub add_subnet {
 		PVE::Network::SDN::api_request("POST", "$url/subnets/", $headers, $params);
 	};
 	if ($@) {
-	    die "error add subnet to ipam: $@";
+	    die "error add subnet to ipam: $@" if !$noerr;
 	}
     }
 
 }
 
 sub del_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $url = $plugin_config->{url};
@@ -89,13 +88,13 @@ sub del_subnet {
 	PVE::Network::SDN::api_request("DELETE", "$url/subnets/$internalid", $headers);
     };
     if ($@) {
-	die "error deleting subnet from ipam: $@";
+	die "error deleting subnet from ipam: $@" if !$noerr;
     }
 
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $url = $plugin_config->{url};
@@ -118,12 +117,12 @@ sub add_ip {
     };
 
     if ($@) {
-	die "error add subnet ip to ipam: ip $ip already exist: $@";
+	die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
     }
 }
 
 sub update_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $url = $plugin_config->{url};
@@ -146,12 +145,12 @@ sub update_ip {
     };
 
     if ($@) {
-	die "ipam: error update subnet ip $ip: $@";
+	die "ipam: error update subnet ip $ip: $@" if !$noerr;
     }
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};  
     my $mask = $subnet->{mask};  
@@ -175,14 +174,14 @@ sub add_next_freeip {
     };
 
     if ($@) {
-        die "can't find free ip in subnet $cidr: $@";
+        die "can't find free ip in subnet $cidr: $@" if !$noerr;
     }
 
-    return "$ip/$mask";
+    return "$ip/$mask" if $ip && $mask;
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $noerr) = @_;
 
     return if !$ip;
 
@@ -197,7 +196,7 @@ sub del_ip {
 	PVE::Network::SDN::api_request("DELETE", "$url/addresses/$ip_id", $headers);
     };
     if ($@) {
-	die "error delete ip $ip: $@";
+	die "error delete ip $ip: $@" if !$noerr;
     }
 }
 
diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plugin.pm
index a4c7dcb..c96eeda 100644
--- a/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/PVE/Network/SDN/Ipams/Plugin.pm
@@ -67,25 +67,25 @@ sub parse_section_header {
 
 
 sub add_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub del_subnet {
-    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub add_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub update_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $noerr) = @_;
     # only update ip attributes (mac,hostname,..). Don't change the ip addresses itself, as some ipam
     # don't allow ip address change without del/add
 
@@ -93,13 +93,13 @@ sub update_ip {
 }
 
 sub add_next_freeip {
-    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $subnet, $ip, $noerr) = @_;
 
     die "please implement inside plugin";
 }
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 09/15] tests: add ipams tests
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (7 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 08/15] ipams: add noerr param Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 10/15] dns: add noerr param Alexandre Derumier
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 test/Makefile                               |   5 +-
 test/ipams/netbox/expected.add_ip           |   9 +
 test/ipams/netbox/expected.add_next_freeip  |   9 +
 test/ipams/netbox/expected.add_subnet       |   9 +
 test/ipams/netbox/expected.del_ip           |   9 +
 test/ipams/netbox/expected.del_subnet       |   9 +
 test/ipams/netbox/expected.update_ip        |   9 +
 test/ipams/netbox/ipam_config               |  18 ++
 test/ipams/netbox/sdn_config                |  20 +++
 test/ipams/phpipam/expected.add_ip          |  12 ++
 test/ipams/phpipam/expected.add_next_freeip |  12 ++
 test/ipams/phpipam/expected.add_subnet      |  12 ++
 test/ipams/phpipam/expected.del_ip          |  12 ++
 test/ipams/phpipam/expected.del_subnet      |  12 ++
 test/ipams/phpipam/expected.update_ip       |  12 ++
 test/ipams/phpipam/ipam_config              |  18 ++
 test/ipams/phpipam/sdn_config               |  20 +++
 test/run_test_ipams.pl                      | 181 ++++++++++++++++++++
 18 files changed, 387 insertions(+), 1 deletion(-)
 create mode 100644 test/ipams/netbox/expected.add_ip
 create mode 100644 test/ipams/netbox/expected.add_next_freeip
 create mode 100644 test/ipams/netbox/expected.add_subnet
 create mode 100644 test/ipams/netbox/expected.del_ip
 create mode 100644 test/ipams/netbox/expected.del_subnet
 create mode 100644 test/ipams/netbox/expected.update_ip
 create mode 100644 test/ipams/netbox/ipam_config
 create mode 100644 test/ipams/netbox/sdn_config
 create mode 100644 test/ipams/phpipam/expected.add_ip
 create mode 100644 test/ipams/phpipam/expected.add_next_freeip
 create mode 100644 test/ipams/phpipam/expected.add_subnet
 create mode 100644 test/ipams/phpipam/expected.del_ip
 create mode 100644 test/ipams/phpipam/expected.del_subnet
 create mode 100644 test/ipams/phpipam/expected.update_ip
 create mode 100644 test/ipams/phpipam/ipam_config
 create mode 100644 test/ipams/phpipam/sdn_config
 create mode 100755 test/run_test_ipams.pl

diff --git a/test/Makefile b/test/Makefile
index b8e5de1..6eb88a1 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,6 +1,9 @@
 all: test
 
-test: test_zones
+test: test_zones test_ipams
 
 test_zones: run_test_zones.pl
 	./run_test_zones.pl
+
+test_ipams: run_test_ipams.pl
+	./run_test_ipams.pl
diff --git a/test/ipams/netbox/expected.add_ip b/test/ipams/netbox/expected.add_ip
new file mode 100644
index 0000000..ae876f2
--- /dev/null
+++ b/test/ipams/netbox/expected.add_ip
@@ -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/netbox/expected.add_next_freeip b/test/ipams/netbox/expected.add_next_freeip
new file mode 100644
index 0000000..7f80f4c
--- /dev/null
+++ b/test/ipams/netbox/expected.add_next_freeip
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '{"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/prefixes/1/available-ips/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/netbox/expected.add_subnet b/test/ipams/netbox/expected.add_subnet
new file mode 100644
index 0000000..62ca823
--- /dev/null
+++ b/test/ipams/netbox/expected.add_subnet
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '{"prefix":"10.0.0.0/24"}',
+                  '_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/prefixes/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/netbox/expected.del_ip b/test/ipams/netbox/expected.del_ip
new file mode 100644
index 0000000..3c41de4
--- /dev/null
+++ b/test/ipams/netbox/expected.del_ip
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '',
+                  '_headers' => bless( {
+                                         'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
+                                         'content-type' => 'application/json; charset=UTF-8'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'DELETE',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8000/api/ipam/ip-addresses/1/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/netbox/expected.del_subnet b/test/ipams/netbox/expected.del_subnet
new file mode 100644
index 0000000..bdadb71
--- /dev/null
+++ b/test/ipams/netbox/expected.del_subnet
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '{"address":"192.168.0.1/24","description":null,"dns_name":"toto"}',
+                  '_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/netbox/expected.update_ip b/test/ipams/netbox/expected.update_ip
new file mode 100644
index 0000000..a1202ad
--- /dev/null
+++ b/test/ipams/netbox/expected.update_ip
@@ -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' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8000/api/ipam/ip-addresses/1/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/netbox/ipam_config b/test/ipams/netbox/ipam_config
new file mode 100644
index 0000000..a33be30
--- /dev/null
+++ b/test/ipams/netbox/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/ipams/netbox/sdn_config b/test/ipams/netbox/sdn_config
new file mode 100644
index 0000000..c31847b
--- /dev/null
+++ b/test/ipams/netbox/sdn_config
@@ -0,0 +1,20 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "netbox" } },
+             },
+
+  subnets => {
+              ids => { 'myzone-10.0.0.0-24' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  }
+                     }
+             }
+}
diff --git a/test/ipams/phpipam/expected.add_ip b/test/ipams/phpipam/expected.add_ip
new file mode 100644
index 0000000..50af460
--- /dev/null
+++ b/test/ipams/phpipam/expected.add_ip
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":"mydescription","hostname":"myhostname","ip":"10.0.0.1","is_gateway":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/ipams/phpipam/expected.add_next_freeip b/test/ipams/phpipam/expected.add_next_freeip
new file mode 100644
index 0000000..d72f94f
--- /dev/null
+++ b/test/ipams/phpipam/expected.add_next_freeip
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":"mydescription","hostname":"myhostname","mac":"da:65:8f:18:9b:6f"}',
+                  '_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/first_free/1/')}, 'URI::https' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/expected.add_subnet b/test/ipams/phpipam/expected.add_subnet
new file mode 100644
index 0000000..b10cc5a
--- /dev/null
+++ b/test/ipams/phpipam/expected.add_subnet
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"mask":"24","sectionId":1,"subnet":"10.0.0.0"}',
+                  '_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/subnets/')}, 'URI::https' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/expected.del_ip b/test/ipams/phpipam/expected.del_ip
new file mode 100644
index 0000000..72e83cb
--- /dev/null
+++ b/test/ipams/phpipam/expected.del_ip
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'token' => 'Token'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'DELETE',
+                  '_uri' => bless( do{\(my $o = 'https://localhost/api/apiadmin/addresses/1')}, 'URI::https' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/expected.del_subnet b/test/ipams/phpipam/expected.del_subnet
new file mode 100644
index 0000000..349a34f
--- /dev/null
+++ b/test/ipams/phpipam/expected.del_subnet
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":null,"hostname":"toto","ip":"192.168.0.1","is_gateway":null,"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/ipams/phpipam/expected.update_ip b/test/ipams/phpipam/expected.update_ip
new file mode 100644
index 0000000..96c219b
--- /dev/null
+++ b/test/ipams/phpipam/expected.update_ip
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":"mydescription","hostname":"myhostname","is_gateway":1,"mac":"da:65:8f:18:9b:6f"}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'token' => 'Token'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'https://localhost/api/apiadmin/addresses/1')}, 'URI::https' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/ipam_config b/test/ipams/phpipam/ipam_config
new file mode 100644
index 0000000..a33be30
--- /dev/null
+++ b/test/ipams/phpipam/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/ipams/phpipam/sdn_config b/test/ipams/phpipam/sdn_config
new file mode 100644
index 0000000..c774807
--- /dev/null
+++ b/test/ipams/phpipam/sdn_config
@@ -0,0 +1,20 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "phpipam" } },
+             },
+
+  subnets => {
+              ids => { 'myzone-10.0.0.0-24' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  }
+                     }
+             }
+}
diff --git a/test/run_test_ipams.pl b/test/run_test_ipams.pl
new file mode 100755
index 0000000..6743eff
--- /dev/null
+++ b/test/run_test_ipams.pl
@@ -0,0 +1,181 @@
+#!/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 = <./ipams/*>;
+my @plugins = read_dir( './ipams/', prefix => 1 ) ;
+
+foreach my $path (@plugins) {
+
+    my (undef, $ipamid) = 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};
+	},
+    );
+
+    my $pve_sdn_ipam;
+    $pve_sdn_subnets = Test::MockModule->new('PVE::Network::SDN::Ipams');
+    $pve_sdn_subnets->mock(
+	config => sub {
+	    my $ipam_config = read_sdn_config ("$path/ipam_config");
+	    return $ipam_config;
+	},
+    );
+
+    my $sdn_module = Test::MockModule->new("PVE::Network::SDN");
+    $sdn_module->mock(
+	config => sub {
+	    return $sdn_config;
+	},
+	api_request => sub {
+          my ($method, $url, $headers, $data) = @_;
+
+ 	my $js = JSON->new;
+	$js->canonical(1);
+	
+	  my $encoded_data = $js->encode($data) if $data;
+	  my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
+          die Dumper($req);
+	}
+    );
+
+
+  
+    #test params;
+    my $subnetid = "myzone-10.0.0.0-24";
+    my $ip = "10.0.0.1";
+    my $hostname = "myhostname";
+    my $mac = "da:65:8f:18:9b:6f";
+    my $description = "mydescription";
+    my $is_gateway = 1;
+
+
+    my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($sdn_config->{subnets}, $subnetid, 1);
+
+    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});
+    my $sdn_ipam_plugin = Test::MockModule->new($plugin);
+    $sdn_ipam_plugin->mock(
+	get_prefix_id => sub {
+	    return 1;
+	},
+	get_ip_id => sub {
+	    return 1;
+	}
+    );
+
+    ## add_ip
+    my $test = "add_ip";
+    my $expected = Dumper read_sdn_config("$path/expected.$test");
+    my $name = "$ipamid $test";
+
+    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, 1);
+
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+    ## add_next_freeip
+    $test = "add_next_freeip";
+    $expected = Dumper read_sdn_config("$path/expected.$test");
+    $name = "$ipamid $test";
+
+    $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $description, 1);
+
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+
+    ## del_ip
+    $test = "del_ip";
+    $expected = Dumper read_sdn_config("$path/expected.$test");
+    $name = "$ipamid $test";
+
+    $plugin->del_ip($plugin_config, $subnetid, $subnet, $ip, 1);
+
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+    ## update_ip
+    $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);
+    }
+
+     $sdn_ipam_plugin->mock(
+	get_prefix_id => sub {
+	    return undef;
+	},
+    );
+
+    ## add_subnet
+    $test = "add_subnet";
+    $expected = Dumper read_sdn_config("$path/expected.$test");
+    $name = "$ipamid $test";
+
+    $plugin->add_subnet($plugin_config, $subnetid, $subnet, 1);
+
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+}
+
+done_testing();
+
+
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 10/15] dns: add noerr param
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (8 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 09/15] tests: add ipams tests Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 11/15] tests: add dns tests Alexandre Derumier
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Dns/Plugin.pm         | 10 +++++-----
 PVE/Network/SDN/Dns/PowerdnsPlugin.pm | 22 +++++++++++-----------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/PVE/Network/SDN/Dns/Plugin.pm b/PVE/Network/SDN/Dns/Plugin.pm
index 199c170..07d0be1 100644
--- a/PVE/Network/SDN/Dns/Plugin.pm
+++ b/PVE/Network/SDN/Dns/Plugin.pm
@@ -67,31 +67,31 @@ sub parse_section_header {
 
 
 sub add_a_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub add_ptr_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub del_ptr_record {
-    my ($class, $plugin_config, $zone, $ip) = @_;
+    my ($class, $plugin_config, $zone, $ip, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub del_a_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     die "please implement inside plugin";
 }
 
 sub verify_zone {
-    my ($class, $plugin_config, $zone) = @_;
+    my ($class, $plugin_config, $zone, $noerr) = @_;
 
     die "please implement inside plugin";
 }
diff --git a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
index d93fb06..339ac28 100644
--- a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
+++ b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
@@ -42,7 +42,7 @@ sub options {
 # Plugin implementation
 
 sub add_a_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     my $url = $plugin_config->{url};
     my $key = $plugin_config->{key};
@@ -88,12 +88,12 @@ sub add_a_record {
     };
 
     if ($@) {
-	die "error add $fqdn to zone $zone: $@";
+	die "error add $fqdn to zone $zone: $@" if !$noerr;
     }
 }
 
 sub add_ptr_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     my $url = $plugin_config->{url};
     my $key = $plugin_config->{key};
@@ -125,12 +125,12 @@ sub add_ptr_record {
     };
 
     if ($@) {
-	die "error add $reverseip to zone $zone: $@";
+	die "error add $reverseip to zone $zone: $@" if !$noerr;
     }
 }
 
 sub del_a_record {
-    my ($class, $plugin_config, $zone, $hostname, $ip) = @_;
+    my ($class, $plugin_config, $zone, $hostname, $ip, $noerr) = @_;
 
     my $url = $plugin_config->{url};
     my $key = $plugin_config->{key};
@@ -151,7 +151,7 @@ sub del_a_record {
 	push @$final_records, $record;
     }
     return if !$foundrecord;
- 
+
     my $rrset = {};
    
     if (scalar (@{$final_records}) > 0) {
@@ -177,12 +177,12 @@ sub del_a_record {
     };
 
     if ($@) {
-	die "error delete $fqdn from zone $zone: $@";
+	die "error delete $fqdn from zone $zone: $@" if !$noerr;
     }
 }
 
 sub del_ptr_record {
-    my ($class, $plugin_config, $zone, $ip) = @_;
+    my ($class, $plugin_config, $zone, $ip, $noerr) = @_;
 
     my $url = $plugin_config->{url};
     my $key = $plugin_config->{key};
@@ -204,12 +204,12 @@ sub del_ptr_record {
     };
 
     if ($@) {
-	die "error delete $reverseip from zone $zone: $@";
+	die "error delete $reverseip from zone $zone: $@" if !$noerr;
     }
 }
 
 sub verify_zone {
-    my ($class, $plugin_config, $zone) = @_;
+    my ($class, $plugin_config, $zone, $noerr) = @_;
 
     #verify that api is working              
 
@@ -222,7 +222,7 @@ sub verify_zone {
     };
 
     if ($@) {
-        die "can't read zone $zone: $@";
+        die "can't read zone $zone: $@" if !$noerr;
     }
 }
 
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 11/15] tests: add dns tests
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (9 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 10/15] dns: add noerr param Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 12/15] subnets: convert dns private function to public sub Alexandre Derumier
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 test/Makefile                                 |   5 +-
 test/dns/powerdns/dns_config                  |  10 +
 .../expected.add_a_multiple_record.ipv4       |  13 +
 .../expected.add_a_multiple_record.ipv6       |  13 +
 test/dns/powerdns/expected.add_a_record.ipv4  |  12 +
 test/dns/powerdns/expected.add_a_record.ipv6  |  13 +
 .../dns/powerdns/expected.add_ptr_record.ipv4 |  13 +
 .../dns/powerdns/expected.add_ptr_record.ipv6 |  12 +
 .../expected.del_a_multiple_record.ipv4       |  13 +
 .../expected.del_a_multiple_record.ipv6       |  12 +
 test/dns/powerdns/expected.del_a_record.ipv4  |  13 +
 test/dns/powerdns/expected.del_a_record.ipv6  |  12 +
 .../dns/powerdns/expected.del_ptr_record.ipv4 |  12 +
 .../dns/powerdns/expected.del_ptr_record.ipv6 |  13 +
 test/dns/powerdns/expected.verify_zone        |  12 +
 test/dns/powerdns/sdn_config                  |  20 ++
 test/run_test_dns.pl                          | 271 ++++++++++++++++++
 17 files changed, 468 insertions(+), 1 deletion(-)
 create mode 100644 test/dns/powerdns/dns_config
 create mode 100644 test/dns/powerdns/expected.add_a_multiple_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_a_multiple_record.ipv6
 create mode 100644 test/dns/powerdns/expected.add_a_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_a_record.ipv6
 create mode 100644 test/dns/powerdns/expected.add_ptr_record.ipv4
 create mode 100644 test/dns/powerdns/expected.add_ptr_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_a_multiple_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_a_multiple_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_a_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_a_record.ipv6
 create mode 100644 test/dns/powerdns/expected.del_ptr_record.ipv4
 create mode 100644 test/dns/powerdns/expected.del_ptr_record.ipv6
 create mode 100644 test/dns/powerdns/expected.verify_zone
 create mode 100644 test/dns/powerdns/sdn_config
 create mode 100755 test/run_test_dns.pl

diff --git a/test/Makefile b/test/Makefile
index 6eb88a1..ca05cf7 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,9 +1,12 @@
 all: test
 
-test: test_zones test_ipams
+test: test_zones test_ipams test_dns
 
 test_zones: run_test_zones.pl
 	./run_test_zones.pl
 
 test_ipams: run_test_ipams.pl
 	./run_test_ipams.pl
+
+test_dns: run_test_dns.pl
+	./run_test_dns.pl
diff --git a/test/dns/powerdns/dns_config b/test/dns/powerdns/dns_config
new file mode 100644
index 0000000..6052366
--- /dev/null
+++ b/test/dns/powerdns/dns_config
@@ -0,0 +1,10 @@
+{
+          'ids' => {
+                     'powerdns' => {
+                                    'url' => 'http://localhost:8881/api/v1/servers/localhost',
+                                    'type' => 'powerdns',
+                                    'key' => '1234',
+                                    'ttl' => '3600'
+                                  },
+                   },
+}
diff --git a/test/dns/powerdns/expected.add_a_multiple_record.ipv4 b/test/dns/powerdns/expected.add_a_multiple_record.ipv4
new file mode 100644
index 0000000..0e5539f
--- /dev/null
+++ b/test/dns/powerdns/expected.add_a_multiple_record.ipv4
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"127.0.0.1","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"A"},{"content":"10.0.0.1","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"A"}],"ttl":"3600","type":"A"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.add_a_multiple_record.ipv6 b/test/dns/powerdns/expected.add_a_multiple_record.ipv6
new file mode 100644
index 0000000..e432e7b
--- /dev/null
+++ b/test/dns/powerdns/expected.add_a_multiple_record.ipv6
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"2001:4860:4860::8844","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"AAAA"},{"content":"2001:4860:4860::8888","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"AAAA"}],"ttl":"3600","type":"AAAA"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.add_a_record.ipv4 b/test/dns/powerdns/expected.add_a_record.ipv4
new file mode 100644
index 0000000..888d67f
--- /dev/null
+++ b/test/dns/powerdns/expected.add_a_record.ipv4
@@ -0,0 +1,12 @@
+bless( {
+                 '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"10.0.0.1","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"A"}],"ttl":"3600","type":"A"}]}',
+                 '_headers' => bless( {
+                                        '::std_case' => {
+                                                          'x-api-key' => 'X-API-Key'
+                                                        },
+                                        'content-type' => 'application/json; charset=UTF-8',
+                                        'x-api-key' => '1234'
+                                      }, 'HTTP::Headers' ),
+                 '_method' => 'PATCH',
+                 '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+               }, 'HTTP::Request' );
\ No newline at end of file
diff --git a/test/dns/powerdns/expected.add_a_record.ipv6 b/test/dns/powerdns/expected.add_a_record.ipv6
new file mode 100644
index 0000000..bfeeab7
--- /dev/null
+++ b/test/dns/powerdns/expected.add_a_record.ipv6
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"2001:4860:4860::8888","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"AAAA"}],"ttl":"3600","type":"AAAA"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.add_ptr_record.ipv4 b/test/dns/powerdns/expected.add_ptr_record.ipv4
new file mode 100644
index 0000000..6923971
--- /dev/null
+++ b/test/dns/powerdns/expected.add_ptr_record.ipv4
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"1.0.0.10.in-addr.arpa.","records":[{"content":"myhostname.","disabled":false,"name":"1.0.0.10.in-addr.arpa.","priority":0,"type":"PTR"}],"ttl":"3600","type":"PTR"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.add_ptr_record.ipv6 b/test/dns/powerdns/expected.add_ptr_record.ipv6
new file mode 100644
index 0000000..1d8049f
--- /dev/null
+++ b/test/dns/powerdns/expected.add_ptr_record.ipv6
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa.","records":[{"content":"myhostname.","disabled":false,"name":"8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa.","priority":0,"type":"PTR"}],"ttl":"3600","type":"PTR"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/dns/powerdns/expected.del_a_multiple_record.ipv4 b/test/dns/powerdns/expected.del_a_multiple_record.ipv4
new file mode 100644
index 0000000..45d76c6
--- /dev/null
+++ b/test/dns/powerdns/expected.del_a_multiple_record.ipv4
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"127.0.0.1","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"A"}],"ttl":"3600","type":"A"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.del_a_multiple_record.ipv6 b/test/dns/powerdns/expected.del_a_multiple_record.ipv6
new file mode 100644
index 0000000..9b56abd
--- /dev/null
+++ b/test/dns/powerdns/expected.del_a_multiple_record.ipv6
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"REPLACE","name":"myhostname.domain.com.","records":[{"content":"2001:4860:4860::8844","disabled":false,"name":"myhostname.domain.com.","priority":0,"type":"AAAA"}],"ttl":"3600","type":"AAAA"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/dns/powerdns/expected.del_a_record.ipv4 b/test/dns/powerdns/expected.del_a_record.ipv4
new file mode 100644
index 0000000..7c0cf45
--- /dev/null
+++ b/test/dns/powerdns/expected.del_a_record.ipv4
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"DELETE","name":"myhostname.domain.com.","records":[],"type":"A"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                 }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.del_a_record.ipv6 b/test/dns/powerdns/expected.del_a_record.ipv6
new file mode 100644
index 0000000..9494c83
--- /dev/null
+++ b/test/dns/powerdns/expected.del_a_record.ipv6
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"DELETE","name":"myhostname.domain.com.","records":[],"type":"AAAA"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/dns/powerdns/expected.del_ptr_record.ipv4 b/test/dns/powerdns/expected.del_ptr_record.ipv4
new file mode 100644
index 0000000..120485b
--- /dev/null
+++ b/test/dns/powerdns/expected.del_ptr_record.ipv4
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"DELETE","name":"1.0.0.10.in-addr.arpa.","records":[],"type":"PTR"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/dns/powerdns/expected.del_ptr_record.ipv6 b/test/dns/powerdns/expected.del_ptr_record.ipv6
new file mode 100644
index 0000000..7948e78
--- /dev/null
+++ b/test/dns/powerdns/expected.del_ptr_record.ipv6
@@ -0,0 +1,13 @@
+bless( {
+                  '_content' => '{"rrsets":[{"changetype":"DELETE","name":"8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa.","records":[],"type":"PTR"}]}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'PATCH',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com')}, 'URI::http' )
+                }, 'HTTP::Request' );
+
diff --git a/test/dns/powerdns/expected.verify_zone b/test/dns/powerdns/expected.verify_zone
new file mode 100644
index 0000000..b476875
--- /dev/null
+++ b/test/dns/powerdns/expected.verify_zone
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'x-api-key' => 'X-API-Key'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'x-api-key' => '1234'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'GET',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8881/api/v1/servers/localhost/zones/domain.com?rrsets=false')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/dns/powerdns/sdn_config b/test/dns/powerdns/sdn_config
new file mode 100644
index 0000000..2087729
--- /dev/null
+++ b/test/dns/powerdns/sdn_config
@@ -0,0 +1,20 @@
+{
+  version => 1,
+  vnets   => {
+               ids => {
+                        myvnet => { type => "vnet", zone => "myzone" },
+                      },
+             },
+
+  zones   => {
+               ids => { myzone => { ipam => "pve", type =>"simple", dns => "powerdns", reversedns => "powerdns", dnszone => "domain.com" } },
+             },
+
+  subnets => {
+              ids => { 'myzone-10.0.0.0-24' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  }
+                     }
+             }
+}
diff --git a/test/run_test_dns.pl b/test/run_test_dns.pl
new file mode 100755
index 0000000..87e011e
--- /dev/null
+++ b/test/run_test_dns.pl
@@ -0,0 +1,271 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib qw(..);
+use File::Slurp;
+use Net::IP;
+
+use Test::More;
+use Test::MockModule;
+
+use PVE::Network::SDN;
+use PVE::Network::SDN::Zones;
+use PVE::Network::SDN::Controllers;
+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( './dns/', prefix => 1 ) ;
+
+foreach my $path (@plugins) {
+
+    my (undef, $dnsid) = split(/\//, $path);
+    my $sdn_config = read_sdn_config ("$path/sdn_config");
+
+
+    my $pve_sdn_dns;
+    $pve_sdn_dns = Test::MockModule->new('PVE::Network::SDN::Dns');
+    $pve_sdn_dns->mock(
+	config => sub {
+	    my $dns_config = read_sdn_config ("$path/dns_config");
+	    return $dns_config;
+	},
+    );
+
+    my $sdn_module = Test::MockModule->new("PVE::Network::SDN");
+    $sdn_module->mock(
+	config => sub {
+	    return $sdn_config;
+	},
+	api_request => sub {
+          my ($method, $url, $headers, $data) = @_;
+
+ 	my $js = JSON->new;
+	$js->canonical(1);
+	
+	  my $encoded_data = $js->encode($data) if $data;
+	  my $req = HTTP::Request->new($method,$url, $headers, $encoded_data);
+          die Dumper($req);
+	}
+    );
+
+
+
+    my $dns_cfg = PVE::Network::SDN::Dns::config();
+    my $plugin_config = $dns_cfg->{ids}->{$dnsid};
+    my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
+  
+    #test params;
+    my @ips = ("10.0.0.1", "2001:4860:4860::8888");
+    my $zone = "domain.com";
+    my $hostname = "myhostname";
+
+    foreach my $ip (@ips) {
+
+	my $ipversion = Net::IP::ip_is_ipv6($ip) ? "ipv6" : "ipv4";
+	my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
+	my $ip2 = $type eq 'AAAA' ? '2001:4860:4860::8844' : '127.0.0.1';
+	my $fqdn = $hostname.".".$zone.".";
+
+	my $sdn_dns_plugin = Test::MockModule->new($plugin); 
+	$sdn_dns_plugin->mock(
+
+	    get_zone_content => sub {
+		return undef;
+	    },
+	    get_zone_rrset => sub {
+		return undef;
+	    }
+	);
+
+	## add_a_record
+	my $test = "add_a_record";
+	my $expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	my $name = "$dnsid $test";
+
+	$plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+
+	## add_ptr_record
+	$test = "add_ptr_record";
+	$expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	$name = "$dnsid $test";
+
+	$plugin->add_ptr_record($plugin_config, $zone, $hostname, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+
+
+	## del_ptr_record
+	$test = "del_ptr_record";
+	$expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	$name = "$dnsid $test";
+
+	$plugin->del_ptr_record($plugin_config, $zone, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+
+
+	## del_a_record
+
+	$sdn_dns_plugin->mock(
+
+	    get_zone_content => sub {
+		return undef;
+	    },
+	    get_zone_rrset => sub {
+
+		my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A";
+		my $fqdn = $hostname.".".$zone.".";
+		my $record = { content => $ip,
+			       disabled => JSON::false,
+			       name => $fqdn,
+			       type => $type,
+			       priority => 0 };
+
+		my $rrset = { name => $fqdn,
+			      type => $type,
+			      ttl =>  '3600',
+			      records => [ $record ] };
+		return $rrset;
+	    }
+	);
+
+	$test = "del_a_record";
+	$expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	$name = "$dnsid $test";
+
+	$plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+
+	## del_a_multiple_record
+
+	$sdn_dns_plugin->mock(
+
+	    get_zone_content => sub {
+		return undef;
+	    },
+	    get_zone_rrset => sub {
+
+		my $record = { content => $ip,
+			       disabled => JSON::false,
+			       name => $fqdn,
+			       type => $type,
+			       priority => 0 };
+
+		my $record2 = { content => $ip2,
+				disabled => JSON::false,
+				name => $fqdn,
+				type => $type,
+				priority => 0 };
+
+		my $rrset = { name => $fqdn,
+			      type => $type,
+			      ttl =>  '3600',
+			      records => [ $record, $record2 ] };
+		return $rrset;
+	    }
+	);
+
+	$test = "del_a_multiple_record";
+	$expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	$name = "$dnsid $test";
+
+	$plugin->del_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+
+	## add_a_multiple_record
+
+	$sdn_dns_plugin->mock(
+
+	    get_zone_content => sub {
+		return undef;
+	    },
+	    get_zone_rrset => sub {
+
+		my $record2 = { content => $ip2,
+				disabled => JSON::false,
+				name => $fqdn,
+				type => $type,
+				priority => 0 };
+
+		my $rrset = { name => $fqdn,
+			      type => $type,
+			      ttl =>  '3600',
+			      records => [ $record2 ] };
+		return $rrset;
+	    }
+	);
+
+	$test = "add_a_multiple_record";
+	$expected = Dumper read_sdn_config("$path/expected.$test.$ipversion");
+	$name = "$dnsid $test";
+
+	$plugin->add_a_record($plugin_config, $zone, $hostname, $ip, 1);
+
+	if ($@) {
+	    is ($@, $expected, $name);
+	} else {
+	    fail($name);
+	}
+    }
+
+    ## verify_zone
+    my $test = "verify_zone";
+    my $expected = Dumper read_sdn_config("$path/expected.$test");
+    my $name = "$dnsid $test";
+
+    $plugin->verify_zone($plugin_config, $zone, 1);
+
+    if ($@) {
+	is ($@, $expected, $name);
+    } else {
+	fail($name);
+    }
+
+}
+
+done_testing();
+
+
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 12/15] subnets: convert dns private function to public sub
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (10 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 11/15] tests: add dns tests Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 13/15] subnets: add add_subnet/del_subnet Alexandre Derumier
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Subnets.pm | 66 +++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 25261ac..ec0fb66 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -94,7 +94,7 @@ sub find_ip_subnet {
     return ($subnetid, $subnet);
 }
 
-my $verify_dns_zone = sub {
+sub verify_dns_zone {
     my ($zone, $dns) = @_;
 
     return if !$zone || !$dns;
@@ -103,9 +103,9 @@ my $verify_dns_zone = sub {
     my $plugin_config = $dns_cfg->{ids}->{$dns};
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->verify_zone($plugin_config, $zone);
-};
+}
 
-my $get_reversedns_zone = sub {
+sub get_reversedns_zone {
     my ($subnetid, $subnet, $dns, $ip) = @_;
 
     return if !$subnetid || !$dns || !$ip;
@@ -114,9 +114,9 @@ my $get_reversedns_zone = sub {
     my $plugin_config = $dns_cfg->{ids}->{$dns};
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->get_reversedns_zone($plugin_config, $subnetid, $subnet, $ip);
-};
+}
 
-my $add_dns_record = sub {
+sub add_dns_record {
     my ($zone, $dns, $hostname, $ip) = @_;
     return if !$zone || !$dns || !$hostname || !$ip;
 
@@ -125,9 +125,9 @@ my $add_dns_record = sub {
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->add_a_record($plugin_config, $zone, $hostname, $ip);
 
-};
+}
 
-my $add_dns_ptr_record = sub {
+sub add_dns_ptr_record {
     my ($reversezone, $zone, $dns, $hostname, $ip) = @_;
 
     return if !$zone || !$reversezone || !$dns || !$hostname || !$ip;
@@ -137,9 +137,9 @@ my $add_dns_ptr_record = sub {
     my $plugin_config = $dns_cfg->{ids}->{$dns};
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->add_ptr_record($plugin_config, $reversezone, $hostname, $ip);
-};
+}
 
-my $del_dns_record = sub {
+sub del_dns_record {
     my ($zone, $dns, $hostname, $ip) = @_;
 
     return if !$zone || !$dns || !$hostname || !$ip;
@@ -148,9 +148,9 @@ my $del_dns_record = sub {
     my $plugin_config = $dns_cfg->{ids}->{$dns};
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->del_a_record($plugin_config, $zone, $hostname, $ip);
-};
+}
 
-my $del_dns_ptr_record = sub {
+sub del_dns_ptr_record {
     my ($reversezone, $dns, $ip) = @_;
 
     return if !$reversezone || !$dns || !$ip;
@@ -159,7 +159,7 @@ my $del_dns_ptr_record = sub {
     my $plugin_config = $dns_cfg->{ids}->{$dns};
     my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
     $plugin->del_ptr_record($plugin_config, $reversezone, $ip);
-};
+}
 
 sub next_free_ip {
     my ($zone, $subnetid, $subnet, $hostname, $mac, $description) = @_;
@@ -177,7 +177,7 @@ sub next_free_ip {
     $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
 
     #verify dns zones before ipam
-    &$verify_dns_zone($dnszone, $dns);
+    verify_dns_zone($dnszone, $dns);
 
     if($ipamid) {
 	my $ipam_cfg = PVE::Network::SDN::Ipams::config();
@@ -191,12 +191,12 @@ sub next_free_ip {
     }
 
     eval {
-	my $reversednszone = &$get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+	my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
 
 	#add dns
-	&$add_dns_record($dnszone, $dns, $hostname, $ip);
+	add_dns_record($dnszone, $dns, $hostname, $ip);
 	#add reverse dns
-	&$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+	add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
     };
     if ($@) {
 	#rollback
@@ -221,14 +221,14 @@ sub add_ip {
     my $dns = $zone->{dns};
     my $dnszone = $zone->{dnszone};
     my $reversedns = $zone->{reversedns};
-    my $reversednszone = &$get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+    my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
     my $dnszoneprefix = $subnet->{dnszoneprefix};
 
     $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
 
     #verify dns zones before ipam
-    &$verify_dns_zone($dnszone, $dns);
-    &$verify_dns_zone($reversednszone, $reversedns);
+    verify_dns_zone($dnszone, $dns);
+    verify_dns_zone($reversednszone, $reversedns);
 
     if ($ipamid) {
 	my $ipam_cfg = PVE::Network::SDN::Ipams::config();
@@ -242,9 +242,9 @@ sub add_ip {
 
     eval {
 	#add dns
-	&$add_dns_record($dnszone, $dns, $hostname, $ip);
+	add_dns_record($dnszone, $dns, $hostname, $ip);
 	#add reverse dns
-	&$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+	add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
     };
     if ($@) {
 	#rollback
@@ -268,14 +268,14 @@ sub update_ip {
     my $dns = $zone->{dns};
     my $dnszone = $zone->{dnszone};
     my $reversedns = $zone->{reversedns};
-    my $reversednszone = &$get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+    my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
     my $dnszoneprefix = $subnet->{dnszoneprefix};
 
     $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
 
     #verify dns zones before ipam
-    &$verify_dns_zone($dnszone, $dns);
-    &$verify_dns_zone($reversednszone, $reversedns);
+    verify_dns_zone($dnszone, $dns);
+    verify_dns_zone($reversednszone, $reversedns);
 
     if ($ipamid) {
 	my $ipam_cfg = PVE::Network::SDN::Ipams::config();
@@ -292,11 +292,11 @@ sub update_ip {
     eval {
 	#add dns
 	
-	&$del_dns_record($dnszone, $dns, $oldhostname, $ip);
-	&$add_dns_record($dnszone, $dns, $hostname, $ip);
+	del_dns_record($dnszone, $dns, $oldhostname, $ip);
+	add_dns_record($dnszone, $dns, $hostname, $ip);
 	#add reverse dns
-	&$del_dns_ptr_record($reversednszone, $reversedns, $ip);
-	&$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
+	del_dns_ptr_record($reversednszone, $reversedns, $ip);
+	add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip);
     };
 }
 
@@ -312,13 +312,13 @@ sub del_ip {
     my $dns = $zone->{dns};
     my $dnszone = $zone->{dnszone};
     my $reversedns = $zone->{reversedns};
-    my $reversednszone = &$get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
+    my $reversednszone = get_reversedns_zone($subnetid, $subnet, $reversedns, $ip);
     my $dnszoneprefix = $subnet->{dnszoneprefix};
     $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
 
 
-    &$verify_dns_zone($dnszone, $dns);
-    &$verify_dns_zone($reversednszone, $reversedns);
+    verify_dns_zone($dnszone, $dns);
+    verify_dns_zone($reversednszone, $reversedns);
 
     if ($ipamid) {
 	my $ipam_cfg = PVE::Network::SDN::Ipams::config();
@@ -328,8 +328,8 @@ sub del_ip {
     }
 
     eval {
-	&$del_dns_record($dnszone, $dns, $hostname, $ip);
-	&$del_dns_ptr_record($reversednszone, $reversedns, $ip);
+	del_dns_record($dnszone, $dns, $hostname, $ip);
+	del_dns_ptr_record($reversednszone, $reversedns, $ip);
     };
     if ($@) {
 	warn $@;
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 13/15] subnets: add add_subnet/del_subnet
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (11 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 12/15] subnets: convert dns private function to public sub Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests Alexandre Derumier
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/API2/Network/SDN/Subnets.pm | 19 ++++++++-----------
 PVE/Network/SDN/SubnetPlugin.pm |  5 +----
 PVE/Network/SDN/Subnets.pm      | 20 ++++++++++++++++++++
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subnets.pm
index 07ef2e1..f7e095f 100644
--- a/PVE/API2/Network/SDN/Subnets.pm
+++ b/PVE/API2/Network/SDN/Subnets.pm
@@ -277,21 +277,18 @@ __PACKAGE__->register_method ({
 	    sub {
 		my $cfg = PVE::Network::SDN::Subnets::config();
 
-		my $scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id);
+		my $scfg = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $id, 1);
 
-		my $subnets_cfg = PVE::Network::SDN::Subnets::config();
 		my $vnets_cfg = PVE::Network::SDN::Vnets::config();
 
-		PVE::Network::SDN::SubnetPlugin->on_delete_hook($id, $subnets_cfg, $vnets_cfg);
+		PVE::Network::SDN::SubnetPlugin->on_delete_hook($id, $cfg, $vnets_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->del_subnet($plugin_config, $id, $scfg);
-		}
+		my $zone_cfg = PVE::Network::SDN::Zones::config();
+		my $vnet = $param->{vnet};
+		my $zoneid = $vnets_cfg->{ids}->{$vnet}->{zone};
+		my $zone = $zone_cfg->{ids}->{$zoneid};
+
+		PVE::Network::SDN::Subnets::del_subnet($zone, $id, $scfg);
 
 		delete $cfg->{ids}->{$id};
 
diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm
index 68efeb6..b4c8954 100644
--- a/PVE/Network/SDN/SubnetPlugin.pm
+++ b/PVE/Network/SDN/SubnetPlugin.pm
@@ -129,10 +129,7 @@ sub on_update_hook {
 
 
     if ($ipam) {
-	my $ipam_cfg = PVE::Network::SDN::Ipams::config();
-	my $plugin_config = $ipam_cfg->{ids}->{$ipam};
-	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
-	$plugin->add_subnet($plugin_config, $subnetid, $subnet);
+	PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet);
 
 	#don't register gateway for pointopoint
 	return if $pointopoint;
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index ec0fb66..34b3450 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -161,6 +161,26 @@ sub del_dns_ptr_record {
     $plugin->del_ptr_record($plugin_config, $reversezone, $ip);
 }
 
+sub add_subnet {
+    my ($zone, $subnetid, $subnet) = @_;
+
+    my $ipam = $zone->{ipam};
+    my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+    my $plugin_config = $ipam_cfg->{ids}->{$ipam};
+    my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+    $plugin->add_subnet($plugin_config, $subnetid, $subnet);
+}
+
+sub del_subnet {
+    my ($zone, $subnetid, $subnet) = @_;
+
+    my $ipam = $zone->{ipam};
+    my $ipam_cfg = PVE::Network::SDN::Ipams::config();
+    my $plugin_config = $ipam_cfg->{ids}->{$ipam};
+    my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+    $plugin->del_subnet($plugin_config, $subnetid, $subnet);
+}
+
 sub next_free_ip {
     my ($zone, $subnetid, $subnet, $hostname, $mac, $description) = @_;
 
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (12 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 13/15] subnets: add add_subnet/del_subnet Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-02-06 13:56   ` Thomas Lamprecht
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 15/15] fix coding style NetAddr::IP->new Alexandre Derumier
  2021-02-06 13:57 ` [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Thomas Lamprecht
  15 siblings, 1 reply; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 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 +++
 6 files changed, 353 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/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..6241f55
--- /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 = PVE::Network::SDN::Zones::get_zone("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..32c548b
--- /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", dns => "powerdns", dnszone => "domain.com" } },
+             },
+
+  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..2e5b824
--- /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", dns => "powerdns", dnszone => "domain.com" } },
+             },
+
+  subnets => {
+              ids => { 'myzone-2a0a:1580:2000::-56' => {
+                                                        'type' => 'subnet',
+                                                        'vnet' => 'myvnet',
+                                                  }
+                     }
+             }
+}
-- 
2.20.1




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

* [pve-devel] [PATCH pve-network 15/15] fix coding style NetAddr::IP->new
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (13 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests Alexandre Derumier
@ 2021-01-05  9:35 ` Alexandre Derumier
  2021-02-06 13:57 ` [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Thomas Lamprecht
  15 siblings, 0 replies; 20+ messages in thread
From: Alexandre Derumier @ 2021-01-05  9:35 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/Network/SDN/Dns/PowerdnsPlugin.pm | 2 +-
 PVE/Network/SDN/Ipams/PVEPlugin.pm    | 2 +-
 PVE/Network/SDN/Subnets.pm            | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
index 339ac28..096d131 100644
--- a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
+++ b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm
@@ -237,7 +237,7 @@ sub get_reversedns_zone {
     if (Net::IP::ip_is_ipv4($ip)) {
 	my ($ipblock1, $ipblock2, $ipblock3, $ipblock4) = split(/\./, $ip);
 
-        my $ipv4 = new NetAddr::IP($cidr);
+        my $ipv4 = NetAddr::IP->new($cidr);
 	#private addresse #powerdns built-in private zone : serve-rfc1918
 	if($ipv4->is_rfc1918()) {
 	    if ($ipblock1 == 192) {
diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 2527850..7e2fb77 100644
--- a/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -131,7 +131,7 @@ sub add_next_freeip {
 	    die "cannot find free IP in subnet '$cidr'\n" if defined($dbsubnet->{ips}->{$network});
 	    $freeip = $network;
 	} else {
-	    my $iplist = new NetAddr::IP($cidr);
+	    my $iplist = NetAddr::IP->new($cidr);
 	    my $broadcast = $iplist->broadcast();
 
 	    while(1) {
diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm
index 34b3450..0cbf5fd 100644
--- a/PVE/Network/SDN/Subnets.pm
+++ b/PVE/Network/SDN/Subnets.pm
@@ -234,7 +234,7 @@ sub add_ip {
 
     return if !$subnet || !$ip; 
 
-    my $ipaddr = new NetAddr::IP($ip);
+    my $ipaddr = NetAddr::IP->new($ip);
     $ip = $ipaddr->canon();
 
     my $ipamid = $zone->{ipam};
@@ -281,7 +281,7 @@ sub update_ip {
 
     return if !$subnet || !$ip; 
 
-    my $ipaddr = new NetAddr::IP($ip);
+    my $ipaddr = NetAddr::IP->new($ip);
     $ip = $ipaddr->canon();
 
     my $ipamid = $zone->{ipam};
@@ -325,7 +325,7 @@ sub del_ip {
 
     return if !$subnet || !$ip;
 
-    my $ipaddr = new NetAddr::IP($ip);
+    my $ipaddr = NetAddr::IP->new($ip);
     $ip = $ipaddr->canon();
 
     my $ipamid = $zone->{ipam};
-- 
2.20.1




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

* Re: [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests Alexandre Derumier
@ 2021-02-06 13:56   ` Thomas Lamprecht
  2021-02-07 14:09     ` aderumier
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas Lamprecht @ 2021-02-06 13:56 UTC (permalink / raw)
  To: Proxmox VE development discussion, Alexandre Derumier

I get some errors from this test, did not really investigated though.


./run_test_subnets.pl
ok 1 - ipv4 add_subnet
not ok 2 - ipv4 add_ip
#   Failed test 'ipv4 add_ip'
#   at ./run_test_subnets.pl line 130.
#          got: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{"10.0.0.1":{}}}}}}}'
not ok 3 - ipv4 add_already_exist_ip :
#   Failed test 'ipv4 add_already_exist_ip : '
#   at ./run_test_subnets.pl line 144.
not ok 4 - ipv4 add_second_ip
#   Failed test 'ipv4 add_second_ip'
#   at ./run_test_subnets.pl line 161.
#          got: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{"10.0.0.1":{},"10.0.0.3":{}}}}}}}'
not ok 5 - ipv4 add_next_freeip
#   Failed test 'ipv4 add_next_freeip'
#   at ./run_test_subnets.pl line 179.
#          got: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{"10.0.0.1":{},"10.0.0.2":{},"10.0.0.3":{}}}}}}}'
not ok 6 - ipv4 del_ip
#   Failed test 'ipv4 del_ip'
#   at ./run_test_subnets.pl line 196.
#          got: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{"10.0.0.2":{},"10.0.0.3":{}}}}}}}'
Use of uninitialized value $ipam in hash element at ../PVE/Network/SDN/Subnets.pm line 179.
ok 7 - ipv4 del_subnet_not_empty
not ok 8 - ipv4 add_ip_rollback_failing_dns
#   Failed test 'ipv4 add_ip_rollback_failing_dns'
#   at ./run_test_subnets.pl line 243.
#          got: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"10.0.0.0/24":{"ips":{"10.0.0.2":{},"10.0.0.3":{}}}}}}}'
Use of uninitialized value $ipam in hash element at ../PVE/Network/SDN/Subnets.pm line 179.
not ok 9 - ipv4 del_empty_subnet : cannot lookup undefined type! at ../PVE/Network/SDN/Subnets.pm line 180.
#
#   Failed test 'ipv4 del_empty_subnet : cannot lookup undefined type! at ../PVE/Network/SDN/Subnets.pm line 180.
# '
#   at ./run_test_subnets.pl line 262.
ok 10 - ipv6 add_subnet
not ok 11 - ipv6 add_ip
#   Failed test 'ipv6 add_ip'
#   at ./run_test_subnets.pl line 130.
#          got: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{"2a0a:1580:2000::1":{}}}}}}}'
not ok 12 - ipv6 add_already_exist_ip :
#   Failed test 'ipv6 add_already_exist_ip : '
#   at ./run_test_subnets.pl line 144.
not ok 13 - ipv6 add_second_ip
#   Failed test 'ipv6 add_second_ip'
#   at ./run_test_subnets.pl line 161.
#          got: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{"2a0a:1580:2000::1":{},"2a0a:1580:2000::3":{}}}}}}}'
not ok 14 - ipv6 add_next_freeip
#   Failed test 'ipv6 add_next_freeip'
#   at ./run_test_subnets.pl line 179.
#          got: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{"2a0a:1580:2000::1":{},"2a0a:1580:2000::2":{},"2a0a:1580:2000::3":{}}}}}}}'
not ok 15 - ipv6 del_ip
#   Failed test 'ipv6 del_ip'
#   at ./run_test_subnets.pl line 196.
#          got: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{"2a0a:1580:2000::2":{},"2a0a:1580:2000::3":{}}}}}}}'
Use of uninitialized value $ipam in hash element at ../PVE/Network/SDN/Subnets.pm line 179.
ok 16 - ipv6 del_subnet_not_empty
not ok 17 - ipv6 add_ip_rollback_failing_dns
#   Failed test 'ipv6 add_ip_rollback_failing_dns'
#   at ./run_test_subnets.pl line 243.
#          got: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{}}}}}}'
#     expected: '{"zones":{"myzone":{"subnets":{"2a0a:1580:2000::/56":{"ips":{"2a0a:1580:2000::2":{},"2a0a:1580:2000::3":{}}}}}}}'
Use of uninitialized value $ipam in hash element at ../PVE/Network/SDN/Subnets.pm line 179.
not ok 18 - ipv6 del_empty_subnet : cannot lookup undefined type! at ../PVE/Network/SDN/Subnets.pm line 180.
#
#   Failed test 'ipv6 del_empty_subnet : cannot lookup undefined type! at ../PVE/Network/SDN/Subnets.pm line 180.
# '
#   at ./run_test_subnets.pl line 262.
1..18
# Looks like you failed 14 tests of 18.




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

* Re: [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests
  2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
                   ` (14 preceding siblings ...)
  2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 15/15] fix coding style NetAddr::IP->new Alexandre Derumier
@ 2021-02-06 13:57 ` Thomas Lamprecht
  2021-02-07 14:26   ` aderumier
  15 siblings, 1 reply; 20+ messages in thread
From: Thomas Lamprecht @ 2021-02-06 13:57 UTC (permalink / raw)
  To: Proxmox VE development discussion, Alexandre Derumier

applied all but this one:

>   tests: add subnets tests

as my build fails with it (see reply to that patch)

much much thanks for the work here!




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

* Re: [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests
  2021-02-06 13:56   ` Thomas Lamprecht
@ 2021-02-07 14:09     ` aderumier
  0 siblings, 0 replies; 20+ messages in thread
From: aderumier @ 2021-02-07 14:09 UTC (permalink / raw)
  To: Thomas Lamprecht, Proxmox VE development discussion

Le samedi 06 février 2021 à 14:56 +0100, Thomas Lamprecht a écrit :
> I get some errors from this test, did not really investigated though.
It was using the current running cluster sdn config instead the test
sdn config.

I have resend a fixed version.




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

* Re: [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests
  2021-02-06 13:57 ` [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Thomas Lamprecht
@ 2021-02-07 14:26   ` aderumier
  0 siblings, 0 replies; 20+ messages in thread
From: aderumier @ 2021-02-07 14:26 UTC (permalink / raw)
  To: Thomas Lamprecht, Proxmox VE development discussion

Le samedi 06 février 2021 à 14:57 +0100, Thomas Lamprecht a écrit :
> applied all but this one:
> 
> >   tests: add subnets tests
> 
> as my build fails with it (see reply to that patch)
> 
> much much thanks for the work here!
> 

Thanks for your time for the review!

could it be possible to apply pve-cluster patches to handle new cfg
files ?




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

end of thread, other threads:[~2021-02-07 14:26 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-05  9:35 [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 01/15] sdn: pending_config: initialize empty pending key Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 02/15] ipams: add mac address Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 03/15] ipam: add update_ip Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 04/15] dns/ipam : move api_request helper to sdn module Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 05/15] subnets: fix del_ip rollback Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 06/15] dns: add update record && fix powerdns Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 07/15] ipam: phpipam: rename get_internal to get_prefix_id (like netbox) Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 08/15] ipams: add noerr param Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 09/15] tests: add ipams tests Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 10/15] dns: add noerr param Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 11/15] tests: add dns tests Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 12/15] subnets: convert dns private function to public sub Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 13/15] subnets: add add_subnet/del_subnet Alexandre Derumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 14/15] tests: add subnets tests Alexandre Derumier
2021-02-06 13:56   ` Thomas Lamprecht
2021-02-07 14:09     ` aderumier
2021-01-05  9:35 ` [pve-devel] [PATCH pve-network 15/15] fix coding style NetAddr::IP->new Alexandre Derumier
2021-02-06 13:57 ` [pve-devel] [PATCH pve-network 00/15] bugfix && unit tests Thomas Lamprecht
2021-02-07 14:26   ` aderumier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal