This is the same code than lxc, it can be move to a common module later Signed-off-by: Alexandre Derumier <aderum...@odiso.com> --- PVE/QemuServer/Ipam.pm | 158 ++++++++++++++++++++++++++++++++++++++++ PVE/QemuServer/Makefile | 1 + 2 files changed, 159 insertions(+) create mode 100644 PVE/QemuServer/Ipam.pm
diff --git a/PVE/QemuServer/Ipam.pm b/PVE/QemuServer/Ipam.pm new file mode 100644 index 0000000..37b1595 --- /dev/null +++ b/PVE/QemuServer/Ipam.pm @@ -0,0 +1,158 @@ +package PVE::QemuServer::Ipam; + +use strict; +use warnings; + +my $have_sdn; +eval { + require PVE::Network::SDN::Zones; + $have_sdn = 1; +}; + +sub is_static_ip { + my ($ip) = @_; + + return 1 if $ip !~ m/(dhcp|manual|auto)$/; +} + + +sub ip_has_changed { + my ($oldip, $ip) = @_; + + return 1 if !$oldip && $ip; + return 1 if !$ip && $oldip; + return 1 if $ip && $oldip && $ip ne $oldip; +} + +my $add_net_ip = sub { + my ($version, $net, $oldnet, $hostname, $oldhostname, $description) = @_; + + my $oldbridge = $oldnet->{bridge}; + my $bridge = $net->{bridge}; + my $mac = $net->{hwaddr}; + my $ipfield = $version == 4 ? "ip" : "ip6"; + my $ip = $net->{$ipfield}; + my $oldip = $oldnet->{$ipfield}; + my $subnets = PVE::Network::SDN::Vnets::get_subnets($bridge); + return if !keys %{$subnets}; + + eval { + if (!$ip) { + my $next_free_ip = PVE::Network::SDN::Vnets::get_next_free_cidr($bridge, $hostname, $mac, $description, $version); + $net->{$ipfield} = $next_free_ip if $next_free_ip; + } elsif (is_static_ip($ip)) { + if (!ip_has_changed($oldip, $ip)) { + #update ip attributes if no ip address change + PVE::Network::SDN::Vnets::update_cidr($bridge, $ip, $hostname, $oldhostname, $mac, $description); + } else { + PVE::Network::SDN::Vnets::add_cidr($bridge, $ip, $hostname, $mac, $description); + } + } + }; + if ($@) { + die $@; + } +}; + + +my $del_net_ip = sub { + my ($version, $oldnet, $net, $hostname, $description) = @_; + + my $oldbridge = $oldnet->{bridge}; + my $bridge = $net->{bridge}; + my $ip = $version == 4 ? $net->{ip} : $net->{ip6}; + my $oldip = $version == 4 ? $oldnet->{ip} : $oldnet->{ip6}; + + return if !$oldip || !is_static_ip($oldip); + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($oldbridge); + return if !keys %{$subnets}; + + eval { + PVE::Network::SDN::Vnets::del_cidr($oldbridge, $oldip, $hostname, $description) if !$bridge || $bridge ne $oldbridge || !$ip || $ip ne $oldip; + }; + warn $@ if $@; +}; + + +my $update_net_gateway = sub { + my ($version, $net) = @_; + + my $bridge = $net->{bridge}; + my $netip = $version == 4 ? $net->{ip} : $net->{ip6}; + my $gwfield = $version == 4 ? "gw" : "gw6"; + + return if (!$netip || !is_static_ip($netip)); + + my $subnets = PVE::Network::SDN::Vnets::get_subnets($bridge); + return if !keys %{$subnets}; + + #update gateway + my ($ip, $mask) = split(/\//, $netip); + my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets); + my $gw = $subnet->{gateway} if $subnet->{gateway}; + $net->{$gwfield} = $gw if $gw; + +}; + +sub destroy_net_ip { + my ($conf) = @_; + + return if !$have_sdn; + + foreach my $opt (keys %$conf) { + next if $opt !~ m/^net(\d+)$/; + my $netid = $1; + my $oldnet = PVE::LXC::Config->parse_lxc_network($conf->{$opt}); + my $hostname = $conf->{hostname}; + my $description = ''; + delete_net_ip($hostname, $oldnet, undef, $description); + } +} + +sub update_net_ip { + my ($net, $oldnet, $hostname, $oldhostname, $description) = @_; + + return if !$have_sdn; + + eval { + &$add_net_ip(4, $net, $oldnet, $hostname, $oldhostname, $description); + }; + if ($@) { + $net->{ip} = $oldnet->{ip}; + die "can't change ip4: $@\n"; + } + + eval { + &$add_net_ip(6, $net, $oldnet, $hostname, $oldhostname, $description); + }; + if ($@) { + my $err = $@; + #if error, delete previously added ipv4 + eval { + PVE::Network::SDN::Vnets::del_cidr($net->{bridge}, $net->{ip}, $hostname, $description) if ip_has_changed($oldnet->{ip}, $net->{ip}); + }; + $net->{ip6} = $oldnet->{ip6}; + $net->{ip} = $oldnet->{ip}; + + die "error change ipv6: $err\n"; + } + + delete_net_ip($oldhostname, $oldnet, $net, $description); + + &$update_net_gateway(4, $net); + &$update_net_gateway(6, $net); +} + + + +sub delete_net_ip { + my ($hostname, $oldnet, $net, $description) = @_; + + return if !$have_sdn; + + &$del_net_ip(4, $oldnet, $net, $hostname, $description); + &$del_net_ip(6, $oldnet, $net, $hostname, $description); +} + +1; \ No newline at end of file diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile index e4ed184..0292383 100644 --- a/PVE/QemuServer/Makefile +++ b/PVE/QemuServer/Makefile @@ -11,6 +11,7 @@ SOURCES=PCI.pm \ CPUConfig.pm \ CGroup.pm \ Drive.pm \ + Ipam.pm \ .PHONY: install install: ${SOURCES} -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel