[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