[pve-devel] [PATCH v9 pve-network 11/26] add pve internal ipam plugin

Alexandre Derumier aderumier at odiso.com
Mon Oct 5 17:08:08 CEST 2020


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/API2/Network/SDN/Ipams.pm          |   1 +
 PVE/API2/Network/SDN/Subnets.pm        |   4 +-
 PVE/Network/SDN/Ipams.pm               |   2 +
 PVE/Network/SDN/Ipams/Makefile         |   2 +-
 PVE/Network/SDN/Ipams/NetboxPlugin.pm  |   4 +-
 PVE/Network/SDN/Ipams/PVEPlugin.pm     | 166 +++++++++++++++++++++++++
 PVE/Network/SDN/Ipams/PhpIpamPlugin.pm |   2 +-
 PVE/Network/SDN/Ipams/Plugin.pm        |   2 +-
 debian/control                         |   1 +
 9 files changed, 177 insertions(+), 7 deletions(-)
 create mode 100644 PVE/Network/SDN/Ipams/PVEPlugin.pm

diff --git a/PVE/API2/Network/SDN/Ipams.pm b/PVE/API2/Network/SDN/Ipams.pm
index f8665a1..0d567c8 100644
--- a/PVE/API2/Network/SDN/Ipams.pm
+++ b/PVE/API2/Network/SDN/Ipams.pm
@@ -9,6 +9,7 @@ use PVE::Cluster qw(cfs_read_file cfs_write_file);
 use PVE::Network::SDN;
 use PVE::Network::SDN::Ipams;
 use PVE::Network::SDN::Ipams::Plugin;
+use PVE::Network::SDN::Ipams::PVEPlugin;
 use PVE::Network::SDN::Ipams::PhpIpamPlugin;
 use PVE::Network::SDN::Ipams::NetboxPlugin;
 
diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subnets.pm
index b60db3d..094401c 100644
--- a/PVE/API2/Network/SDN/Subnets.pm
+++ b/PVE/API2/Network/SDN/Subnets.pm
@@ -193,10 +193,10 @@ __PACKAGE__->register_method ({
 		$plugin->add_subnet($plugin_config, $id, $cfg->{ids}->{$id});
 
 		if($opts->{gateway} && $scfg->{gateway} && $opts->{gateway} ne $scfg->{gateway}) {
-		    $plugin->del_ip($plugin_config, $scfg->{gateway});
+		    $plugin->del_ip($plugin_config, $id, $scfg->{gateway});
 		}
 		if (!defined($opts->{gateway}) && $scfg->{gateway}) {
-		    $plugin->del_ip($plugin_config, $scfg->{gateway});
+		    $plugin->del_ip($plugin_config, $id, $scfg->{gateway});
 		} 
 		$plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) if $opts->{gateway};
 	    }
diff --git a/PVE/Network/SDN/Ipams.pm b/PVE/Network/SDN/Ipams.pm
index 3d33632..b634020 100644
--- a/PVE/Network/SDN/Ipams.pm
+++ b/PVE/Network/SDN/Ipams.pm
@@ -10,10 +10,12 @@ use PVE::Tools qw(extract_param dir_glob_regex run_command);
 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::Network;
 
+use PVE::Network::SDN::Ipams::PVEPlugin;
 use PVE::Network::SDN::Ipams::NetboxPlugin;
 use PVE::Network::SDN::Ipams::PhpIpamPlugin;
 use PVE::Network::SDN::Ipams::Plugin;
 
+PVE::Network::SDN::Ipams::PVEPlugin->register();
 PVE::Network::SDN::Ipams::NetboxPlugin->register();
 PVE::Network::SDN::Ipams::PhpIpamPlugin->register();
 PVE::Network::SDN::Ipams::Plugin->init();
diff --git a/PVE/Network/SDN/Ipams/Makefile b/PVE/Network/SDN/Ipams/Makefile
index 884c47a..4e7d65f 100644
--- a/PVE/Network/SDN/Ipams/Makefile
+++ b/PVE/Network/SDN/Ipams/Makefile
@@ -1,4 +1,4 @@
-SOURCES=Plugin.pm PhpIpamPlugin.pm NetboxPlugin.pm
+SOURCES=Plugin.pm PhpIpamPlugin.pm NetboxPlugin.pm PVEPlugin.pm
 
 
 PERL5DIR=${DESTDIR}/usr/share/perl5
diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index ccc1184..c25f451 100644
--- a/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -68,7 +68,7 @@ sub del_subnet {
     return if !$internalid;
     #fixme: check that prefix is empty exluding gateway, before delete
 
-    PVE::Network::SDN::Ipams::NetboxPlugin::del_ip($class, $plugin_config, $gateway) if $gateway;
+    PVE::Network::SDN::Ipams::NetboxPlugin::del_ip($class, $plugin_config, $subnetid, $gateway) if $gateway;
 
     eval {
 	PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
@@ -125,7 +125,7 @@ sub add_next_freeip {
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $ip) = @_;
 
     return if !$ip;
 
diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/PVEPlugin.pm
new file mode 100644
index 0000000..0dfc8a4
--- /dev/null
+++ b/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -0,0 +1,166 @@
+package PVE::Network::SDN::Ipams::PVEPlugin;
+
+use strict;
+use warnings;
+use PVE::INotify;
+use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file cfs_lock_file);
+use PVE::Tools;
+use JSON;
+use Net::IP;
+use Digest::SHA;
+
+use base('PVE::Network::SDN::Ipams::Plugin');
+
+
+my $ipamdb_file = "priv/ipam.db";
+
+PVE::Cluster::cfs_register_file($ipamdb_file,
+                                 sub { PVE::Network::SDN::Ipams::PVEPlugin->parse_config(@_); },
+                                 sub { PVE::Network::SDN::Ipams::PVEPlugin->write_config(@_); });
+
+sub type {
+    return 'pve';
+}
+
+sub properties {
+}
+
+sub options {
+}
+
+# Plugin implementation
+
+sub add_subnet {
+    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+
+    my $cidr = $subnetid =~ s/-/\//r;
+    my $gateway = $subnet->{gateway};
+
+    cfs_lock_file($ipamdb_file, undef, sub {
+	my $config = read_db();
+	#create subnet
+	if (!defined($config->{subnets}->{$cidr})) {
+	    $config->{subnets}->{$cidr}->{ips} = {};
+	    write_db($config);
+	}
+    });
+    die "$@" if $@;
+}
+
+sub del_subnet {
+    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+
+    my $cidr = $subnetid =~ s/-/\//r;
+
+    cfs_lock_file($ipamdb_file, undef, sub {
+
+	my $db = read_db();
+	my $ips = $db->{subnets}->{$cidr}->{ips};
+	die "can't delete subnet, not empty" if keys %{$ips} > 0;
+	delete $db->{subnets}->{$cidr};
+	write_db($db);
+    });
+    die "$@" if $@;
+
+}
+
+sub add_ip {
+    my ($class, $plugin_config, $subnetid, $ip, $is_gateway) = @_;
+
+    my $cidr = $subnetid =~ s/-/\//r;
+
+    cfs_lock_file($ipamdb_file, undef, sub {
+
+	my $db = read_db();
+	my $s = $db->{subnets}->{$cidr};
+
+	die "ip already exist" if defined($s->{ips}->{$ip});
+
+	#verify that ip is valid for this subnet
+	$s->{ips}->{$ip} = 1;
+	write_db($db);
+    });
+    die "$@" if $@;
+}
+
+sub add_next_freeip {
+    my ($class, $plugin_config, $subnetid, $subnet) = @_;
+
+    my $cidr = $subnetid =~ s/-/\//r;
+    my $freeip = undef;
+
+    cfs_lock_file($ipamdb_file, undef, sub {
+
+	my $db = read_db();
+	my $s = $db->{subnets}->{$cidr};
+
+	my $iplist = new Net::IP($cidr);
+
+	while(1) {
+	    my $ip = $iplist->ip();
+	    ++$iplist;
+	    print "nextip: $ip\n";
+	    next if defined($s->{ips}->{$ip});
+	    $freeip = $ip;
+	    last;
+	}
+
+	die "can't find free ip in subnet $cidr" if !$freeip;
+  
+	$s->{ips}->{$freeip} = 1;
+	write_db($db);
+    });
+    die "$@" if $@;
+
+    my ($network, $mask) = split(/-/, $subnetid);
+    return "$freeip/$mask";
+}
+
+sub del_ip {
+    my ($class, $plugin_config, $subnetid, $ip) = @_;
+
+    my $cidr = $subnetid =~ s/-/\//r;
+
+    cfs_lock_file($ipamdb_file, undef, sub {
+
+	my $db = read_db();
+	my $s = $db->{subnets}->{$cidr};
+	return if !$ip;
+
+	die "ip does not exist in pam" if !defined($s->{ips}->{$ip});
+	delete $s->{ips}->{$ip};
+	write_db($db);
+    });
+    die "$@" if $@;
+}
+
+#helpers
+
+sub read_db {
+    my $db = cfs_read_file($ipamdb_file);
+    return $db;
+}
+
+sub write_db {
+    my ($cfg) = @_;
+
+    my $json = to_json($cfg);
+    cfs_write_file($ipamdb_file, $json);
+}
+
+sub write_config {
+    my ($class, $filename, $cfg) = @_;
+
+    return $cfg;
+}
+
+sub parse_config {
+    my ($class, $filename, $raw) = @_;
+
+    $raw = '{}' if !defined($raw) ||$raw eq '';
+    my $cfg = from_json($raw);
+
+    return $cfg;
+}
+
+1;
diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index 7380bf3..d7ba3ed 100644
--- a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -145,7 +145,7 @@ sub add_next_freeip {
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $ip) = @_;
 
     return if !$ip;
 
diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plugin.pm
index 8a44090..fc736b8 100644
--- a/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/PVE/Network/SDN/Ipams/Plugin.pm
@@ -84,7 +84,7 @@ sub add_next_freeip {
 }
 
 sub del_ip {
-    my ($class, $plugin_config, $ip) = @_;
+    my ($class, $plugin_config, $subnetid, $ip) = @_;
 }
 
 
diff --git a/debian/control b/debian/control
index 8b67d74..c54f8bc 100644
--- a/debian/control
+++ b/debian/control
@@ -17,6 +17,7 @@ Depends: libpve-common-perl (>= 5.0-45),
          perl (>= 5.6.0-16),
          pve-cluster (>= 5.0-32),
          libnet-subnet-perl,
+         libnet-ip-perl,
          ${misc:Depends},
          ${perl:Depends},
 Recommends: frr-pythontools, ifupdown2
-- 
2.20.1





More information about the pve-devel mailing list