[pve-devel] [RFC pve-container 1/4] debian: deal with gateways in external subnets

Wolfgang Bumiller w.bumiller at proxmox.com
Fri Oct 16 15:57:10 CEST 2015


---
 src/PVE/LXC/Setup/Debian.pm                        | 74 +++++++++++++++++++++-
 src/test/test-debian-012/config                    |  2 +
 src/test/test-debian-012/etc/debian_version        |  1 +
 src/test/test-debian-012/etc/network/interfaces    |  2 +
 .../test-debian-012/etc/network/interfaces.exp     | 21 ++++++
 5 files changed, 98 insertions(+), 2 deletions(-)
 create mode 100644 src/test/test-debian-012/config
 create mode 100644 src/test/test-debian-012/etc/debian_version
 create mode 100644 src/test/test-debian-012/etc/network/interfaces
 create mode 100644 src/test/test-debian-012/etc/network/interfaces.exp

diff --git a/src/PVE/LXC/Setup/Debian.pm b/src/PVE/LXC/Setup/Debian.pm
index 4b423cc..2db8066 100644
--- a/src/PVE/LXC/Setup/Debian.pm
+++ b/src/PVE/LXC/Setup/Debian.pm
@@ -5,6 +5,7 @@ use warnings;
 use Data::Dumper;
 use PVE::Tools qw($IPV6RE);
 use PVE::LXC;
+use PVE::Network;
 use File::Path;
 
 use PVE::LXC::Setup::Base;
@@ -67,6 +68,49 @@ sub setup_init {
     $self->ct_file_set_contents($filename, $inittab);
 }
 
+sub remove_gateway_scripts {
+    my ($attr) = @_;
+    my $length = scalar(@$attr);
+    for (my $i = 0; $i < $length; ++$i) {
+	my $a = $attr->[$i];
+	if ($a =~ m@^\s*post-up\s+.*route.*add.*default.*(?:gw|via)\s+(\S+)@) {
+	    my $gw = $1;
+	    if ($i > 0 && $attr->[$i-1] =~ m@^\s*post-up\s+.*route.*add.*\Q$1\E@) {
+		--$i;
+		splice @$attr, $i, 2;
+		$length -= 2;
+	    } else {
+		splice @$attr, $i, 1;
+		$length -= 1;
+	    }
+	    --$i;
+	    next;
+	}
+	if ($a =~ m@^\s*pre-down\s+.*route.*del.*default.*(?:gw|via)\s+(\S+)@) {
+	    my $gw = $1;
+	    if ($attr->[$i+1] =~ m@^\s*pre-down\s+.*route.*del.*\Q$1\E@) {
+		splice @$attr, $i, 2;
+		$length -= 2;
+	    } else {
+		splice @$attr, $i, 1;
+		$length -= 1;
+	    }
+	    --$i;
+	    next;
+	}
+    }
+}
+
+sub make_gateway_scripts {
+    my ($ifname, $gw) = @_;
+    return <<"SCRIPTS";
+\tpost-up ip route add $gw dev $ifname
+\tpost-up ip route add default via $gw
+\tpre-down ip route del default via $gw
+\tpre-down ip route del $gw dev $ifname
+SCRIPTS
+}
+
 sub setup_network {
     my ($self, $conf) = @_;
 
@@ -77,6 +121,7 @@ sub setup_network {
 	my $d = PVE::LXC::parse_lxc_network($conf->{$k});
 	if ($d->{name}) {
 	    my $net = {};
+	    my $cidr;
 	    if (defined($d->{ip})) {
 		if ($d->{ip} =~ /^(?:dhcp|manual)$/) {
 		    $net->{address} = $d->{ip};
@@ -84,11 +129,17 @@ sub setup_network {
 		    my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip});
 		    $net->{address} = $ipinfo->{address};
 		    $net->{netmask} = $ipinfo->{netmask};
+		    $cidr = $d->{ip};
 		}
 	    }
 	    if (defined($d->{'gw'})) {
 		$net->{gateway} = $d->{'gw'};
+		if (defined($cidr) && !PVE::Network::is_ip_in_cidr($d->{gw}, $cidr, 4)) {
+		    # gateway is not reachable, need an extra route
+		    $net->{needsroute} = 1;
+		}
 	    }
+	    $cidr = undef;
 	    if (defined($d->{ip6})) {
 		if ($d->{ip6} =~ /^(?:auto|dhcp|manual)$/) {
 		    $net->{address6} = $d->{ip6};
@@ -97,10 +148,15 @@ sub setup_network {
 		} else {
 		    $net->{address6} = $1;
 		    $net->{netmask6} = $2;
+		    $cidr = $d->{ip6};
 		}
 	    }
 	    if (defined($d->{'gw6'})) {
 		$net->{gateway6} = $d->{'gw6'};
+		if (defined($cidr) && !PVE::Network::is_ip_in_cidr($d->{gw6}, $cidr, 6)) {
+		    # gateway is not reachable, need an extra route
+		    $net->{needsroute6} = 1;
+		}
 	    }
 	    $networks->{$d->{name}} = $net if keys %$net;
 	}
@@ -137,7 +193,14 @@ sub setup_network {
 		$interfaces .= "iface $ifname inet static\n";
 		$interfaces .= "\taddress $net->{address}\n" if defined($net->{address});
 		$interfaces .= "\tnetmask $net->{netmask}\n" if defined($net->{netmask});
-		$interfaces .= "\tgateway $net->{gateway}\n" if defined($net->{gateway});
+		if (defined(my $gw = $net->{gateway})) {
+		    remove_gateway_scripts($section->{attr});
+		    if ($net->{needsroute}) {
+			$interfaces .= make_gateway_scripts($ifname, $gw);
+		    } else {
+			$interfaces .= "\tgateway $gw\n";
+		    }
+		}
 		foreach my $attr (@{$section->{attr}}) {
 		    $interfaces .= "\t$attr\n";
 		}
@@ -154,7 +217,14 @@ sub setup_network {
 		$interfaces .= "iface $ifname inet6 static\n";
 		$interfaces .= "\taddress $net->{address6}\n" if defined($net->{address6});
 		$interfaces .= "\tnetmask $net->{netmask6}\n" if defined($net->{netmask6});
-		$interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6});
+		if (defined(my $gw = $net->{gateway6})) {
+		    remove_gateway_scripts($section->{attr});
+		    if ($net->{needsroute6}) {
+			$interfaces .= make_gateway_scripts($ifname, $gw);
+		    } else {
+			$interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6});
+		    }
+		}
 		foreach my $attr (@{$section->{attr}}) {
 		    $interfaces .= "\t$attr\n";
 		}
diff --git a/src/test/test-debian-012/config b/src/test/test-debian-012/config
new file mode 100644
index 0000000..1aeb8c8
--- /dev/null
+++ b/src/test/test-debian-012/config
@@ -0,0 +1,2 @@
+net0: name=eth0,hwaddr=11:22:33:44:55:66,bridge=vmbr0,ip=10.0.0.100/32,gw=11.0.0.1
+net1: name=eth1,hwaddr=22:33:44:55:66:77,bridge=vmbr0,ip6=fc00::1/64,gw6=fc00:1::ff
diff --git a/src/test/test-debian-012/etc/debian_version b/src/test/test-debian-012/etc/debian_version
new file mode 100644
index 0000000..cc40bca
--- /dev/null
+++ b/src/test/test-debian-012/etc/debian_version
@@ -0,0 +1 @@
+8.0
diff --git a/src/test/test-debian-012/etc/network/interfaces b/src/test/test-debian-012/etc/network/interfaces
new file mode 100644
index 0000000..f1bd92e
--- /dev/null
+++ b/src/test/test-debian-012/etc/network/interfaces
@@ -0,0 +1,2 @@
+auto lo
+iface lo inet loopback
diff --git a/src/test/test-debian-012/etc/network/interfaces.exp b/src/test/test-debian-012/etc/network/interfaces.exp
new file mode 100644
index 0000000..4606578
--- /dev/null
+++ b/src/test/test-debian-012/etc/network/interfaces.exp
@@ -0,0 +1,21 @@
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet static
+	address 10.0.0.100
+	netmask 255.255.255.255
+	post-up ip route add 11.0.0.1 dev eth0
+	post-up ip route add default via 11.0.0.1
+	pre-down ip route del default via 11.0.0.1
+	pre-down ip route del 11.0.0.1 dev eth0
+
+auto eth1
+iface eth1 inet6 static
+	address fc00::1
+	netmask 64
+	post-up ip route add fc00:1::ff dev eth1
+	post-up ip route add default via fc00:1::ff
+	pre-down ip route del default via fc00:1::ff
+	pre-down ip route del fc00:1::ff dev eth1
+
-- 
2.1.4





More information about the pve-devel mailing list