all lists on 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal