public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Hanreich <s.hanreich@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC pve-network 6/6] sdn: dhcp: regenerate config for DHCP servers on reload
Date: Fri,  8 Sep 2023 15:43:04 +0200	[thread overview]
Message-ID: <20230908134304.2009415-7-s.hanreich@proxmox.com> (raw)
In-Reply-To: <20230908134304.2009415-1-s.hanreich@proxmox.com>

During config regeneration parsing of the SDN configuration happens in
one pass before generating the configuration files via the plugins in
order to avoid having to parse property strings in the subnet
configuration multiple times.

Then we call the respective hooks of the plugin responsible for
configuring a DHCP instance. The plugin should then handle the config
generation accordingly.

Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
 src/PVE/Network/SDN.pm       |  11 +++-
 src/PVE/Network/SDN/Dhcp.pm  | 122 +++++++++++++++++++++++++++++++++++
 src/PVE/Network/SDN/Makefile |   3 +-
 3 files changed, 133 insertions(+), 3 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..952f9dc 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, dhcp => $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..8c8a437
--- /dev/null
+++ b/src/PVE/Network/SDN/Dhcp.pm
@@ -0,0 +1,122 @@
+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);
+use PVE::Network::SDN::Dhcp::Plugin;
+use PVE::Network::SDN::Dhcp::Dnsmasq;
+use PVE::JSONSchema qw(parse_property_string);
+
+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 {
+    return cfs_read_file('sdn/dhcp.cfg');
+}
+
+sub parse_config {
+    my ($dhcps, $subnets, $nodename) = @_;
+
+    my %parsed_config;
+
+    for 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'};
+
+	foreach my $element (@{$subnet_config->{'dhcp-range'}}) {
+	    my $dhcp_range = eval { parse_property_string('pve-sdn-dhcp-range', $element) };
+
+	    if ($@ || !$dhcp_range) {
+		warn "Unable to parse dhcp-range string: $element\n";
+		warn "$@\n" if $@;
+		next;
+	    }
+
+	    my $dhcp_config = $dhcps->{ids}->{$dhcp_range->{server}};
+
+	    if (!$dhcp_config) {
+		warn "Cannot find configuration for DHCP server $dhcp_range->{server}";
+		next;
+	    }
+
+	    next if $dhcp_config->{node} && !grep(/^$nodename$/, @{$dhcp_config->{node}});
+
+	    push @{$parsed_config{$dhcp_range->{server}}{$subnet_id}}, $dhcp_range;
+	}
+    }
+
+    return \%parsed_config;
+}
+
+sub regenerate_config {
+    my ($reload) = @_;
+
+    my $dhcps = PVE::Network::SDN::Dhcp::config();
+    my $subnets = PVE::Network::SDN::Subnets::config();
+    my $nodename = PVE::INotify::nodename();
+    my $parsed_config = parse_config($dhcps, $subnets, $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 $@;
+    }
+
+    for my $dhcp_id (keys %$parsed_config) {
+	my $parsed_subnets = $parsed_config->{$dhcp_id};
+
+	next if !%$parsed_subnets;
+
+	my $dhcp_config = $dhcps->{ids}->{$dhcp_id};
+	$dhcp_config->{id} = $dhcp_id;
+
+	my $plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcp_config->{type});
+
+	eval { $plugin->before_configure($dhcp_config) };
+
+	if ($@) {
+	    warn "Could not run before_configure for DHCP server $dhcp_id $@\n" if $@;
+	    next;
+	}
+
+	for my $subnet_id (keys %$parsed_subnets) {
+	    my $subnet_config = PVE::Network::SDN::Subnets::sdn_subnets_config($subnets, $subnet_id);
+	    $subnet_config->{id} = $subnet_id;
+
+	    eval {
+		$plugin->configure_subnet(
+		    $dhcp_config,
+		    $subnet_config,
+		    $parsed_subnets->{$subnet_id},
+		);
+	    };
+	    warn "Could not configure Subnet $subnet_id: $@\n" if $@;
+	}
+
+	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..86c3b9d 100644
--- a/src/PVE/Network/SDN/Makefile
+++ b/src/PVE/Network/SDN/Makefile
@@ -1,5 +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




  parent reply	other threads:[~2023-09-08 13:43 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-08 13:42 [pve-devel] [RFC cluster/manager/network 0/6] Add support for DHCP servers to SDN Stefan Hanreich
2023-09-08 13:42 ` [pve-devel] [RFC pve-cluster 1/6] cluster files: add dhcp.cfg Stefan Hanreich
2023-09-08 13:43 ` [pve-devel] [RFC pve-manager 2/6] sdn: regenerate DHCP config on reload Stefan Hanreich
2023-09-08 13:43 ` [pve-devel] [RFC pve-network 3/6] sdn: dhcp: add abstract class for DHCP plugins Stefan Hanreich
2023-09-08 13:43 ` [pve-devel] [RFC pve-network 4/6] sdn: dhcp: subnet: add DHCP options to subnet configuration Stefan Hanreich
2023-09-11  4:03   ` DERUMIER, Alexandre
2023-09-13  8:37     ` Stefan Hanreich
2023-09-08 13:43 ` [pve-devel] [RFC pve-network 5/6] sdn: dhcp: add DHCP plugin for dnsmasq Stefan Hanreich
2023-09-08 13:43 ` Stefan Hanreich [this message]
2023-09-11  3:53 ` [pve-devel] [RFC cluster/manager/network 0/6] Add support for DHCP servers to SDN DERUMIER, Alexandre
2023-09-13  8:18   ` DERUMIER, Alexandre
2023-09-13  8:54   ` Stefan Hanreich
2023-09-13  9:26     ` DERUMIER, Alexandre
2023-09-13 11:37     ` Thomas Lamprecht
2023-09-13 11:43       ` DERUMIER, Alexandre
2023-09-13 11:50       ` Stefan Hanreich
2023-09-13 12:40         ` Thomas Lamprecht
2023-09-13 12:50         ` DERUMIER, Alexandre
2023-09-13 13:05           ` Stefan Hanreich
2023-09-13 13:21             ` DERUMIER, Alexandre
2023-09-13 13:48               ` Stefan Hanreich
2023-09-13 13:52                 ` Stefan Hanreich
2023-09-14 13:15                   ` DERUMIER, Alexandre
2023-09-20 21:48               ` DERUMIER, Alexandre
2023-09-26 11:20                 ` Stefan Hanreich
2023-09-26 13:07                   ` DERUMIER, Alexandre
2023-09-26 14:12                     ` Stefan Hanreich
2023-09-26 16:55                       ` DERUMIER, Alexandre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230908134304.2009415-7-s.hanreich@proxmox.com \
    --to=s.hanreich@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal