diff --git a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm index af9be25..a691323 100644 --- a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm @@ -96,6 +96,60 @@ sub add_subnet { } } +sub update_subnet { + my ($class, $plugin_config, $subnetid, $subnet, $old_subnet, $noerr) = @_; + + # old subnet in SubnetPlugin hook has already parsed dhcp-ranges + # new subnet doesn't + my $old_dhcp_ranges = $old_subnet->{'dhcp-range'}; + my $new_dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet); + + my $hash_range = sub { + my ($dhcp_range) = @_; + "$dhcp_range->{'start-address'} - $dhcp_range->{'end-address'}" + }; + + my $old_lookup = {}; + for my $dhcp_range (@$old_dhcp_ranges) { + my $hash = $hash_range->($dhcp_range); + $old_lookup->{$hash} = undef; + } + + my $new_lookup = {}; + for my $dhcp_range (@$new_dhcp_ranges) { + my $hash = $hash_range->($dhcp_range); + $new_lookup->{$hash} = undef; + } + + my $to_delete_ids = (); + + # delete first so we don't get errors with overlapping ranges + for my $dhcp_range (@$old_dhcp_ranges) { + my $hash = $hash_range->($dhcp_range); + + if (exists($new_lookup->{$hash})) { + next; + } + + my $internalid = get_iprange_id($plugin_config, $dhcp_range, $noerr); + + # definedness check, because ID could be 0 + if (!defined($internalid)) { + warn "could not find id for ip range $dhcp_range->{'start-address'}:$dhcp_range->{'end-address'}"; + next; + } + + del_dhcp_range($plugin_config, $internalid, $noerr); + } + + for my $dhcp_range (@$new_dhcp_ranges) { + my $hash = $hash_range->($dhcp_range); + + add_dhcp_range($plugin_config, $dhcp_range, $noerr) + if !exists($old_lookup->{$hash}); + } +} + sub del_subnet { my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_; diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm index 742f1b1..59ad4ea 100644 --- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm @@ -82,6 +82,11 @@ sub add_subnet { die "$@" if $@; } +sub update_subnet { + my ($class, $plugin_config, $subnetid, $subnet, $old_subnet, $noerr) = @_; + # we don't need to do anything on update +} + sub only_gateway_remains { my ($ips) = @_; diff --git a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm index df5048d..8ee430a 100644 --- a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm @@ -67,6 +67,11 @@ sub add_subnet { } } +sub update_subnet { + my ($class, $plugin_config, $subnetid, $subnet, $old_subnet, $noerr) = @_; + # we don't need to do anything on update +} + sub del_subnet { my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_; diff --git a/src/PVE/Network/SDN/Ipams/Plugin.pm b/src/PVE/Network/SDN/Ipams/Plugin.pm index ab4cae8..6190c24 100644 --- a/src/PVE/Network/SDN/Ipams/Plugin.pm +++ b/src/PVE/Network/SDN/Ipams/Plugin.pm @@ -75,6 +75,12 @@ sub add_subnet { die "please implement inside plugin"; } +sub update_subnet { + my ($class, $plugin_config, $subnetid, $subnet, $old_subnet, $noerr) = @_; + + die "please implement inside plugin"; +} + sub del_subnet { my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_; diff --git a/src/PVE/Network/SDN/SubnetPlugin.pm b/src/PVE/Network/SDN/SubnetPlugin.pm index 049f7e1..e73d97a 100644 --- a/src/PVE/Network/SDN/SubnetPlugin.pm +++ b/src/PVE/Network/SDN/SubnetPlugin.pm @@ -186,7 +186,11 @@ sub on_update_hook { validate_dhcp_ranges($subnet); if ($ipam) { - PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet); + if ($old_subnet) { + PVE::Network::SDN::Subnets::update_subnet($zone, $subnetid, $subnet, $old_subnet); + } else { + PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet); + } #don't register gateway for pointopoint return if $pointopoint; diff --git a/src/PVE/Network/SDN/Subnets.pm b/src/PVE/Network/SDN/Subnets.pm index e2c8c9c..18847c2 100644 --- a/src/PVE/Network/SDN/Subnets.pm +++ b/src/PVE/Network/SDN/Subnets.pm @@ -194,6 +194,18 @@ sub add_subnet { $plugin->add_subnet($plugin_config, $subnetid, $subnet); } +sub update_subnet { + my ($zone, $subnetid, $subnet, $old_subnet) = @_; + + my $ipam = $zone->{ipam}; + return if !$ipam; + + my $ipam_cfg = PVE::Network::SDN::Ipams::config(); + my $plugin_config = $ipam_cfg->{ids}->{$ipam}; + my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type}); + $plugin->update_subnet($plugin_config, $subnetid, $subnet, $old_subnet); +} + sub del_subnet { my ($zone, $subnetid, $subnet) = @_;