Regenerate the configuration files for the different DHCP server plugins when applying SDN settings by calling the respective hooks of the plugin responsible for configuring a DHCP instance.
Signed-off-by: Stefan Hanreich <s.hanre...@proxmox.com> --- src/PVE/Network/SDN.pm | 11 +- src/PVE/Network/SDN/Dhcp.pm | 192 +++++++++++++++++++++++++++++++++++ src/PVE/Network/SDN/Makefile | 2 +- 3 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 src/PVE/Network/SDN/Dhcp.pm diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm index 057034f..5c059bc 100644 --- a/src/PVE/Network/SDN.pm +++ b/src/PVE/Network/SDN.pm @@ -12,6 +12,7 @@ use PVE::Network::SDN::Vnets; use PVE::Network::SDN::Zones; use PVE::Network::SDN::Controllers; use PVE::Network::SDN::Subnets; +use PVE::Network::SDN::Dhcp; use PVE::Tools qw(extract_param dir_glob_regex run_command); use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file); @@ -149,13 +150,15 @@ sub commit_config { my $zones_cfg = PVE::Network::SDN::Zones::config(); my $controllers_cfg = PVE::Network::SDN::Controllers::config(); my $subnets_cfg = PVE::Network::SDN::Subnets::config(); + my $dhcp_cfg = PVE::Network::SDN::Dhcp::config(); my $vnets = { ids => $vnets_cfg->{ids} }; my $zones = { ids => $zones_cfg->{ids} }; my $controllers = { ids => $controllers_cfg->{ids} }; my $subnets = { ids => $subnets_cfg->{ids} }; + my $dhcp = { ids => $dhcp_cfg->{ids} }; - $cfg = { version => $version, vnets => $vnets, zones => $zones, controllers => $controllers, subnets => $subnets }; + $cfg = { version => $version, vnets => $vnets, zones => $zones, controllers => $controllers, subnets => $subnets, dhcps => $dhcp }; cfs_write_file($running_cfg, $cfg); } @@ -231,6 +234,12 @@ sub generate_controller_config { PVE::Network::SDN::Controllers::reload_controller() if $reload; } +sub generate_dhcp_config { + my ($reload) = @_; + + PVE::Network::SDN::Dhcp::regenerate_config($reload); +} + sub encode_value { my ($type, $key, $value) = @_; diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm new file mode 100644 index 0000000..b92c73a --- /dev/null +++ b/src/PVE/Network/SDN/Dhcp.pm @@ -0,0 +1,192 @@ +package PVE::Network::SDN::Dhcp; + +use strict; +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); +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 config { + my ($running) = @_; + + if ($running) { + my $cfg = PVE::Network::SDN::running_config(); + return $cfg->{dhcps}; + } + + return cfs_read_file('sdn/dhcp.cfg'); +} + +sub sdn_dhcps_config { + my ($cfg, $id, $noerr) = @_; + + die "No DHCP ID specified!\n" if !$id; + + my $dhcp_config = $cfg->{ids}->{$id}; + die "SDN DHCP '$id' does not exist!\n" if (!$noerr && !$dhcp_config); + + if ($dhcp_config) { + $dhcp_config->{id} = $id; + } + + return $dhcp_config; +} + +sub get_dhcp { + my ($dhcp_id, $running) = @_; + + return if !$dhcp_id; + + my $cfg = PVE::Network::SDN::Dhcp::config($running); + return PVE::Network::SDN::Dhcp::sdn_dhcps_config($cfg, $dhcp_id, 1); +} + +sub add_mapping { + my ($vmid, $vnet, $mac) = @_; + + my $vnet_config = PVE::Network::SDN::Vnets::get_vnet($vnet, 1); + return if !$vnet_config; + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnet, 1); + + for my $subnet_id (keys %{$subnets}) { + my $subnet_config = $subnets->{$subnet_id}; + + next if !$subnet_config->{'dhcp-range'}; + + foreach my $dhcp_range (@{$subnet_config->{'dhcp-range'}}) { + my $dhcp_config = PVE::Network::SDN::Dhcp::get_dhcp($dhcp_range->{server}); + + if (!$dhcp_config) { + warn "Cannot find configuration for DHCP server $dhcp_range->{server}"; + next; + } + + my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve'); + + my $data = { + vmid => $vmid, + mac => $mac, + }; + + my $ip = $ipam_plugin->add_dhcp_ip($subnet_config, $dhcp_range, $data); + + next if !$ip; + + my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type}); + $dhcp_plugin->add_ip_mapping($dhcp_config, $mac, $ip); + + return $ip; + } + } +} + +sub remove_mapping { + my ($vnet, $mac) = @_; + + my $vnet_config = PVE::Network::SDN::Vnets::get_vnet($vnet, 1); + return if !$vnet_config; + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnet, 1); + + for my $subnet_id (keys %{$subnets}) { + my $subnet_config = $subnets->{$subnet_id}; + next if !$subnet_config->{'dhcp-range'}; + + my $ipam_plugin = PVE::Network::SDN::Ipams::Plugin->lookup('pve'); + $ipam_plugin->del_dhcp_ip($subnet_config, $mac); + + foreach my $dhcp_range (@{$subnet_config->{'dhcp-range'}}) { + my $dhcp_config = PVE::Network::SDN::Dhcp::get_dhcp($dhcp_range->{server}); + + if (!$dhcp_config) { + warn "Cannot find configuration for DHCP server $dhcp_range->{server}"; + next; + } + + my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type}); + $dhcp_plugin->del_ip_mapping($dhcp_config, $mac); + } + } +} + +sub regenerate_config { + my ($reload) = @_; + + my $dhcps = PVE::Network::SDN::Dhcp::config(); + my $subnets = PVE::Network::SDN::Subnets::config(); + + my $plugins = PVE::Network::SDN::Dhcp::Plugin->lookup_types(); + + my $nodename = PVE::INotify::nodename(); + + 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 $dhcp_id (keys %{$dhcps->{ids}}) { + my $dhcp_config = PVE::Network::SDN::Dhcp::sdn_dhcps_config($dhcps, $dhcp_id); + my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type}); + + eval { $plugin->before_configure($dhcp_config) }; + die "Could not run before_configure for DHCP server $dhcp_id $@\n" if $@; + } + + foreach my $subnet_id (keys %{$subnets->{ids}}) { + my $subnet_config = PVE::Network::SDN::Subnets::sdn_subnets_config($subnets, $subnet_id); + next if !$subnet_config->{'dhcp-range'}; + + my @configured_servers = (); + + foreach my $dhcp_range (@{$subnet_config->{'dhcp-range'}}) { + my $dhcp_config = PVE::Network::SDN::Dhcp::sdn_dhcps_config($dhcps, $dhcp_range->{server}); + my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type}); + + next if $dhcp_config->{node} && !grep(/^$nodename$/, @{$dhcp_config->{node}}); + + if (!grep(/^$subnet_id$/, @configured_servers)) { + eval { $plugin->configure_subnet($dhcp_config, $subnet_config) }; + warn "Could not configure Subnet $subnet_id: $@\n" if $@; + + push @configured_servers, $subnet_id; + } + + eval { $plugin->configure_range($dhcp_config, $subnet_config, $dhcp_range) }; + warn "Could not configure DHCP range for $subnet_id: $@\n" if $@; + } + } + + foreach my $dhcp_id (keys %{$dhcps->{ids}}) { + my $dhcp_config = PVE::Network::SDN::Dhcp::sdn_dhcps_config($dhcps, $dhcp_id); + my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type}); + + eval { $plugin->after_configure($dhcp_config) }; + warn "Could not run after_configure for DHCP server $dhcp_id $@\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; diff --git a/src/PVE/Network/SDN/Makefile b/src/PVE/Network/SDN/Makefile index 848f7d4..3e6e5fb 100644 --- a/src/PVE/Network/SDN/Makefile +++ b/src/PVE/Network/SDN/Makefile @@ -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 -- 2.39.2 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel