[pve-devel] [RFC pve-network 5/9] ipam : add get_ips_from_mac
Alexandre Derumier
aderumier at odiso.com
Mon Nov 13 11:04:14 CET 2023
First look ip mac.db cache
if not, lookup in ipam , and cache result in mac.db
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
src/PVE/Network/SDN/Dhcp.pm | 8 ++----
src/PVE/Network/SDN/Ipams.pm | 19 +++++++++++--
src/PVE/Network/SDN/Ipams/NetboxPlugin.pm | 25 +++++++++++++++++
src/PVE/Network/SDN/Ipams/PVEPlugin.pm | 32 ++++++++++++++++++++++
src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 29 ++++++++++++++++++++
src/PVE/Network/SDN/Ipams/Plugin.pm | 6 ++++
src/PVE/Network/SDN/Vnets.pm | 11 ++++++++
7 files changed, 123 insertions(+), 7 deletions(-)
diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm
index 1c32fec..b3c2751 100644
--- a/src/PVE/Network/SDN/Dhcp.pm
+++ b/src/PVE/Network/SDN/Dhcp.pm
@@ -6,7 +6,6 @@ use warnings;
use PVE::Cluster qw(cfs_read_file);
use PVE::Network::SDN;
-use PVE::Network::SDN::Ipams::Plugin;
use PVE::Network::SDN::SubnetPlugin;
use PVE::Network::SDN::Dhcp qw(config);
use PVE::Network::SDN::Subnets qw(sdn_subnets_config config);
@@ -21,9 +20,8 @@ PVE::Network::SDN::Dhcp::Dnsmasq->register();
PVE::Network::SDN::Dhcp::Dnsmasq->init();
sub add_mapping {
- my ($vmid, $vnetid, $mac, $ip) = @_;
+ my ($vnetid, $mac, $ip4, $ip6) = @_;
- 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);
@@ -32,13 +30,13 @@ sub add_mapping {
return if !$dhcptype;
my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcptype);
- $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip);
+ $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip4) if $ip4;
+ $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip6) if $ip6;
}
sub remove_mapping {
my ($vnetid, $mac) = @_;
- 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);
diff --git a/src/PVE/Network/SDN/Ipams.pm b/src/PVE/Network/SDN/Ipams.pm
index a459441..926df90 100644
--- a/src/PVE/Network/SDN/Ipams.pm
+++ b/src/PVE/Network/SDN/Ipams.pm
@@ -98,8 +98,8 @@ sub config {
}
sub get_plugin_config {
- my ($vnet) = @_;
- my $ipamid = $vnet->{ipam};
+ my ($zone) = @_;
+ my $ipamid = $zone->{ipam};
my $ipam_cfg = PVE::Network::SDN::Ipams::config();
return $ipam_cfg->{ids}->{$ipamid};
}
@@ -124,5 +124,20 @@ sub complete_sdn_vnet {
return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Vnets::sdn_ipams_ids($cfg) ];
}
+sub get_ips_from_mac {
+ my ($mac, $zoneid, $zone) = @_;
+
+ my $macdb = read_macdb();
+ return ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) if $macdb->{macs}->{$mac};
+
+ my $plugin_config = get_plugin_config($zone);
+ my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
+ ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) = $plugin->get_ips_from_mac($plugin_config, $mac, $zoneid);
+
+ write_macdb($macdb);
+
+ return ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6});
+}
+
1;
diff --git a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
index 2099a7f..e6cc647 100644
--- a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm
@@ -198,6 +198,31 @@ sub del_ip {
}
}
+sub get_ips_from_mac {
+ my ($class, $plugin_config, $mac, $zoneid) = @_;
+
+ my $url = $plugin_config->{url};
+ my $token = $plugin_config->{token};
+ my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+
+ my $ip4 = undef;
+ my $ip6 = undef;
+
+ my $data = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?description__ic=$mac", $headers);
+ for my $ip (@{$data->{results}}) {
+ if ($ip->{family}->{value} == 4 && !$ip4) {
+ ($ip4, undef) = split(/\//, $ip->{address});
+ }
+
+ if ($ip->{family}->{value} == 6 && !$ip6) {
+ ($ip6, undef) = split(/\//, $ip->{address});
+ }
+ }
+
+ return ($ip4, $ip6);
+}
+
+
sub verify_api {
my ($class, $plugin_config) = @_;
diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 5790715..0bc2b65 100644
--- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -242,6 +242,38 @@ sub del_ip {
die "$@" if $@;
}
+sub get_ips_from_mac {
+ my ($class, $plugin_config, $mac, $zoneid) = @_;
+
+ #just in case, as this should already be cached in local macs.db
+
+ my $ip4 = undef;
+ my $ip6 = undef;
+
+ my $db = read_db();
+ die "zone $zoneid don't exist in ipam db" if !$db->{zones}->{$zoneid};
+ my $dbzone = $db->{zones}->{$zoneid};
+ my $subnets = $dbzone->{subnets};
+
+ for my $subnet ( keys %$subnets) {
+ next if Net::IP::ip_is_ipv4($subnet) && $ip4;
+ next if $ip6;
+ my $ips = $subnets->{$subnet}->{ips};
+ for my $ip (keys %$ips) {
+ my $ipobject = $ips->{$ip};
+ if ($ipobject->{mac} && $ipobject->{mac} eq $mac) {
+ if (Net::IP::ip_is_ipv4($ip)) {
+ $ip4 = $ip;
+ } else {
+ $ip6 = $ip;
+ }
+ }
+ }
+ last if $ip4 && $ip6;
+ }
+ return ($ip4, $ip6);
+}
+
#helpers
sub read_db {
diff --git a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
index ad5286b..1b7b666 100644
--- a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
@@ -204,6 +204,35 @@ sub del_ip {
}
}
+sub get_ips_from_mac {
+ my ($class, $plugin_config, $mac, $zoneid) = @_;
+
+
+ my $url = $plugin_config->{url};
+ my $token = $plugin_config->{token};
+ my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token];
+
+ my $ip4 = undef;
+ my $ip6 = undef;
+
+ my $ips = PVE::Network::SDN::api_request("GET", "$url/addresses/search_mac/$mac", $headers);
+
+ #fixme
+ die "parsing of result not yet implemented";
+
+ for my $ip (@$ips) {
+# if ($ip->{family}->{value} == 4 && !$ip4) {
+# ($ip4, undef) = split(/\//, $ip->{address});
+# }
+#
+# if ($ip->{family}->{value} == 6 && !$ip6) {
+# ($ip6, undef) = split(/\//, $ip->{address});
+# }
+ }
+
+ return ($ip4, $ip6);
+}
+
sub verify_api {
my ($class, $plugin_config) = @_;
diff --git a/src/PVE/Network/SDN/Ipams/Plugin.pm b/src/PVE/Network/SDN/Ipams/Plugin.pm
index 4d85b81..59c7e31 100644
--- a/src/PVE/Network/SDN/Ipams/Plugin.pm
+++ b/src/PVE/Network/SDN/Ipams/Plugin.pm
@@ -111,6 +111,12 @@ sub del_ip {
die "please implement inside plugin";
}
+sub get_ips_from_mac {
+ my ($class, $plugin_config, $mac, $zone) = @_;
+
+ die "please implement inside plugin";
+}
+
sub on_update_hook {
my ($class, $plugin_config) = @_;
}
diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm
index 76a6caf..9ba1a1e 100644
--- a/src/PVE/Network/SDN/Vnets.pm
+++ b/src/PVE/Network/SDN/Vnets.pm
@@ -155,6 +155,17 @@ sub del_cidr {
PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $skipdns);
}
+sub get_ips_from_mac {
+ my ($vnetid, $mac) = @_;
+ my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+ my $zoneid = $vnet->{zone};
+ my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+ my $ipam = $zone->{ipam};
+ return if !$ipam;
+
+ return PVE::Network::SDN::Ipams::get_ips_from_mac($mac, $zoneid, $zone);
+}
1;
--
2.39.2
More information about the pve-devel
mailing list