use strict;
use warnings;
use PVE::Network::SDN::Zones::Plugin;
+use PVE::Exception qw(raise raise_param_exc);
+use PVE::Cluster;
+use PVE::Tools;
use base('PVE::Network::SDN::Zones::Plugin');
return 'simple';
}
-sub options {
+sub properties {
+ return {
+ dns => {
+ type => 'string',
+ description => "dns api server",
+ },
+ reversedns => {
+ type => 'string',
+ description => "reverse dns api server",
+ },
+ dnszone => {
+ type => 'string', format => 'dns-name',
+ description => "dns domain zone ex: mydomain.com",
+ }
+ };
+}
+sub options {
return {
- nodes => { optional => 1},
- mtu => { optional => 1 }
+ nodes => { optional => 1},
+ mtu => { optional => 1 },
+ dns => { optional => 1 },
+ reversedns => { optional => 1 },
+ dnszone => { optional => 1 },
+ ipam => { optional => 1 },
};
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
+
+ return $config if$config->{$vnetid}; # nothing to do
- my $ipv4 = $vnet->{ipv4};
- my $ipv6 = $vnet->{ipv6};
my $mac = $vnet->{mac};
my $alias = $vnet->{alias};
my $mtu = $plugin_config->{mtu} if $plugin_config->{mtu};
- #vnet bridge
+ # vnet bridge
my @iface_config = ();
- push @iface_config, "address $ipv4" if $ipv4;
- push @iface_config, "address $ipv6" if $ipv6;
+
+ my $address = {};
+ my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
+
+ my $ipv4 = undef;
+ my $ipv6 = undef;
+ my $enable_forward_v4 = undef;
+ my $enable_forward_v6 = undef;
+
+ foreach my $subnetid (sort keys %{$subnets}) {
+ my $subnet = $subnets->{$subnetid};
+ my $cidr = $subnet->{cidr};
+ my $mask = $subnet->{mask};
+
+ my $gateway = $subnet->{gateway};
+ if ($gateway) {
+ push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
+ $address->{$gateway} = 1;
+ }
+
+ my $iptables = undef;
+ my $checkrouteip = undef;
+ my $ipversion = Net::IP::ip_is_ipv6($gateway) ? 6 : 4;
+
+ if ( $ipversion == 6) {
+ $ipv6 = 1;
+ $iptables = "ip6tables";
+ $checkrouteip = '2001:4860:4860::8888';
+ $enable_forward_v6 = 1 if $gateway;
+ } else {
+ $ipv4 = 1;
+ $iptables = "iptables";
+ $checkrouteip = '8.8.8.8';
+ $enable_forward_v4 = 1 if $gateway;
+ }
+
+ #add route for /32 pointtopoint
+ push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32 && $ipversion == 4;
+ if ($subnet->{snat}) {
+ #find outgoing interface
+ my ($outip, $outiface) = PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
+ if ($outip && $outiface) {
+ #use snat, faster than masquerade
+ push @iface_config, "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ push @iface_config, "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+ #add conntrack zone once on outgoing interface
+ push @iface_config, "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
+ push @iface_config, "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
+ }
+ }
+ }
+
push @iface_config, "hwaddress $mac" if $mac;
push @iface_config, "bridge_ports none";
push @iface_config, "bridge_stp off";
push @iface_config, "bridge_fd 0";
- if($vnet->{vlanaware}) {
+ if ($vnet->{vlanaware}) {
push @iface_config, "bridge-vlan-aware yes";
push @iface_config, "bridge-vids 2-4094";
}
push @iface_config, "mtu $mtu" if $mtu;
push @iface_config, "alias $alias" if $alias;
- push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+ push @iface_config, "ip-forward on" if $enable_forward_v4;
+ push @iface_config, "ip6-forward on" if $enable_forward_v6;
+
+ push @{$config->{$vnetid}}, @iface_config;
return $config;
}
sub status {
my ($class, $plugin_config, $zone, $vnetid, $vnet, $status) = @_;
- my $err_msg = [];
-
# ifaces to check
- my $ifaces = [ $vnetid];
-
+ my $ifaces = [ $vnetid ];
+ my $err_msg = [];
foreach my $iface (@{$ifaces}) {
if (!$status->{$iface}->{status}) {
push @$err_msg, "missing $iface";
- } elsif ($status->{$iface}->{status} ne 'pass') {
+ } elsif ($status->{$iface}->{status} ne 'pass') {
push @$err_msg, "error iface $iface";
}
}
return $err_msg;
}
+
+sub vnet_update_hook {
+ my ($class, $vnet_cfg, $vnetid, $zone_cfg) = @_;
+
+ my $vnet = $vnet_cfg->{ids}->{$vnetid};
+ my $tag = $vnet->{tag};
+
+ raise_param_exc({ tag => "vlan tag is not allowed on simple zone"}) if defined($tag);
+
+ if (!defined($vnet->{mac})) {
+ my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
+ $vnet->{mac} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
+ }
+}
+
1;