[..]
> > diff --git a/src/PVE/CLI/pvesdn.pm b/src/PVE/CLI/pvesdn.pm
> > new file mode 100644
> > index 000000000000..ebb0b60715c9
> > --- /dev/null
> > +++ b/src/PVE/CLI/pvesdn.pm
> > @@ -0,0 +1,252 @@
> > [..]
> > +__PACKAGE__->register_method({
> > + name => 'override',
> > + path => 'override',
> > + method => 'GET',
> > + description => "Override FRR templates.",
> > + parameters => {
> > + properties => {
> > + protocol => {
> > + description =>
> > + "Specifies the FRR routing protocol (e.g., 'bgp',
> > 'ospf') or template file (e.g., 'access_lists.jinja') to copy to the
> > override directory for customization.",
> > + type => 'string',
> > + },
> > + },
> > +
> > + },
> > + returns => { type => 'null' },
> > + code => sub {
> > + my ($param) = @_;
> > + my @template_files = ();
> > +
> > + if ($param->{protocol} eq 'openfabric') {
> > + push(@template_files, 'frr.conf.jinja');
> > + push(@template_files, 'fabricd.jinja');
> > + push(@template_files, 'protocol_routemaps.jinja');
> > + push(@template_files, 'route_maps.jinja');
> > + push(@template_files, 'access_lists.jinja');
> > + push(@template_files, 'interface.jinja');
> > + } elsif ($param->{protocol} eq 'ospf') {
> > + push(@template_files, 'frr.conf.jinja');
> > + push(@template_files, 'ospfd.jinja');
> > + push(@template_files, 'protocol_routemaps.jinja');
> > + push(@template_files, 'route_maps.jinja');
> > + push(@template_files, 'access_lists.jinja');
> > + push(@template_files, 'interface.jinja');
> > + } elsif ($param->{protocol} eq 'isis') {
> > + push(@template_files, 'frr.conf.jinja');
> > + push(@template_files, 'isisd.jinja');
> > + push(@template_files, 'interface.jinja');
> > + } elsif ($param->{protocol} eq 'bgp') {
> > + push(@template_files, 'frr.conf.jinja');
> > + push(@template_files, 'bgpd.jinja');
> > + push(@template_files, 'bgp_router.jinja');
> > + push(@template_files, 'route_maps.jinja');
> > + push(@template_files, 'access_lists.jinja');
> > + push(@template_files, 'prefix_lists.jinja');
> > + push(@template_files, 'ip_routes.jinja');
> > + } else {
> > + push(@template_files, $param->{protocol});
> > + }
> > +
> > + File::Path::make_path($TEMPLATE_OVERRIDE_DIR);
> > +
> > + foreach my $template (@template_files) {
> > + my $filepath = "$TEMPLATE_OVERRIDE_DIR/$template";
> > +
> > + open(my $fh, '>', $filepath) or die "Could not open file
> > '$filepath': $!\n";
>
> since this does create the file, we should probably open the file only
> after we're sure the template we try to override exists. otherwise we'll
> end up with an empty override-file for a non-existing template
Makes sense.
> > +
> > + my $template_content = PVE::RS::SDN::get_template($template);
> > + if (!defined($template_content)) {
> > + die "Template '$template' not found\n";
> > + }
> > + print $fh $template_content;
> > + close $fh;
> > +
> > + print "Created override file: $filepath\n";
> > + }
> > + return undef;
> > + },
> > +});
> > +
> > +__PACKAGE__->register_method({
> > + name => 'show',
> > + path => 'show',
> > + method => 'GET',
> > + description => "Show FRR template.",
>
> should we maybe show the override, if one exists, cause that's what will
> be used? maybe even with small indicator that not the packaged version
> is in use
This is the only way to get the provisioned templates for the user
(without searching through the code), so I'd like to keep this is as it
is. This is also used in the postinst script to make a 3-way-diff
between the override/packaged and newly-packaged.
But I see your concern. Maybe we should create a new command for this?
Thanks for the review!
> > + parameters => {
> > + properties => {
> > + "template-name" => {
> > + description => "Name of the FRR template (e.g.
> > 'bgpd.jinja').",
> > + type => 'string',
> > + },
> > + },
> > + },
> > + returns => { type => 'null' },
> > + code => sub {
> > + my ($param) = @_;
> > +
> > + my $template_name = $param->{"template-name"};
> > + my $template = PVE::RS::SDN::get_template($template_name);
> > + if (defined($template)) {
> > + print($template);
> > + } else {
> > + die("Template '$template_name' not found\n");
> > + }
> > + return undef;
> > + },
> > +});
> > +
> > +sub write_to_template_file {
> > + my ($filename, $content) = @_;
> > + if ($filename =~ m/^([\w_-]+\.jinja)$/) {
> > + my $safe_filename = $1;
> > +
> > + # create backup
> > + my $filepath = "$TEMPLATE_OVERRIDE_DIR/$safe_filename";
> > + my $backup_path = "$filepath-bak";
> > + if (-f $filepath) {
> > + copy($filepath, $backup_path) or die "Could not create backup:
> > $!\n";
> > + }
> > +
> > + open(my $fh, '>', $filepath) or die "Could not open file
> > '$filepath': $!\n";
> > + print $fh $content;
> > + close $fh;
> > + }
> > + return undef;
> > +}
> > +
> > [..]