X-Git-Url: https://git.proxmox.com/?p=pve-network.git;a=blobdiff_plain;f=PVE%2FNetwork%2FSDN%2FSubnetPlugin.pm;h=15b370fb91ce80e9cab368aad42c75dbf314eea7;hp=8900681bd17b47f6d79ffb77bbd6eadedc45067b;hb=9c24bcc5eb191d6f59541dc714d4c8df672f0925;hpb=c33dd81818c4b04119b0dc43cbbf8548c58df047 diff --git a/PVE/Network/SDN/SubnetPlugin.pm b/PVE/Network/SDN/SubnetPlugin.pm index 8900681..15b370f 100644 --- a/PVE/Network/SDN/SubnetPlugin.pm +++ b/PVE/Network/SDN/SubnetPlugin.pm @@ -3,11 +3,16 @@ package PVE::Network::SDN::SubnetPlugin; use strict; use warnings; +use Net::IP; +use Net::Subnet qw(subnet_matcher); + use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file); -use base qw(PVE::SectionConfig); -use PVE::JSONSchema qw(get_standard_option); use PVE::Exception qw(raise raise_param_exc); -use Net::Subnet qw(subnet_matcher); +use PVE::JSONSchema qw(get_standard_option); +use PVE::Network::SDN::Ipams; +use PVE::Network::SDN::Vnets; + +use base qw(PVE::SectionConfig); PVE::Cluster::cfs_register_file('sdn/subnets.cfg', sub { __PACKAGE__->parse_config(@_); }, @@ -23,7 +28,13 @@ PVE::JSONSchema::register_format('pve-sdn-subnet-id', \&parse_sdn_subnet_id); sub parse_sdn_subnet_id { my ($id, $noerr) = @_; - my $cidr = $id =~ s/-/\//r; + my $cidr = ""; + if($id =~ /\//) { + $cidr = $id; + } else { + my ($zone, $ip, $mask) = split(/-/, $id); + $cidr = "$ip/$mask"; + } if (!(PVE::JSONSchema::pve_verify_cidrv4($cidr, 1) || PVE::JSONSchema::pve_verify_cidrv6($cidr, 1))) @@ -52,6 +63,10 @@ sub private { sub properties { return { + vnet => { + type => 'string', + description => "associated vnet", + }, gateway => { type => 'string', format => 'ip', description => "Subnet Gateway: Will be assign on vnet for layer3 zones", @@ -60,56 +75,92 @@ sub properties { type => 'boolean', description => "enable masquerade for this subnet if pve-firewall", }, - #cloudinit, dhcp options - routes => { - type => 'string', - description => "static routes [network=:gateway=,network=:gateway=,... ]", - }, - #cloudinit, dhcp options - nameservers => { - type => 'string', format => 'address-list', - description => " dns nameserver", - }, - #cloudinit, dhcp options - searchdomain => { - type => 'string', - }, - dhcp => { - type => 'boolean', - description => "enable dhcp for this subnet", - }, - dns_driver => { - type => 'string', - description => "Develop some dns registrations plugins (powerdns,...)", - }, - ipam_driver => { - type => 'string', - description => "use a specific ipam", +# #cloudinit, dhcp options +# routes => { +# type => 'string', +# description => "static routes [network=:gateway=,network=:gateway=,... ]", +# }, + dnszoneprefix => { + type => 'string', format => 'dns-name', + description => "dns domain zone prefix ex: 'adm' -> .adm.mydomain.com", }, }; } sub options { return { + vnet => { optional => 0 }, gateway => { optional => 1 }, - routes => { optional => 1 }, - nameservers => { optional => 1 }, - searchdomain => { optional => 1 }, +# routes => { optional => 1 }, snat => { optional => 1 }, - dhcp => { optional => 1 }, - dns_driver => { optional => 1 }, - ipam_driver => { optional => 1 }, + dnszoneprefix => { optional => 1 }, }; } sub on_update_hook { - my ($class, $subnetid, $subnet_cfg) = @_; + my ($class, $zone, $subnetid, $subnet, $old_subnet) = @_; + + my $cidr = $subnet->{cidr}; + my $mask = $subnet->{mask}; + + my $subnet_matcher = subnet_matcher($cidr); + + my $vnetid = $subnet->{vnet}; + my $gateway = $subnet->{gateway}; + my $ipam = $zone->{ipam}; + my $dns = $zone->{dns}; + my $dnszone = $zone->{dnszone}; + my $reversedns = $zone->{reversedns}; + + my $old_gateway = $old_subnet->{gateway} if $old_subnet; + my $mac = undef; + + if($vnetid) { + my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid); + raise_param_exc({ vnet => "$vnetid don't exist"}) if !$vnet; + raise_param_exc({ vnet => "you can't add a subnet on a vlanaware vnet"}) if $vnet->{vlanaware}; + $mac = $vnet->{mac}; + } + + my $pointopoint = 1 if Net::IP::ip_is_ipv4($gateway) && $mask == 32; + + #for /32 pointopoint, we allow gateway outside the subnet + raise_param_exc({ gateway => "$gateway is not in subnet $cidr"}) if $gateway && !$subnet_matcher->($gateway) && !$pointopoint; + + + if ($ipam) { + PVE::Network::SDN::Subnets::add_subnet($zone, $subnetid, $subnet); + + #don't register gateway for pointopoint + return if $pointopoint; + + #delete gateway on removal + if (!defined($gateway) && $old_gateway) { + eval { + PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway); + }; + warn if $@; + } + if(!$old_gateway || $gateway && $gateway ne $old_gateway) { + my $hostname = "$vnetid-gw"; + my $description = "gateway"; + PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, $description, 1); + } + + #delete old gateway after update + if($gateway && $old_gateway && $gateway ne $old_gateway) { + eval { + PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $old_subnet, $old_gateway); + }; + warn if $@; + } + } +} - my $subnet = $subnetid =~ s/-/\//r; - my $subnet_matcher = subnet_matcher($subnet); +sub on_delete_hook { + my ($class, $subnetid, $subnet_cfg, $vnet_cfg) = @_; - my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway}; - raise_param_exc({ gateway => "$gateway is not in subnet $subnet"}) if $gateway && !$subnet_matcher->($gateway); + return; } 1;