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 AAF5C618F5 for ; Mon, 28 Sep 2020 10:44:10 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 9FEC92B72D for ; Mon, 28 Sep 2020 10:44:00 +0200 (CEST) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id 0DCDE2B420 for ; Mon, 28 Sep 2020 10:43:38 +0200 (CEST) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id 026A8D6869; Mon, 28 Sep 2020 10:43:38 +0200 (CEST) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Mon, 28 Sep 2020 10:43:28 +0200 Message-Id: <20200928084336.3487196-19-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200928084336.3487196-1-aderumier@odiso.com> References: <20200928084336.3487196-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.435 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.078 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.399 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH v9 pve-network 18/26] add vnet to subnets && remove subnetlist from vnet 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: Mon, 28 Sep 2020 08:44:10 -0000 Signed-off-by: Alexandre Derumier --- PVE/API2/Network/SDN/Subnets.pm | 31 +------------- PVE/Network/SDN/SubnetPlugin.pm | 59 ++++++++++++++++++++------- PVE/Network/SDN/Subnets.pm | 34 +++++++++------ PVE/Network/SDN/VnetPlugin.pm | 23 ++++------- PVE/Network/SDN/Vnets.pm | 43 ++++++++++++------- PVE/Network/SDN/Zones/EvpnPlugin.pm | 10 ++--- PVE/Network/SDN/Zones/SimplePlugin.pm | 16 ++++---- 7 files changed, 117 insertions(+), 99 deletions(-) diff --git a/PVE/API2/Network/SDN/Subnets.pm b/PVE/API2/Network/SDN/Subnets.pm index 094401c..728b939 100644 --- a/PVE/API2/Network/SDN/Subnets.pm +++ b/PVE/API2/Network/SDN/Subnets.pm @@ -135,17 +135,7 @@ __PACKAGE__->register_method ({ } $cfg->{ids}->{$id} = $opts; - PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $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->add_subnet($plugin_config, $id, $cfg->{ids}->{$id}); - $plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) if $opts->{gateway}; - } + PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $opts); PVE::Network::SDN::Subnets::write_config($cfg); @@ -182,24 +172,7 @@ __PACKAGE__->register_method ({ my $opts = PVE::Network::SDN::SubnetPlugin->check_config($id, $param, 0, 1); $cfg->{ids}->{$id} = $opts; - PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $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->add_subnet($plugin_config, $id, $cfg->{ids}->{$id}); - - if($opts->{gateway} && $scfg->{gateway} && $opts->{gateway} ne $scfg->{gateway}) { - $plugin->del_ip($plugin_config, $id, $scfg->{gateway}); - } - if (!defined($opts->{gateway}) && $scfg->{gateway}) { - $plugin->del_ip($plugin_config, $id, $scfg->{gateway}); - } - $plugin->add_ip($plugin_config, $id, $opts->{gateway}, 1) if $opts->{gateway}; - } + PVE::Network::SDN::SubnetPlugin->on_update_hook($id, $opts, $scfg); PVE::Network::SDN::Subnets::write_config($cfg); diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm index bc66b82..84303d1 100644 --- a/PVE/Network/SDN/SubnetPlugin.pm +++ b/PVE/Network/SDN/SubnetPlugin.pm @@ -8,6 +8,8 @@ use base qw(PVE::SectionConfig); use PVE::JSONSchema qw(get_standard_option); use PVE::Exception qw(raise raise_param_exc); use Net::Subnet qw(subnet_matcher); +use PVE::Network::SDN::Vnets; +use PVE::Network::SDN::Ipams; PVE::Cluster::cfs_register_file('sdn/subnets.cfg', sub { __PACKAGE__->parse_config(@_); }, @@ -52,6 +54,10 @@ sub private { sub properties { return { + vnet => { + type => 'string', + description => "associated vnet", + }, gateway => { type => 'string', format => 'ip', description => "Subnet Gateway: Will be assign on vnet for layer3 zones", @@ -94,6 +100,7 @@ sub properties { sub options { return { + vnet => { optional => 1 }, gateway => { optional => 1 }, routes => { optional => 1 }, snat => { optional => 1 }, @@ -107,44 +114,66 @@ sub options { } sub on_update_hook { - my ($class, $subnetid, $subnet_cfg) = @_; + my ($class, $subnetid, $subnet, $old_subnet) = @_; my $cidr = $subnetid =~ s/-/\//r; my $subnet_matcher = subnet_matcher($cidr); - my $subnet = $subnet_cfg->{ids}->{$subnetid}; - + my $vnetid = $subnet->{vnet}; my $gateway = $subnet->{gateway}; + my $ipam = $subnet->{ipam}; my $dns = $subnet->{dns}; my $dnszone = $subnet->{dnszone}; my $reversedns = $subnet->{reversedns}; my $reversednszone = $subnet->{reversednszone}; - my ($ip, $mask) = split(/\//, $cidr); + my $old_gateway = $old_subnet->{gateway} if $old_subnet; + if($vnetid) { + my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid); + raise_param_exc({ vnet => "$vnetid don't exist"}) if !$vnet; + } + + my ($ip, $mask) = split(/\//, $cidr); #for /32 pointopoint, we allow gateway outside the subnet - raise_param_exc({ gateway => "$gateway is not in subnet $subnet"}) if $gateway && !$subnet_matcher->($gateway) && $mask != 32; + raise_param_exc({ gateway => "$gateway is not in subnet $subnetid"}) if $gateway && !$subnet_matcher->($gateway) && $mask != 32; raise_param_exc({ dns => "missing dns provider"}) if $dnszone && !$dns; raise_param_exc({ dnszone => "missing dns zone"}) if $dns && !$dnszone; raise_param_exc({ reversedns => "missing dns provider"}) if $reversednszone && !$reversedns; raise_param_exc({ reversednszone => "missing dns zone"}) if $reversedns && !$reversednszone; + if ($ipam) { + my $ipam_cfg = PVE::Network::SDN::Ipams::config(); + my $plugin_config = $ipam_cfg->{ids}->{$ipam}; + raise_param_exc({ ipam => "$ipam not existing"}) if !$plugin_config; + my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type}); + $plugin->add_subnet($plugin_config, $subnetid, $subnet); + + #delete on removal + if (!defined($gateway) && $old_gateway) { + eval { + PVE::Network::SDN::Subnets::del_ip($subnetid, $old_subnet, $old_gateway); + }; + warn if $@; + } + if(!$old_gateway || $gateway && $gateway ne $old_gateway) { + PVE::Network::SDN::Subnets::add_ip($subnetid, $subnet, $gateway); + } + + #delete old ip after update + if($gateway && $old_gateway && $gateway ne $old_gateway) { + eval { + PVE::Network::SDN::Subnets::del_ip($subnetid, $old_subnet, $old_gateway); + }; + warn if $@; + } + } } sub on_delete_hook { my ($class, $subnetid, $subnet_cfg, $vnet_cfg) = @_; - #verify if vnets have subnet - foreach my $vnetid (keys %{$vnet_cfg->{ids}}) { - my $vnet = $vnet_cfg->{ids}->{$vnetid}; - my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets}; - foreach my $subnet (@subnets) { - my $id = $subnet =~ s/\//-/r; - raise_param_exc({ subnet => "$subnet is attached to vnet $vnetid"}) if $id eq $subnetid; - } - } - return; } diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm index 4e8353e..d20af9e 100644 --- a/PVE/Network/SDN/Subnets.pm +++ b/PVE/Network/SDN/Subnets.pm @@ -57,20 +57,18 @@ sub get_subnet { } sub find_ip_subnet { - my ($ip, $subnetslist) = @_; - - my $subnets_cfg = PVE::Network::SDN::Subnets::config(); - my @subnets = PVE::Tools::split_list($subnetslist) if $subnetslist; + my ($ip, $subnets) = @_; my $subnet = undef; my $subnetid = undef; - foreach my $s (@subnets) { - my $subnet_matcher = subnet_matcher($s); - next if !$subnet_matcher->($ip); - $subnetid = $s =~ s/\//-/r; - $subnet = $subnets_cfg->{ids}->{$subnetid}; - last; + foreach my $id (sort keys %{$subnets}) { + my $cidr = $id =~ s/-/\//r; + my $subnet_matcher = subnet_matcher($cidr); + next if !$subnet_matcher->($ip); + $subnet = $subnets->{$id}; + $subnetid = $id; + last; } die "can't find any subnet for ip $ip" if !$subnet; @@ -143,8 +141,11 @@ sub next_free_ip { 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}); - $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet); - ($ip, undef) = split(/\//, $cidr); + eval { + $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet); + ($ip, undef) = split(/\//, $cidr); + }; + die $@ if $@; } eval { @@ -167,6 +168,8 @@ sub next_free_ip { sub add_ip { my ($subnetid, $subnet, $ip, $hostname) = @_; + return if !$subnet; + my $ipamid = $subnet->{ipam}; my $dns = $subnet->{dns}; my $dnszone = $subnet->{dnszone}; @@ -182,7 +185,10 @@ sub add_ip { 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}); - $plugin->add_ip($plugin_config, $subnetid, $ip); + eval { + $plugin->add_ip($plugin_config, $subnetid, $ip); + }; + die $@ if $@; } eval { @@ -204,6 +210,8 @@ sub add_ip { sub del_ip { my ($subnetid, $subnet, $ip, $hostname) = @_; + return if !$subnet; + my $ipamid = $subnet->{ipam}; my $dns = $subnet->{dns}; my $dnszone = $subnet->{dnszone}; diff --git a/PVE/Network/SDN/VnetPlugin.pm b/PVE/Network/SDN/VnetPlugin.pm index 6b2bcc8..47fd4d4 100644 --- a/PVE/Network/SDN/VnetPlugin.pm +++ b/PVE/Network/SDN/VnetPlugin.pm @@ -68,11 +68,6 @@ sub properties { description => "alias name of the vnet", optional => 1, }, - subnets => { - type => 'string', - description => "Subnets list", - optional => 1, - }, mac => { type => 'string', description => "Anycast router mac address", @@ -86,16 +81,21 @@ sub options { zone => { optional => 0}, tag => { optional => 1}, alias => { optional => 1 }, - subnets => { optional => 1 }, mac => { optional => 1 }, vlanaware => { optional => 1 }, }; } sub on_delete_hook { - my ($class, $sdnid, $vnet_cfg) = @_; + my ($class, $vnetid, $vnet_cfg) = @_; - return; + #verify if subnets are associated + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); + my @subnetlist = (); + foreach my $subnetid (sort keys %{$subnets}) { + push @subnetlist, $subnetid; + } + raise_param_exc({ vnet => "Vnet is attached to following subnets:". join(',', @subnetlist)}) if @subnetlist > 0; } sub on_update_hook { @@ -111,13 +111,6 @@ sub on_update_hook { } } } - - #verify subnet - my @subnets = PVE::Tools::split_list($vnet_cfg->{ids}->{$vnetid}->{subnets}) if $vnet_cfg->{ids}->{$vnetid}->{subnets}; - foreach my $subnet (@subnets) { - my $id = $subnet =~ s/\//-/r; - raise_param_exc({ subnet => "$subnet not existing"}) if !$subnet_cfg->{ids}->{$id}; - } } 1; diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm index c9916b1..7cec418 100644 --- a/PVE/Network/SDN/Vnets.pm +++ b/PVE/Network/SDN/Vnets.pm @@ -54,22 +54,35 @@ sub get_vnet { return $vnet; } +sub get_subnets { + my ($vnetid) = @_; + + my $subnets = {}; + my $subnets_cfg = PVE::Network::SDN::Subnets::config(); + foreach my $subnetid (sort keys %{$subnets_cfg->{ids}}) { + my $subnet = $subnets_cfg->{ids}->{$subnetid}; + next if !$subnet->{vnet} || $subnet->{vnet} ne $vnetid; + $subnets->{$subnetid} = $subnet; + } + return $subnets; + +} + sub get_next_free_ip { - my ($vnet, $hostname, $ipversion) = @_; + my ($vnetid, $hostname, $ipversion) = @_; $ipversion = 4 if !$ipversion; - my $subnets_cfg = PVE::Network::SDN::Subnets::config(); - my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets}; + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); my $ip = undef; - my $subnet = undef; my $subnetcount = 0; - foreach my $s (@subnets) { - my $subnetid = $s =~ s/\//-/r; + + foreach my $subnetid (sort keys %{$subnets}) { + my $subnet = $subnets->{$subnetid}; my ($network, $mask) = split(/-/, $subnetid); + next if $ipversion != Net::IP::ip_get_version($network); $subnetcount++; - $subnet = $subnets_cfg->{ids}->{$subnetid}; - if ($subnet && $subnet->{ipam}) { + if ($subnet->{ipam}) { eval { $ip = PVE::Network::SDN::Subnets::next_free_ip($subnetid, $subnet, $hostname); }; @@ -83,21 +96,23 @@ sub get_next_free_ip { } sub add_ip { - my ($vnet, $cidr, $hostname) = @_; + my ($vnetid, $cidr, $hostname) = @_; + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); my ($ip, $mask) = split(/\//, $cidr); - my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $vnet->{subnets}); - return if !$subnet->{ipam}; + my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $subnets); PVE::Network::SDN::Subnets::add_ip($subnetid, $subnet, $ip, $hostname); } sub del_ip { - my ($vnet, $cidr, $hostname) = @_; + my ($vnetid, $cidr, $hostname) = @_; + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); my ($ip, $mask) = split(/\//, $cidr); - my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $vnet->{subnets}); - return if !$subnet->{ipam}; + my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $subnets); PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname); } diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm b/PVE/Network/SDN/Zones/EvpnPlugin.pm index 17c9262..ff25f12 100644 --- a/PVE/Network/SDN/Zones/EvpnPlugin.pm +++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm @@ -76,12 +76,12 @@ sub generate_sdn_config { #vnet bridge @iface_config = (); - my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets}; my $address = {}; - foreach my $subnet (@subnets) { - my $subnetid = $subnet =~ s/\//-/r; - next if !defined($subnet_cfg->{ids}->{$subnetid}); - my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway}; + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); + foreach my $subnetid (sort keys %{$subnets}) { + my $subnet = $subnets->{$subnetid}; + my $cidr = $subnetid =~ s/-/\//r; + my $gateway = $subnet->{gateway}; if ($gateway) { push @iface_config, "address $gateway" if !defined($address->{$gateway}); $address->{$gateway} = 1; diff --git a/PVE/Network/SDN/Zones/SimplePlugin.pm b/PVE/Network/SDN/Zones/SimplePlugin.pm index a1733d5..a4299dd 100644 --- a/PVE/Network/SDN/Zones/SimplePlugin.pm +++ b/PVE/Network/SDN/Zones/SimplePlugin.pm @@ -35,19 +35,19 @@ sub generate_sdn_config { # vnet bridge my @iface_config = (); - my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets}; my $address = {}; - foreach my $subnet (@subnets) { - my $subnetid = $subnet =~ s/\//-/r; - next if !defined($subnet_cfg->{ids}->{$subnetid}); - my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway}; - if ($gateway) { + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid); + foreach my $subnetid (sort keys %{$subnets}) { + my $subnet = $subnets->{$subnetid}; + my $cidr = $subnetid =~ s/-/\//r; + my $gateway = $subnet->{gateway}; + if ($gateway) { push @iface_config, "address $gateway" if !defined($address->{$gateway}); $address->{$gateway} = 1; } #add route for /32 pointtopoint - my ($ip, $mask) = split(/\//, $subnet); - push @iface_config, "up ip route add $subnet dev $vnetid" if $mask == 32; + my ($ip, $mask) = split(/\//, $cidr); + push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32; } push @iface_config, "hwaddress $mac" if $mac; -- 2.20.1