]> git.proxmox.com Git - pve-common.git/blobdiff - src/PVE/INotify.pm
/etc/network/interfaces: deal with OVS allow- lines
[pve-common.git] / src / PVE / INotify.pm
index e773cf4d93649b56c5fc93775abf01a151d4ac84..5fce0c8656f7405f48826ef894f56b63d9c72247 100644 (file)
@@ -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};
@@ -1197,7 +1243,19 @@ 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 = {};
 
@@ -1266,8 +1324,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",