]> git.proxmox.com Git - pve-network.git/commitdiff
sdn: dhcp: add helper for creating DHCP leases
authorStefan Hanreich <s.hanreich@proxmox.com>
Fri, 17 Nov 2023 11:39:47 +0000 (12:39 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Sat, 18 Nov 2023 14:59:50 +0000 (15:59 +0100)
This helper can be used to create DHCP entries for a specific zone. It
is used by the API to create DHCP leases for VMs/CTs.

Co-Authored-By: Alexandre Derumier <aderumier@odiso.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
src/PVE/Network/SDN/Dhcp.pm [new file with mode: 0644]
src/PVE/Network/SDN/Makefile

diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm
new file mode 100644 (file)
index 0000000..a05b441
--- /dev/null
@@ -0,0 +1,115 @@
+package PVE::Network::SDN::Dhcp;
+
+use strict;
+use warnings;
+
+use PVE::Cluster qw(cfs_read_file);
+
+use PVE::Network::SDN;
+use PVE::Network::SDN::SubnetPlugin;
+use PVE::Network::SDN::Dhcp qw(config);
+use PVE::Network::SDN::Subnets qw(sdn_subnets_config config get_dhcp_ranges);
+use PVE::Network::SDN::Dhcp::Plugin;
+use PVE::Network::SDN::Dhcp::Dnsmasq;
+
+use PVE::INotify qw(nodename);
+
+PVE::Network::SDN::Dhcp::Plugin->init();
+
+PVE::Network::SDN::Dhcp::Dnsmasq->register();
+PVE::Network::SDN::Dhcp::Dnsmasq->init();
+
+sub add_mapping {
+    my ($vnetid, $mac, $ip4, $ip6) = @_;
+
+    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    return if !$vnet;
+
+    my $zoneid = $vnet->{zone};
+    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+    return if !$zone->{ipam} || !$zone->{dhcp};
+
+    my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($zone->{dhcp});
+    $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 $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    return if !$vnet;
+
+    my $zoneid = $vnet->{zone};
+    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+    return if !$zone->{ipam} || !$zone->{dhcp};
+
+    my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($zone->{dhcp});
+    $dhcp_plugin->del_ip_mapping($zoneid, $mac);
+}
+
+sub regenerate_config {
+    my ($reload) = @_;
+
+    my $cfg = PVE::Network::SDN::running_config();
+
+    my $zone_cfg = $cfg->{zones};
+    my $subnet_cfg = $cfg->{subnets};
+    return if !$zone_cfg && !$subnet_cfg;
+
+    my $nodename = PVE::INotify::nodename();
+
+    my $plugins = PVE::Network::SDN::Dhcp::Plugin->lookup_types();
+
+    foreach my $plugin_name (@$plugins) {
+       my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
+       eval { $plugin->before_regenerate() };
+       die "Could not run before_regenerate for DHCP plugin $plugin_name $@\n" if $@;
+    }
+
+    foreach my $zoneid (sort keys %{$zone_cfg->{ids}}) {
+        my $zone = $zone_cfg->{ids}->{$zoneid};
+        next if !$zone->{dhcp};
+
+       my $dhcp_plugin_name = $zone->{dhcp};
+       my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_plugin_name);
+
+       die "Could not find DHCP plugin: $dhcp_plugin_name" if !$dhcp_plugin;
+
+       eval { $dhcp_plugin->before_configure($zoneid) };
+       die "Could not run before_configure for DHCP server $zoneid $@\n" if $@;
+
+
+       foreach my $subnet_id (keys %{$subnet_cfg->{ids}}) {
+           my $subnet_config = PVE::Network::SDN::Subnets::sdn_subnets_config($subnet_cfg, $subnet_id);
+           my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet_config);
+
+           my ($zone, $subnet_network, $subnet_mask) = split(/-/, $subnet_id);
+           next if $zone ne $zoneid;
+           next if !$dhcp_ranges;
+
+           eval { $dhcp_plugin->configure_subnet($zoneid, $subnet_config) };
+           warn "Could not configure subnet $subnet_id: $@\n" if $@;
+
+           foreach my $dhcp_range (@$dhcp_ranges) {
+               eval { $dhcp_plugin->configure_range($zoneid, $subnet_config, $dhcp_range) };
+               warn "Could not configure DHCP range for $subnet_id: $@\n" if $@;
+           }
+       }
+
+       eval { $dhcp_plugin->after_configure($zoneid) };
+       warn "Could not run after_configure for DHCP server $zoneid $@\n" if $@;
+
+    }
+
+    foreach my $plugin_name (@$plugins) {
+       my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($plugin_name);
+
+       eval { $plugin->after_regenerate() };
+       warn "Could not run after_regenerate for DHCP plugin $plugin_name $@\n" if $@;
+    }
+}
+
+1;
index 848f7d44edd6eebe5543d24d3ee2f766a7292bac..3e6e5fb4c6f25283457c389353343c9872889cae 100644 (file)
@@ -1,4 +1,4 @@
-SOURCES=Vnets.pm VnetPlugin.pm Zones.pm Controllers.pm Subnets.pm SubnetPlugin.pm Ipams.pm Dns.pm
+SOURCES=Vnets.pm VnetPlugin.pm Zones.pm Controllers.pm Subnets.pm SubnetPlugin.pm Ipams.pm Dns.pm Dhcp.pm
 
 
 PERL5DIR=${DESTDIR}/usr/share/perl5