Signed-off-by: Alexandre Derumier <aderum...@odiso.com>
---
 src/PVE/Network/SDN/Ipams/NetboxPlugin.pm | 36 ++++++++++++++++++++
 src/PVE/Network/SDN/Ipams/PVEPlugin.pm    | 12 +++----
 src/PVE/Network/SDN/Ipams/Plugin.pm       |  7 ++++
 src/PVE/Network/SDN/Subnets.pm            | 21 +++++++++---
 src/PVE/Network/SDN/Vnets.pm              | 40 +++++++++++------------
 src/test/run_test_subnets.pl              |  2 +-
 src/test/run_test_vnets.pl                |  4 +--
 7 files changed, 88 insertions(+), 34 deletions(-)

diff --git a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm 
b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index f0e7168..2099a7f 100644
--- a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -151,6 +151,33 @@ sub add_next_freeip {
     return $ip;
 }
 
+sub add_range_next_freeip {
+    my ($class, $plugin_config, $subnet, $range, $data, $noerr) = @_;
+
+    my $url = $plugin_config->{url};
+    my $token = $plugin_config->{token};
+    my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 
'Authorization' => "token $token"];
+
+    my $internalid = get_iprange_id($url, $range, $headers);
+    my $description = "mac:$data->{mac}" if $data->{mac};
+
+    my $params = { dns_name => $data->{hostname}, description => $description 
};
+
+    my $ip = undef;
+    eval {
+       my $result = PVE::Network::SDN::api_request("POST", 
"$url/ipam/ip-ranges/$internalid/available-ips/", $headers, $params);
+       $ip = $result->{address};
+       print "found ip free $ip in range 
$range->{'start-address'}-$range->{'end-address'}\n" if $ip;
+    };
+
+    if ($@) {
+       die "can't find free ip in range 
$range->{'start-address'}-$range->{'end-address'}: $@" if !$noerr;
+    }
+
+    return $ip;
+
+}
+
 sub del_ip {
     my ($class, $plugin_config, $subnetid, $subnet, $ip, $noerr) = @_;
 
@@ -204,6 +231,15 @@ sub get_prefix_id {
     return $internalid;
 }
 
+sub get_iprange_id {
+    my ($url, $range, $headers) = @_;
+
+    my $result = PVE::Network::SDN::api_request("GET", 
"$url/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}",
 $headers);
+    my $data = @{$result->{results}}[0];
+    my $internalid = $data->{id};
+    return $internalid;
+}
+
 sub get_ip_id {
     my ($url, $ip, $headers) = @_;
     my $result = PVE::Network::SDN::api_request("GET", 
"$url/ipam/ip-addresses/?q=$ip", $headers);
diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm 
b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
index fcc8282..37b47e4 100644
--- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -110,7 +110,7 @@ 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) = @_;
 
     my $cidr = $subnet->{cidr};
     my $network = $subnet->{network};
@@ -156,8 +156,8 @@ sub add_next_freeip {
     return "$freeip/$mask";
 }
 
-sub add_dhcp_ip {
-    my ($class, $subnet, $dhcp_range, $data) = @_;
+sub add_range_next_freeip {
+    my ($class, $plugin_config, $subnet, $range, $data, $noerr) = @_;
 
     my $cidr = $subnet->{cidr};
     my $zone = $subnet->{zone};
@@ -171,8 +171,8 @@ sub add_dhcp_ip {
        my $dbsubnet = $dbzone->{subnets}->{$cidr};
        die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
 
-       my $ip = new Net::IP ("$dhcp_range->{'start-address'} - 
$dhcp_range->{'end-address'}")
-           or die "Invalid IP address(es) in DHCP Range!\n";
+       my $ip = new Net::IP ("$range->{'start-address'} - 
$range->{'end-address'}")
+           or die "Invalid IP address(es) in Range!\n";
 
        do {
            my $ip_address = $ip->ip();
@@ -184,7 +184,7 @@ sub add_dhcp_ip {
            }
        } while (++$ip);
 
-       die "No free IP left in DHCP Range 
$dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}}\n";
+       die "No free IP left in Range 
$range->{'start-address'}:$range->{'end-address'}}\n";
     });
 }
 
diff --git a/src/PVE/Network/SDN/Ipams/Plugin.pm 
b/src/PVE/Network/SDN/Ipams/Plugin.pm
index c96eeda..4d85b81 100644
--- a/src/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/src/PVE/Network/SDN/Ipams/Plugin.pm
@@ -98,6 +98,13 @@ sub add_next_freeip {
     die "please implement inside plugin";
 }
 
+
+sub add_range_next_freeip {
+    my ($class, $plugin_config, $subnet, $range, $data, $noerr) = @_;
+
+    die "please implement inside plugin";
+}
+
 sub del_ip {
     my ($class, $plugin_config, $subnetid, $subnet, $ip, $noerr) = @_;
 
diff --git a/src/PVE/Network/SDN/Subnets.pm b/src/PVE/Network/SDN/Subnets.pm
index dd9e697..9f953a6 100644
--- a/src/PVE/Network/SDN/Subnets.pm
+++ b/src/PVE/Network/SDN/Subnets.pm
@@ -202,8 +202,8 @@ sub del_subnet {
     $plugin->del_subnet($plugin_config, $subnetid, $subnet);
 }
 
-sub next_free_ip {
-    my ($zone, $subnetid, $subnet, $hostname, $mac, $description, $skipdns) = 
@_;
+sub add_next_free_ip {
+    my ($zone, $subnetid, $subnet, $hostname, $mac, $description, $skipdns, 
$dhcprange) = @_;
 
     my $cidr = undef;
     my $ip = undef;
@@ -225,9 +225,20 @@ 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, $mac, $description);
-           ($ip, undef) = split(/\//, $cidr);
+           if ($dhcprange) {
+               my $data = {
+                   mac => $mac,
+                   hostname => $hostname,
+               };
+               foreach my $range (@{$subnet->{'dhcp-range'}}) { 
+                   $ip = $plugin->add_range_next_freeip($plugin_config, 
$subnet, $range, $data);
+                   next if !$ip;
+               }
+           } else {
+               $ip = $plugin->add_next_freeip($plugin_config, $subnetid, 
$subnet, $hostname, $mac, $description);
+           }
        };
+
        die $@ if $@;
     }
 
@@ -249,7 +260,7 @@ sub next_free_ip {
        };
        die $err;
     }
-    return $cidr;
+    return $ip;
 }
 
 sub add_ip {
diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm
index 39bdda0..76a6caf 100644
--- a/src/PVE/Network/SDN/Vnets.pm
+++ b/src/PVE/Network/SDN/Vnets.pm
@@ -96,8 +96,8 @@ sub get_subnet_from_vnet_cidr {
     return ($zone, $subnetid, $subnet, $ip);
 }
 
-sub get_next_free_cidr {
-    my ($vnetid, $hostname, $mac, $description, $ipversion, $skipdns) = @_;
+sub add_next_free_cidr {
+    my ($vnetid, $hostname, $mac, $description, $skipdns, $dhcprange) = @_;
 
     my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
     my $zoneid = $vnet->{zone};
@@ -105,27 +105,27 @@ sub get_next_free_cidr {
 
     return if !$zone->{ipam};
 
-    $ipversion = 4 if !$ipversion;
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
-    my $ip = undef;
-    my $subnetcount = 0;
 
-    foreach my $subnetid (sort keys %{$subnets}) {
-        my $subnet = $subnets->{$subnetid};
-       my $network = $subnet->{network};
-
-       next if $ipversion != Net::IP::ip_get_version($network);
-       $subnetcount++;
-
-       eval {
-           $ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, 
$subnet, $hostname, $mac, $description, $skipdns);
-       };
-       warn $@ if $@;
-       last if $ip;
+    my @ipversions = qw/ 4 6 /;
+    for my $ipversion (@ipversions) {
+       my $ip = undef;
+       my $subnetcount = 0;
+       foreach my $subnetid (sort keys %{$subnets}) {
+           my $subnet = $subnets->{$subnetid};
+           my $network = $subnet->{network};
+
+           next if Net::IP::ip_get_version($network) != $ipversion;
+           $subnetcount++;
+
+           eval {
+               $ip = PVE::Network::SDN::Subnets::add_next_free_ip($zone, 
$subnetid, $subnet, $hostname, $mac, $description, $skipdns, $dhcprange);
+           };
+           die $@ if $@;
+           last if $ip;
+       }
+       die "can't find any free ip" if !$ip && $subnetcount > 0;
     }
-    die "can't find any free ip" if !$ip && $subnetcount > 0;
-
-    return $ip;
 }
 
 sub add_cidr {
diff --git a/src/test/run_test_subnets.pl b/src/test/run_test_subnets.pl
index f6564e1..9692f4c 100755
--- a/src/test/run_test_subnets.pl
+++ b/src/test/run_test_subnets.pl
@@ -192,7 +192,7 @@ foreach my $path (@plugins) {
     $expected = 
'{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
 
     eval {
-       $ip3 = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, 
$subnet, $hostname, $mac, $description);
+       $ip3 = PVE::Network::SDN::Subnets::add_next_free_ip($zone, $subnetid, 
$subnet, $hostname, $mac, $description);
     };
 
     if ($@) {
diff --git a/src/test/run_test_vnets.pl b/src/test/run_test_vnets.pl
index 5aeb676..dc9da67 100755
--- a/src/test/run_test_vnets.pl
+++ b/src/test/run_test_vnets.pl
@@ -231,7 +231,7 @@ foreach my $path (@plugins) {
     $expected = $ipam ? $cidr3 : undef;
 
     eval {
-       $result = PVE::Network::SDN::Vnets::get_next_free_cidr($vnetid, 
$hostname, $mac, $description, $ipversion);
+       $result = PVE::Network::SDN::Vnets::add_next_free_cidr($vnetid, 
$hostname, $mac, $description);
     };
 
     if ($@) {
@@ -309,7 +309,7 @@ foreach my $path (@plugins) {
     $expected = $ipam ? $cidr1 : undef;
 
     eval {
-       $result = PVE::Network::SDN::Vnets::get_next_free_cidr($vnetid, 
$hostname, $mac, $description, $ipversion);
+       $result = PVE::Network::SDN::Vnets::add_next_free_cidr($vnetid, 
$hostname, $mac, $description);
     };
 
     if ($@) {
-- 
2.39.2


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

Reply via email to