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 B787965F20 for ; Tue, 5 Jan 2021 10:35:41 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 98F6C25520 for ; Tue, 5 Jan 2021 10:35:41 +0100 (CET) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id 781D8254B9 for ; Tue, 5 Jan 2021 10:35:37 +0100 (CET) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id 5098F89E25; Tue, 5 Jan 2021 10:35:37 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Tue, 5 Jan 2021 10:35:24 +0100 Message-Id: <20210105093536.1727641-4-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210105093536.1727641-1-aderumier@odiso.com> References: <20210105093536.1727641-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.140 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.248 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.287 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 URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [vnets.pm, phpipamplugin.pm, pveplugin.pm, netboxplugin.pm, plugin.pm, subnets.pm] Subject: [pve-devel] [PATCH pve-network 03/15] ipam: add update_ip 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, 05 Jan 2021 09:35:41 -0000 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 --- 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