[pve-devel] [pve-common 3/3] allow multiple address by interfaces

Alexandre Derumier aderumier at odiso.com
Thu Feb 20 12:55:20 CET 2020


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/INotify.pm                            | 64 +++++++++++++------
 test/etc_network_interfaces/t.bridge-v4-v6.pl |  4 +-
 .../t.create_network.pl                       |  6 +-
 .../t.list-interfaces.pl                      | 47 +++++++++-----
 .../t.ovs_bridge_allow.pl                     |  2 +-
 .../etc_network_interfaces/t.unknown_order.pl |  2 +-
 .../t.update_network.pl                       |  8 +--
 7 files changed, 88 insertions(+), 45 deletions(-)

diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm
index e9dc485..2bb5272 100644
--- a/src/PVE/INotify.pm
+++ b/src/PVE/INotify.pm
@@ -966,7 +966,9 @@ sub __read_etc_network_interfaces {
 			'vxlan-physdev' => 1,
 			'vxlan-local-tunnelip' => 1 };
 
-		    if (($id eq 'address') || ($id eq 'netmask') || ($id eq 'broadcast') || ($id eq 'gateway')) {
+		    if ($id eq 'address') {
+			push @{$f->{$id}}, $value;
+		    } elsif (($id eq 'netmask') || ($id eq 'broadcast') || ($id eq 'gateway')) {
 			$f->{$id} = $value;
 		    } elsif ($simple_options->{$id}) {
 			$d->{$id} = $value;
@@ -1104,23 +1106,29 @@ sub __read_etc_network_interfaces {
 	    }
 	}
 
-	# map address and netmask to cidr
-	if ($d->{address}) {
-	    if ($d->{netmask} && $d->{netmask} =~ m/^\d+$/) { # e.g. netmask 20
-		$d->{address} = $d->{address} . "/" . $d->{netmask};
-	    } elsif ($d->{netmask} &&
-		     (my $cidr = PVE::JSONSchema::get_netmask_bits($d->{netmask}))) { # e.g. netmask 255.255.255.0
-		$d->{address} = $d->{address} . "/" . $cidr;
+	my $addresses = $d->{address};
+        foreach my $address (@{$addresses}) {
+	    # map address and netmask to cidr
+	    if ($address) {
+		if ($d->{netmask} && $d->{netmask} =~ m/^\d+$/) { # e.g. netmask 20
+		    $address = $address . "/" . $d->{netmask};
+		} elsif ($d->{netmask} &&
+			(my $cidr = PVE::JSONSchema::get_netmask_bits($d->{netmask}))) { # e.g. netmask 255.255.255.0
+		    $address = $address . "/" . $cidr;
+		}
+		#for api compatibility, first address only
+		$d->{cidr} = $address if !$d->{cidr};
 	    }
-           #for api compatibility
-           $d->{cidr} = $d->{address} 
-	}
+        }
 
-	# map address6 and netmask6 to cidr6
-	if ($d->{address6}) {
-	    $d->{address6} .= "/" . $d->{netmask6} if $d->{address6} !~ m!^(.*)/(\d+)$! && $d->{netmask6};
-            #for api compatibility
-	    $d->{cidr6} = $d->{address6} 
+	my $addresses6 = $d->{address6};
+        foreach my $address6 (@{$addresses6}) {
+	    # map address6 and netmask6 to cidr6
+	    if ($address6) {
+		$address6 .= "/" . $d->{netmask6} if $address6 !~ m!^(.*)/(\d+)$! && $d->{netmask6};
+		#for api compatibility, first address only
+		$d->{cidr6} = $address6 if !$d->{cidr6};
+	    }
 	}
 
 	$d->{method} = 'manual' if !$d->{method};
@@ -1168,7 +1176,12 @@ sub __interface_to_string {
     my $raw = '';
 
     $raw .= "iface $iface $family " . $d->{"method$suffix"} . "\n";
-    $raw .= "\taddress " . $d->{"address$suffix"} . "\n" if $d->{"address$suffix"};
+
+    my $addresses = $d->{"address$suffix"};
+    foreach my $address (@{$addresses}) {
+	$raw .= "\taddress " . $address . "\n";
+    }
+
     $raw .= "\tgateway " . $d->{"gateway$suffix"} . "\n" if $d->{"gateway$suffix"};
 
     my $done = { type => 1, priority => 1, method => 1, active => 1, exists => 1,
@@ -1557,9 +1570,20 @@ sub __write_etc_network_interfaces {
 		}
 		my $n = $ifaces_copy->{$p};
 		die "bridge '$iface' - unable to find bridge port '$p'\n" if !$n;
-		die "iface $p - ip address can't be set on interface if bridged in $iface\n"
-		    if ($n->{method} && $n->{method} eq 'static' && $n->{address} ne '0.0.0.0') ||
-		       ($n->{method6} && $n->{method6} eq 'static' && $n->{address} ne '::');
+		if ($n->{method} && $n->{method} eq 'static') {
+		    my $addresses = $d->{address};
+		    foreach my $address (@{$addresses}) {
+			die "iface $p - ip address can't be set on interface if bridged in $iface\n" if $address ne '0.0.0.0';
+		    }
+                }
+
+		if ($n->{method6} && $n->{method6} eq 'static') {
+		    my $addresses = $d->{address6};
+		    foreach my $address (@{$addresses}) {
+			die "iface $p - ip address can't be set on interface if bridged in $iface\n" if $address ne '::';
+		    }
+                }
+
 		&$check_mtu($ifaces_copy, $p, $iface);
 		$bridgeports->{$p} = $iface;
 	    }
diff --git a/test/etc_network_interfaces/t.bridge-v4-v6.pl b/test/etc_network_interfaces/t.bridge-v4-v6.pl
index 07c1c03..8693df8 100644
--- a/test/etc_network_interfaces/t.bridge-v4-v6.pl
+++ b/test/etc_network_interfaces/t.bridge-v4-v6.pl
@@ -19,7 +19,7 @@ EOF
 # add an ip and disable previously enabled autostart
 update_iface('vmbr0',
     [ { family => 'inet',
-	address => $ip,
+	address => [$ip],
 	gateway => $gw } ],
     autostart => 0);
 
@@ -36,7 +36,7 @@ save('with-ipv4', w());
 
 update_iface('vmbr0',
     [ { family => 'inet6',
-	address => $ip6,
+	address => [$ip6],
 	gateway => $gw6 } ]);
 
 expect load('with-ipv4') . <<"EOF";
diff --git a/test/etc_network_interfaces/t.create_network.pl b/test/etc_network_interfaces/t.create_network.pl
index 9bb26bd..e3a17df 100644
--- a/test/etc_network_interfaces/t.create_network.pl
+++ b/test/etc_network_interfaces/t.create_network.pl
@@ -14,6 +14,7 @@ r(load('brbase'));
 #
 
 my $ip = '192.168.0.2/24';
+my $ip2 = '192.168.1.2/24';
 my $gw = '192.168.0.1';
 my $svcnodeip = '239.192.105.237';
 my $physdev = 'eth0';
@@ -43,7 +44,7 @@ chomp $vmbr0_part;
 $config->{ifaces}->{eth1} = {
     type => 'eth',
     method => 'static',
-    address => $ip,
+    address => [$ip, $ip2],
     gateway => $gw,
     families => ['inet'],
     autostart => 1
@@ -53,6 +54,7 @@ my $eth1_part = <<"PART";
 auto eth1
 iface eth1 inet static
 	address $ip
+	address $ip2
 	gateway $gw
 PART
 chomp $eth1_part;
@@ -489,7 +491,7 @@ my $gw = 'fc05::1';
 $config->{ifaces}->{eth1} = {
     type => 'eth',
     method6 => 'static',
-    address6 => $ip,
+    address6 => [$ip],
     netmask6 => $nm,
     gateway6 => $gw,
     families => ['inet6'],
diff --git a/test/etc_network_interfaces/t.list-interfaces.pl b/test/etc_network_interfaces/t.list-interfaces.pl
index 5925c35..d4f5065 100644
--- a/test/etc_network_interfaces/t.list-interfaces.pl
+++ b/test/etc_network_interfaces/t.list-interfaces.pl
@@ -16,10 +16,10 @@ eth100:
 /proc/net/dev
 
 my %wanted = (
-    vmbr0 => { address => '192.168.1.2/24',
+    vmbr0 => { address => ['192.168.1.2/24'],
 	       gateway => '192.168.1.1',
-	       address6 => 'fc05::1:1/112'},
-    vmbr1 => { address => '10.0.0.5/24'}
+	       address6 => ['fc05::1:1/112']},
+    vmbr1 => { address => ['10.0.0.5/24', '10.0.0.6/24']}
 );
 
 save('interfaces', <<"/etc/network/interfaces");
@@ -37,23 +37,24 @@ iface eth100 inet manual
 
 auto vmbr0
 iface vmbr0 inet static
-	address  192.168.1.2
-	netmask  24
-	gateway  $wanted{vmbr0}->{gateway}
+	address 192.168.1.2
+	netmask 24
+	gateway $wanted{vmbr0}->{gateway}
 	bridge_ports eth0
 	bridge_stp off
 	bridge_fd 0
 
 iface vmbr0 inet6 static
-	address  fc05::1:1
-	netmask  112
+	address fc05::1:1
+	netmask 112
 
 source-directory before-ovs.d
 
 allow-ovs vmbr1
 iface vmbr1 inet static
-	address  10.0.0.5
-	netmask  255.255.255.0
+	address 10.0.0.5
+	address 10.0.0.6
+	netmask 255.255.255.0
 	ovs_type OVSBridge
 	ovs_ports eth100
 
@@ -73,11 +74,27 @@ defined($ifaces->{"eth$_"})
 # check configuration
 foreach my $ifname (keys %wanted) {
     my $if = $wanted{$ifname};
-    $ifaces->{$ifname}->{$_} eq $if->{$_}
-	or die "unexpected $_ for interface $ifname: \""
-	     . $ifaces->{$ifname}->{$_}
-	     . "\", expected: \"$if->{$_}\"\n"
-	foreach (keys %$if);
+    use Data::Dumper;
+
+    foreach my $key (keys %{$if}) {
+
+	if(ref($if->{$key}) eq 'ARRAY') {
+	    my $res1 = $if->{$key};
+	    my $res2 = $ifaces->{$ifname}->{$key};
+	    foreach my $index (0..$#{$res1}){
+		if ($res1->[$index] != $res2->[$index]) {
+		    die " unexpected keys $res2->[$index] for interface $ifname:". $res2->[$index]." expected: $res1->[$index]";
+		}
+	    }
+        } else {
+
+	    $ifaces->{$ifname}->{$key} eq $if->{$key}
+		or die "unexpected $key for interface $ifname: \""
+		. $ifaces->{$ifname}->{$key}
+		. "\", expected: \"$if->{$key}\"\n"
+       }
+    }
+
 }
 
 my $ck = sub {
diff --git a/test/etc_network_interfaces/t.ovs_bridge_allow.pl b/test/etc_network_interfaces/t.ovs_bridge_allow.pl
index 9479ff5..d5d2505 100644
--- a/test/etc_network_interfaces/t.ovs_bridge_allow.pl
+++ b/test/etc_network_interfaces/t.ovs_bridge_allow.pl
@@ -15,7 +15,7 @@ r('');
 
 new_iface('vmbr0', 'OVSBridge',
     [ { family => 'inet',
-        address => $ip,
+        address => [$ip],
         gateway => $gw } ],
     autostart => 1);
 
diff --git a/test/etc_network_interfaces/t.unknown_order.pl b/test/etc_network_interfaces/t.unknown_order.pl
index cd8f51b..082cf48 100644
--- a/test/etc_network_interfaces/t.unknown_order.pl
+++ b/test/etc_network_interfaces/t.unknown_order.pl
@@ -85,7 +85,7 @@ IFACES
 }
 
 r(wanted(13));
-update_iface('bond1', [ { family => 'inet', address => '10.10.10.11/24' } ]);
+update_iface('bond1', [ { family => 'inet', address => ['10.10.10.11/24'] } ]);
 expect wanted(11);
 
 1;
diff --git a/test/etc_network_interfaces/t.update_network.pl b/test/etc_network_interfaces/t.update_network.pl
index 18bba00..a7cbf37 100644
--- a/test/etc_network_interfaces/t.update_network.pl
+++ b/test/etc_network_interfaces/t.update_network.pl
@@ -15,7 +15,7 @@ r(load('brbase'));
 $config->{ifaces}->{eth1} = {
     type => 'eth',
     method => 'static',
-    address => $ip,
+    address => [$ip],
     gateway => $gw,
     families => ['inet'],
     autostart => 1
@@ -49,7 +49,7 @@ expect load('ipv4');
 
 $config->{ifaces}->{eth1}->{$_->[0]} = $_->[1] foreach (
     [ method6 => 'static' ],
-    [ address6 => $ip6 ],
+    [ address6 => [$ip6] ],
     [ netmask6 => $nm6 ],
     [ gateway6 => $gw6 ],
     [ families => ['inet', 'inet6'] ]
@@ -91,11 +91,11 @@ r(load('ipv4'));
 $config->{ifaces}->{eth1} = {
     type => 'eth',
     method => 'static',
-    address => $ip,
+    address => [$ip],
     netmask => $nm,
     gateway => $gw,
     method6 => 'static',
-    address6 => $ip6,
+    address6 => [$ip6],
     netmask6 => $nm6,
     gateway6 => $gw6,
     families => ['inet', 'inet6'],
-- 
2.20.1




More information about the pve-devel mailing list