From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 4DED3635AF for ; Tue, 25 Aug 2020 07:21:18 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C0C542303E for ; Tue, 25 Aug 2020 07:21:15 +0200 (CEST) Received: from mailpro.odiso.net (mailpro.odiso.net [89.248.211.110]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 1806C22D14 for ; Tue, 25 Aug 2020 07:20:58 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mailpro.odiso.net (Postfix) with ESMTP id EE9B515B9E32; Tue, 25 Aug 2020 07:20:57 +0200 (CEST) Received: from mailpro.odiso.net ([127.0.0.1]) by localhost (mailpro.odiso.net [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id f_bdXpIgBngS; Tue, 25 Aug 2020 07:20:57 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mailpro.odiso.net (Postfix) with ESMTP id D39DA15B9EA9; Tue, 25 Aug 2020 07:20:57 +0200 (CEST) X-Virus-Scanned: amavisd-new at mailpro.odiso.com Received: from mailpro.odiso.net ([127.0.0.1]) by localhost (mailpro.odiso.net [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id ohN6xlEtiHs1; Tue, 25 Aug 2020 07:20:57 +0200 (CEST) Received: from pve.fritz.box (unknown [213.211.148.86]) by mailpro.odiso.net (Postfix) with ESMTPSA id A184715B9E3C; Tue, 25 Aug 2020 07:20:57 +0200 (CEST) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Tue, 25 Aug 2020 07:02:15 +0200 Message-Id: <20200825050222.12447-12-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200825050222.12447-1-aderumier@odiso.com> References: <20200825050222.12447-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SPAM-LEVEL: Spam detection results: 0 AWL 0.000 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_DNSWL_NONE -0.0001 Sender listed at https://www.dnswl.org/, no trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [subnets.pm, ipams.pm, netboxplugin.pm, plugin.pm, pveplugin.pm, phpipamplugin.pm] Subject: [pve-devel] [PATCH v6 pve-network 11/18] add pve internal ipam plugin X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Aug 2020 05:21:18 -0000 --- 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.p= m 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; =20 diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subne= ts.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}); =20 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}); }=20 $plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) if $opts->{g= ateway}; } 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_co= mmand); use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file); use PVE::Network; =20 +use PVE::Network::SDN::Ipams::PVEPlugin; use PVE::Network::SDN::Ipams::NetboxPlugin; use PVE::Network::SDN::Ipams::PhpIpamPlugin; use PVE::Network::SDN::Ipams::Plugin; =20 +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/Makef= ile index 884c47a..4e7d65f 100644 --- a/PVE/Network/SDN/Ipams/Makefile +++ b/PVE/Network/SDN/Ipams/Makefile @@ -1,4 +1,4 @@ -SOURCES=3DPlugin.pm PhpIpamPlugin.pm NetboxPlugin.pm +SOURCES=3DPlugin.pm PhpIpamPlugin.pm NetboxPlugin.pm PVEPlugin.pm =20 =20 PERL5DIR=3D${DESTDIR}/usr/share/perl5 diff --git a/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/PVE/Network/SDN/Ipam= s/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 =20 - PVE::Network::SDN::Ipams::NetboxPlugin::del_ip($class, $plugin_confi= g, $gateway) if $gateway; + PVE::Network::SDN::Ipams::NetboxPlugin::del_ip($class, $plugin_confi= g, $subnetid, $gateway) if $gateway; =20 eval { PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/pref= ixes/$internalid/", $headers); @@ -125,7 +125,7 @@ sub add_next_freeip { } =20 sub del_ip { - my ($class, $plugin_config, $ip) =3D @_; + my ($class, $plugin_config, $subnetid, $ip) =3D @_; =20 return if !$ip; =20 diff --git a/PVE/Network/SDN/Ipams/PVEPlugin.pm b/PVE/Network/SDN/Ipams/P= VEPlugin.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_l= ock_file); +use PVE::Tools; +use JSON; +use Net::IP; +use Digest::SHA; + +use base('PVE::Network::SDN::Ipams::Plugin'); + + +my $ipamdb_file =3D "priv/ipam.db"; + +PVE::Cluster::cfs_register_file($ipamdb_file, + sub { PVE::Network::SDN::Ipams::PVEPlug= in->parse_config(@_); }, + sub { PVE::Network::SDN::Ipams::PVEPlug= in->write_config(@_); }); + +sub type { + return 'pve'; +} + +sub properties { +} + +sub options { +} + +# Plugin implementation + +sub add_subnet { + my ($class, $plugin_config, $subnetid, $subnet) =3D @_; + + my $cidr =3D $subnetid =3D~ s/-/\//r; + my $gateway =3D $subnet->{gateway}; + + cfs_lock_file($ipamdb_file, undef, sub { + my $config =3D read_db(); + #create subnet + if (!defined($config->{subnets}->{$cidr})) { + $config->{subnets}->{$cidr}->{ips} =3D {}; + write_db($config); + } + }); + die "$@" if $@; +} + +sub del_subnet { + my ($class, $plugin_config, $subnetid, $subnet) =3D @_; + + my $cidr =3D $subnetid =3D~ s/-/\//r; + + cfs_lock_file($ipamdb_file, undef, sub { + + my $db =3D read_db(); + my $ips =3D $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) =3D @_; + + my $cidr =3D $subnetid =3D~ s/-/\//r; + + cfs_lock_file($ipamdb_file, undef, sub { + + my $db =3D read_db(); + my $s =3D $db->{subnets}->{$cidr}; + + die "ip already exist" if defined($s->{ips}->{$ip}); + + #verify that ip is valid for this subnet + $s->{ips}->{$ip} =3D 1; + write_db($db); + }); + die "$@" if $@; +} + +sub add_next_freeip { + my ($class, $plugin_config, $subnetid, $subnet) =3D @_; + + my $cidr =3D $subnetid =3D~ s/-/\//r; + my $freeip =3D undef; + + cfs_lock_file($ipamdb_file, undef, sub { + + my $db =3D read_db(); + my $s =3D $db->{subnets}->{$cidr}; + + my $iplist =3D new Net::IP($cidr); + + while(1) { + my $ip =3D $iplist->ip(); + ++$iplist; + print "nextip: $ip\n"; + next if defined($s->{ips}->{$ip}); + $freeip =3D $ip; + last; + } + + die "can't find free ip in subnet $cidr" if !$freeip; + =20 + $s->{ips}->{$freeip} =3D 1; + write_db($db); + }); + die "$@" if $@; + + my ($network, $mask) =3D split(/-/, $subnetid); + return "$freeip/$mask"; +} + +sub del_ip { + my ($class, $plugin_config, $subnetid, $ip) =3D @_; + + my $cidr =3D $subnetid =3D~ s/-/\//r; + + cfs_lock_file($ipamdb_file, undef, sub { + + my $db =3D read_db(); + my $s =3D $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 =3D cfs_read_file($ipamdb_file); + return $db; +} + +sub write_db { + my ($cfg) =3D @_; + + my $json =3D to_json($cfg); + cfs_write_file($ipamdb_file, $json); +} + +sub write_config { + my ($class, $filename, $cfg) =3D @_; + + return $cfg; +} + +sub parse_config { + my ($class, $filename, $raw) =3D @_; + + $raw =3D '{}' if !defined($raw) ||$raw eq ''; + my $cfg =3D from_json($raw); + + return $cfg; +} + +1; diff --git a/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/PVE/Network/SDN/Ipa= ms/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 { } =20 sub del_ip { - my ($class, $plugin_config, $ip) =3D @_; + my ($class, $plugin_config, $subnetid, $ip) =3D @_; =20 return if !$ip; =20 diff --git a/PVE/Network/SDN/Ipams/Plugin.pm b/PVE/Network/SDN/Ipams/Plug= in.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 { } =20 sub del_ip { - my ($class, $plugin_config, $ip) =3D @_; + my ($class, $plugin_config, $subnetid, $ip) =3D @_; } =20 =20 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 (>=3D 5.0-45), perl (>=3D 5.6.0-16), pve-cluster (>=3D 5.0-32), libnet-subnet-perl, + libnet-ip-perl, ${misc:Depends}, ${perl:Depends}, Recommends: frr-pythontools, ifupdown2 --=20 2.20.1