[pve-devel] [PATCH pve-network 08/17] sdn: frr: add daemon status to frr helper
Fabian Grünbichler
f.gruenbichler at proxmox.com
Wed Apr 2 12:41:35 CEST 2025
On March 28, 2025 6:13 pm, Gabriel Goller wrote:
> From: Stefan Hanreich <s.hanreich at proxmox.com>
>
> Add functions that allow reading and manipulating values in the
> /etc/frr/daemons file. We need this for en/disabling daemons depending
> on which fabric types are configured. We only enable daemons which are
> required for the configured fabrics. If a daemon is enabled but a
> fabric gets deleted, we disable them.
>
> The helper works by iterating over the lines of the daemons file from
> FRR, parsing the key and checking if the key is managed by the SDN
> configuration, then sets it. As a safeguard, keys that can be changed
> by SDN have to be explicitly configured in the respective hash of the
> Frr module.
>
> Signed-off-by: Stefan Hanreich <s.hanreich at proxmox.com>
> Co-authored-by: Gabriel Goller <g.goller at proxmox.com>
> Signed-off-by: Gabriel Goller <g.goller at proxmox.com>
> ---
> src/PVE/Network/SDN.pm | 15 +++++++++++
> src/PVE/Network/SDN/Fabrics.pm | 18 +++++++++++++
> src/PVE/Network/SDN/Frr.pm | 49 ++++++++++++++++++++++++++++++++++
> 3 files changed, 82 insertions(+)
>
> diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm
> index b777a098a987..a0b61275e10b 100644
> --- a/src/PVE/Network/SDN.pm
> +++ b/src/PVE/Network/SDN.pm
> @@ -258,12 +258,27 @@ sub generate_frr_raw_config {
> return $raw_config;
> }
>
> +=head3 get_frr_daemon_status(\%running_config, \%fabric_config)
> +
> +Returns a hash that indicates the status of the FRR daemons managed by SDN.
> +
> +=cut
> +
> +sub get_frr_daemon_status {
> + my ($running_config, $fabric_config) = @_;
> +
> + return PVE::Network::SDN::Fabrics::get_frr_daemon_status($fabric_config);
this takes but doesn't use the $running_config.. is this intentional?
> +}
> +
> sub generate_frr_config {
> my ($reload) = @_;
>
> my $running_config = PVE::Network::SDN::running_config();
> my $fabric_config = PVE::Network::SDN::Fabrics::config(1);
>
> + my $daemon_status = PVE::Network::SDN::get_frr_daemon_status($running_config, $fabric_config);
the getter has a top-level wrapper
> + PVE::Network::SDN::Frr::set_daemon_status($daemon_status);
but the setter doesn't? seems inconsistent ;)
> +
> my $raw_config = PVE::Network::SDN::generate_frr_raw_config($running_config, $fabric_config);
> PVE::Network::SDN::Frr::write_raw_config($raw_config);
>
> diff --git a/src/PVE/Network/SDN/Fabrics.pm b/src/PVE/Network/SDN/Fabrics.pm
> index 6e3fa5234a5b..d716c68feac4 100644
> --- a/src/PVE/Network/SDN/Fabrics.pm
> +++ b/src/PVE/Network/SDN/Fabrics.pm
> @@ -69,6 +69,24 @@ sub config_for_protocol {
> return $module->config($section_config);
> }
>
> +sub get_frr_daemon_status {
> + my ($fabric_config) = @_;
> +
> + my $daemon_status = {};
> + my $nodename = PVE::INotify::nodename();
> +
> + for my $protocol (sort keys %$fabric_config) {
> + my $config = $fabric_config->{$protocol};
this could iterate over the values instead? ;)
> + my $enabled_daemons = $config->enabled_daemons($nodename);
> +
> + for my $daemon (@$enabled_daemons) {
> + $daemon_status->{$daemon} = 1;
> + }
> + }
> +
> + return $daemon_status;
> +}
> +
> sub generate_frr_raw_config {
> my ($fabric_config) = @_;
>
> diff --git a/src/PVE/Network/SDN/Frr.pm b/src/PVE/Network/SDN/Frr.pm
> index bb0f197d8dea..9ae302a9c25f 100644
> --- a/src/PVE/Network/SDN/Frr.pm
> +++ b/src/PVE/Network/SDN/Frr.pm
> @@ -77,6 +77,55 @@ sub reload {
> }
> }
>
> +my $SDN_DAEMONS_DEFAULT = {
> + ospfd => 0,
> + fabricd => 0,
> +};
> +
> +=head3 set_daemon_status(\%daemons, $set_default)
> +
> +Sets the status of all daemons supplied in C<\%daemons>. This only works for
> +daemons managed by SDN, as indicated in the C<$SDN_DAEMONS_DEFAULT> constant. If
> +a daemon is supplied that isn't managed by SDN then this command will fail. If
> +C<$set_default> is set, then additionally all sdn-managed daemons that are
> +missing in C<\%daemons> are reset to their default value.
> +
> +=cut
> +
> +sub set_daemon_status {
> + my ($daemon_status, $set_default) = @_;
> +
> + for my $daemon (keys %$daemon_status) {
> + die "$daemon is not SDN managed" if !defined $SDN_DAEMONS_DEFAULT->{$daemon};
> + }
> +
> + my $daemons_file = "/etc/frr/daemons";
> +
> + my $old_config = PVE::Tools::file_get_contents($daemons_file);
> + my $new_config = "";
> +
> + my @lines = split(/\n/, $old_config);
> +
> + for my $line (@lines) {
so we have three cases here
- line contains one of our daemons as key (=> set status)
- line contains something else as key (=> keep line as is)
- line contains no key but something else entirely (=> keep line as is)
I think this could be structured so that it is a bit more readable/easy
to follow along..
first, fill in the defaults if needed:
if ($set_default) {
for my $daemon (keys %$SDN_DAEMONS_DEFAULT) {
$daemon_status->{$daemon} = $SDN_DAEMONS_DEFAULT->{$daemon}
if !defined($daemon_status->{$daemon});
}
}
and then simply override lines as needed:
for my $line (@lines) {
if ($line =~ m/^([a-z_]+)=/) {
my $key = $1;
my $status = $daemon_status->{$key};
if (defined($status)) {
my $value = status ? "yes" : "no";
$line = "$key=$value";
}
}
$new_config .= "$line\n";
}
> + if ($line =~ m/^([a-z_]+)=/) {
> + my $key = $1;
> +
> + my $status = $daemon_status->{$key};
> + $status = $SDN_DAEMONS_DEFAULT->{$key} if !defined $status && $set_default;
> +
> + if (defined $status) {
> + my $value = $status ? "yes" : "no";
> + $new_config .= "$key=$value\n";
> + next;
> + }
> + }
> +
> + $new_config .= "$line\n";
> + }
> +
> + PVE::Tools::file_set_contents($daemons_file, $new_config);
> +}
> +
> =head3 to_raw_config(\%frr_config)
>
> Converts a given C<\%frr_config> to the raw config format.
> --
> 2.39.5
>
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
>
More information about the pve-devel
mailing list