X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FINotify.pm;h=136dd90f36d22abf37bd596fd385c592346b9b6c;hp=e773cf4d93649b56c5fc93775abf01a151d4ac84;hb=21d32c95cdb63fa96091f2efe735a9c8a1a3e44e;hpb=48ab17b3eec31fdb89b8523f7ca2577fa87298c5 diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm index e773cf4..136dd90 100644 --- a/src/PVE/INotify.pm +++ b/src/PVE/INotify.pm @@ -784,6 +784,13 @@ my $extract_ovs_option = sub { # } sub read_etc_network_interfaces { my ($filename, $fh) = @_; + my $proc_net_dev = IO::File->new('/proc/net/dev', 'r'); + my $proc_net_if_inet6 = IO::File->new('/proc/net/if_inet6', 'r'); + return __read_etc_network_interfaces($fh, $proc_net_dev, $proc_net_if_inet6); +} + +sub __read_etc_network_interfaces { + my ($fh, $proc_net_dev, $proc_net_if_inet6) = @_; my $config = {}; my $ifaces = $config->{ifaces} = {}; @@ -791,13 +798,13 @@ sub read_etc_network_interfaces { my $line; - if (my $fd2 = IO::File->new("/proc/net/dev", "r")) { - while (defined ($line = <$fd2>)) { + if ($proc_net_dev) { + while (defined ($line = <$proc_net_dev>)) { if ($line =~ m/^\s*(eth\d+):.*/) { $ifaces->{$1}->{exists} = 1; } } - close($fd2); + close($proc_net_dev); } # we try to keep order inside the file @@ -820,7 +827,7 @@ sub read_etc_network_interfaces { my $f = { method => $3 }; # by family, merged to $d with a $suffix (my $suffix = $family) =~ s/^inet//; - my $d = $ifaces->{$i}; + my $d = $ifaces->{$i} ||= {}; $d->{priority} = $priority++ if !$d->{priority}; push @{$d->{families}}, $family; @@ -976,17 +983,43 @@ sub read_etc_network_interfaces { $d->{method} = 'manual' if !$d->{method}; $d->{method6} = 'manual' if !$d->{method6}; + + $d->{families} ||= ['inet']; } - if (my $fd2 = IO::File->new("/proc/net/if_inet6", "r")) { - while (defined ($line = <$fd2>)) { + if ($proc_net_if_inet6) { + while (defined ($line = <$proc_net_if_inet6>)) { if ($line =~ m/^[a-f0-9]{32}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+(\S+)$/) { $ifaces->{$1}->{active} = 1 if defined($ifaces->{$1}); } } - close ($fd2); + close ($proc_net_if_inet6); } + # OVS bridges create "allow-$BRIDGE $IFACE" lines which we need to remove + # from the {options} hash for them to be removed correctly. + @$options = grep {defined($_)} map { + my ($pri, $line) = @$_; + if ($line =~ /^allow-(\S+)\s+(.*)$/) { + my $bridge = $1; + my @ports = split(/\s+/, $2); + if (defined(my $br = $ifaces->{$bridge})) { + # if this port is part of a bridge, remove it + my %in_ovs_ports = map {$_=>1} split(/\s+/, $br->{ovs_ports}); + @ports = grep { not $in_ovs_ports{$_} } @ports; + } + # create the allow line for the remaining ports, or delete if empty + if (@ports) { + [$pri, "allow-$bridge " . join(' ', @ports)]; + } else { + undef; + } + } else { + # don't modify other lines + $_; + } + } @$options; + return $config; } @@ -1121,8 +1154,14 @@ sub __interface_to_string { return $raw; } + sub write_etc_network_interfaces { my ($filename, $fh, $config) = @_; + my $raw = __write_etc_network_interfaces($config); + PVE::Tools::safe_print($filename, $fh, $raw); +} +sub __write_etc_network_interfaces { + my ($config) = @_; my $ifaces = $config->{ifaces}; my @options = @{$config->{options}}; @@ -1151,7 +1190,14 @@ sub write_etc_network_interfaces { $d->{type} eq 'OVSBond') { my $brname = $used_ports->{$iface}; if (!$brname || !$ifaces->{$brname}) { - delete $ifaces->{$iface}; + if ($iface =~ /^eth/) { + $ifaces->{$iface} = { type => 'eth', + exists => 1, + method => 'manual', + families => ['inet'] }; + } else { + delete $ifaces->{$iface}; + } next; } my $bd = $ifaces->{$brname}; @@ -1170,6 +1216,7 @@ sub write_etc_network_interfaces { my $n = $ifaces->{$p}; die "OVS bridge '$iface' - unable to find port '$p'\n" if !$n; + $n->{autostart} = 0; if ($n->{type} eq 'eth') { $n->{type} = 'OVSPort'; $n->{ovs_bridge} = $iface; @@ -1183,6 +1230,19 @@ sub write_etc_network_interfaces { } } + # Remove autostart from linux bridge ports + foreach my $iface (keys %$ifaces) { + my $d = $ifaces->{$iface}; + if ($d->{type} eq 'bridge' && $d->{bridge_ports}) { + foreach my $p (split (/\s+/, $d->{bridge_ports})) { + my $n = $ifaces->{$p}; + die "bridge '$iface' - unable to find port '$p'\n" + if !$n; + $n->{autostart} = 0; + } + } + } + # check OVS bond ports foreach my $iface (keys %$ifaces) { my $d = $ifaces->{$iface}; @@ -1197,16 +1257,28 @@ sub write_etc_network_interfaces { } } - my $raw = "# network interface settings\n"; + my $raw = <<'NETWORKDOC'; +# network interface settings; autogenerated +# Please do NOT modify this file directly, unless you know what +# you're doing. +# +# If you want to manage part of the network configuration manually, +# please utilize the 'source' or 'source-directory' directives to do +# so. +# PVE will preserve these directives, but will NOT its network +# configuration from sourced files, so do not attempt to move any of +# the PVE managed interfaces into external files! + +NETWORKDOC my $printed = {}; my $if_type_hash = { unknown => 0, - loopback => 10, - eth => 20, - bond => 30, - bridge => 40, + loopback => 100000, + eth => 200000, + bond => 300000, + bridge => 400000, }; my $lookup_type_prio = sub { @@ -1238,24 +1310,21 @@ sub write_etc_network_interfaces { my $p1 = &$lookup_type_prio($a); my $p2 = &$lookup_type_prio($b); - return $p1 <=> $p2 if $p1 != $p2; - - $p1 = $ref1->{priority} || 100000; - $p2 = $ref2->{priority} || 100000; + $p1 += $ref1->{priority} // 50000; + $p2 += $ref2->{priority} // 50000; return $p1 <=> $p2 if $p1 != $p2; return $a cmp $b; - } keys %$ifaces) { - - my $d = $ifaces->{$iface}; - + } keys %$ifaces) { next if $printed->{$iface}; - if (@options && $options[0]->[0] < $d->{priority}) { + my $d = $ifaces->{$iface}; + my $pri = $d->{priority} // 0; + if (@options && $options[0]->[0] < $pri) { do { $raw .= (shift @options)->[1] . "\n"; - } while (@options && $options[0]->[0] < $d->{priority}); + } while (@options && $options[0]->[0] < $pri); $raw .= "\n"; } @@ -1266,8 +1335,7 @@ sub write_etc_network_interfaces { } $raw .= $_->[1] . "\n" foreach @options; - - PVE::Tools::safe_print($filename, $fh, $raw); + return $raw; } register_file('interfaces', "/etc/network/interfaces",