X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FINotify.pm;h=0b9ea4adc3e078a47369cd97bc6c271a45f16870;hp=6cec84bc2a2a3e0e4e0aca97da660b9d896237cf;hb=e97f807c388c10250f442b1f16c5315df2ffc2af;hpb=e34c27f4745c47446962c696105344275d011acf diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm index 6cec84b..0b9ea4a 100644 --- a/src/PVE/INotify.pm +++ b/src/PVE/INotify.pm @@ -13,8 +13,10 @@ use File::Basename; use Fcntl qw(:DEFAULT :flock); use PVE::SafeSyslog; use PVE::Exception qw(raise_param_exc); +use PVE::Network; use PVE::Tools; -use Storable qw(dclone); +use PVE::ProcFSTools; +use Clone qw(clone); use Linux::Inotify2; use base 'Exporter'; use JSON; @@ -197,6 +199,16 @@ sub discard_changes { return read_file ($filename, $full); } +sub poll_changes { + my ($filename) = @_; + + poll() if $inotify; # read new inotify events + + $versions->{$filename} = 0 if !defined ($versions->{$filename}); + + return $versions->{$filename}; +} + sub read_file { my ($fileid, $full) = @_; @@ -209,11 +221,7 @@ sub read_file { my $fd; my $shadow; - poll() if $inotify; # read new inotify events - - $versions->{$filename} = 0 if !defined ($versions->{$filename}); - - my $cver = $versions->{$filename}; + my $cver = poll_changes($filename); if (my $copy = $shadowfiles->{$filename}) { if ($fd = IO::File->new ($copy, "r")) { @@ -238,15 +246,15 @@ sub read_file { # file unchanged? if (!$ccinfo->{nocache} && - $inotify && $versions->{$filename} && + $inotify && $cver && defined ($ccinfo->{data}) && defined ($ccinfo->{version}) && ($ccinfo->{readonce} || - ($ccinfo->{version} == $versions->{$filename}))) { + ($ccinfo->{version} == $cver))) { my $ret; if (!$noclone && ref ($ccinfo->{data})) { - $ret->{data} = dclone ($ccinfo->{data}); + $ret->{data} = clone ($ccinfo->{data}); } else { $ret->{data} = $ccinfo->{data}; } @@ -268,7 +276,7 @@ sub read_file { } # we cache data with references, so we always need to - # dclone this data. Else the original data may get + # clone this data. Else the original data may get # modified. $ccinfo->{data} = $res; @@ -277,7 +285,7 @@ sub read_file { my $ret; if (!$noclone && ref ($ccinfo->{data})) { - $ret->{data} = dclone ($ccinfo->{data}); + $ret->{data} = clone ($ccinfo->{data}); } else { $ret->{data} = $ccinfo->{data}; } @@ -340,7 +348,7 @@ sub register_file { sub register_regex { my ($dir, $regex, $parser, $writer, $update, %options) = @_; - die "can't register regex after initify_init" if $inotify; + die "can't register regex after inotify_init" if $inotify; my $uid = "$dir/$regex"; die "regular expression '$uid' already added :ERROR" if defined ($ccacheregex->{$uid}); @@ -665,7 +673,7 @@ register_file('active', "/var/log/pve/tasks/active", \&write_active_workers); -my $bond_modes = { 'balance-rr' => 0, +our $bond_modes = { 'balance-rr' => 0, 'active-backup' => 1, 'balance-xor' => 2, 'broadcast' => 3, @@ -785,22 +793,35 @@ 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); + my $active = PVE::ProcFSTools::get_active_network_interfaces(); + return __read_etc_network_interfaces($fh, $proc_net_dev, $active); } sub __read_etc_network_interfaces { - my ($fh, $proc_net_dev, $proc_net_if_inet6) = @_; + my ($fh, $proc_net_dev, $active_ifaces) = @_; my $config = {}; my $ifaces = $config->{ifaces} = {}; my $options = $config->{options} = []; + my $options_alternatives = { + 'bond-slaves' => 'slaves', + 'bond_slaves' => 'slaves', + 'bond-xmit-hash-policy' => 'bond_xmit_hash_policy', + 'bond-mode' => 'bond_mode', + 'bond-miimon' =>'bond_miimon', + 'bridge-vlan-aware' => 'bridge_vlan_aware', + 'bridge-fd' => 'bridge_fd', + 'bridge-stp' => 'bridge_stp', + 'bridge-ports' => 'bridge_ports', + 'bridge-vids' => 'bridge_vids' + }; + my $line; if ($proc_net_dev) { while (defined ($line = <$proc_net_dev>)) { - if ($line =~ m/^\s*(eth\d+):.*/) { + if ($line =~ m/^\s*($PVE::Network::PHYSICAL_NIC_RE):.*/) { $ifaces->{$1}->{exists} = 1; } } @@ -849,6 +870,9 @@ sub __read_etc_network_interfaces { } elsif ($line =~ m/^\s*((\S+)\s+(.+))$/) { my $option = $1; my ($id, $value) = ($2, $3); + + $id = $options_alternatives->{$id} if $options_alternatives->{$id}; + if (($id eq 'address') || ($id eq 'netmask') || ($id eq 'broadcast') || ($id eq 'gateway')) { $f->{$id} = $value; } elsif ($id eq 'ovs_type' || $id eq 'ovs_options'|| $id eq 'ovs_bridge' || @@ -872,7 +896,7 @@ sub __read_etc_network_interfaces { } else { $d->{$id} = 'off'; } - } elsif ($id eq 'bridge_fd') { + } elsif ($id eq 'bridge_fd' || $id eq 'bridge_vids') { $d->{$id} = $value; } elsif ($id eq 'bridge_vlan_aware') { $d->{$id} = 1; @@ -905,7 +929,11 @@ sub __read_etc_network_interfaces { } } - + foreach my $ifname (@$active_ifaces) { + if (my $iface = $ifaces->{$ifname}) { + $iface->{active} = 1; + } + } if (!$ifaces->{lo}) { $ifaces->{lo}->{priority} = 1; @@ -969,7 +997,7 @@ sub __read_etc_network_interfaces { $ifaces->{$1}->{exists} = 0; $d->{exists} = 0; } - } elsif ($iface =~ m/^eth\d+$/) { + } elsif ($iface =~ m/^$PVE::Network::PHYSICAL_NIC_RE$/) { if (!$d->{ovs_type}) { $d->{type} = 'eth'; } elsif ($d->{ovs_type} eq 'OVSPort') { @@ -997,15 +1025,6 @@ sub __read_etc_network_interfaces { $d->{families} ||= ['inet']; } - 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 ($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 { @@ -1034,7 +1053,7 @@ sub __read_etc_network_interfaces { } sub __interface_to_string { - my ($iface, $d, $family, $first_block) = @_; + my ($iface, $d, $family, $first_block, $ifupdown2) = @_; (my $suffix = $family) =~ s/^inet//; @@ -1058,40 +1077,45 @@ sub __interface_to_string { # not printing out options } elsif ($d->{type} eq 'bridge') { + $d->{bridge_ports} =~ s/[;,\s]+/ /g; my $ports = $d->{bridge_ports} || 'none'; - $raw .= "\tbridge_ports $ports\n"; + $raw .= "\tbridge-ports $ports\n"; $done->{bridge_ports} = 1; my $v = defined($d->{bridge_stp}) ? $d->{bridge_stp} : 'off'; - $raw .= "\tbridge_stp $v\n"; + $raw .= "\tbridge-stp $v\n"; $done->{bridge_stp} = 1; $v = defined($d->{bridge_fd}) ? $d->{bridge_fd} : 0; - $raw .= "\tbridge_fd $v\n"; + $raw .= "\tbridge-fd $v\n"; $done->{bridge_fd} = 1; if( defined($d->{bridge_vlan_aware})) { - $raw .= "\tbridge_vlan_aware yes\n"; + $raw .= "\tbridge-vlan-aware yes\n"; + $v = defined($d->{bridge_vids}) ? $d->{bridge_vids} : "2-4094"; + $raw .= "\tbridge-vids $v\n"; } $done->{bridge_vlan_aware} = 1; + $done->{bridge_vids} = 1; } elsif ($d->{type} eq 'bond') { + $d->{slaves} =~ s/[;,\s]+/ /g; my $slaves = $d->{slaves} || 'none'; - $raw .= "\tslaves $slaves\n"; + $raw .= "\tbond-slaves $slaves\n"; $done->{slaves} = 1; my $v = defined ($d->{'bond_miimon'}) ? $d->{'bond_miimon'} : 100; - $raw .= "\tbond_miimon $v\n"; + $raw .= "\tbond-miimon $v\n"; $done->{'bond_miimon'} = 1; $v = defined ($d->{'bond_mode'}) ? $d->{'bond_mode'} : 'balance-rr'; - $raw .= "\tbond_mode $v\n"; + $raw .= "\tbond-mode $v\n"; $done->{'bond_mode'} = 1; if ($d->{'bond_mode'} && $d->{'bond_xmit_hash_policy'} && ($d->{'bond_mode'} eq 'balance-xor' || $d->{'bond_mode'} eq '802.3ad')) { - $raw .= "\tbond_xmit_hash_policy $d->{'bond_xmit_hash_policy'}\n"; + $raw .= "\tbond-xmit-hash-policy $d->{'bond_xmit_hash_policy'}\n"; } $done->{'bond_xmit_hash_policy'} = 1; @@ -1139,7 +1163,13 @@ sub __interface_to_string { $done->{ovs_type} = 1; if ($d->{ovs_bridge}) { - $raw = "allow-$d->{ovs_bridge} $iface\n$raw"; + + if ($ifupdown2) { + $raw = "auto $iface\n$raw"; + } else { + $raw = "allow-$d->{ovs_bridge} $iface\n$raw"; + } + $raw .= "\tovs_bridge $d->{ovs_bridge}\n"; $done->{ovs_bridge} = 1; } @@ -1172,11 +1202,12 @@ sub __interface_to_string { sub write_etc_network_interfaces { my ($filename, $fh, $config) = @_; - my $raw = __write_etc_network_interfaces($config); + my $ifupdown2 = -e '/usr/share/ifupdown2'; + my $raw = __write_etc_network_interfaces($config, $ifupdown2); PVE::Tools::safe_print($filename, $fh, $raw); } sub __write_etc_network_interfaces { - my ($config) = @_; + my ($config, $ifupdown2) = @_; my $ifaces = $config->{ifaces}; my @options = @{$config->{options}}; @@ -1205,7 +1236,7 @@ sub __write_etc_network_interfaces { $d->{type} eq 'OVSBond') { my $brname = $used_ports->{$iface}; if (!$brname || !$ifaces->{$brname}) { - if ($iface =~ /^eth/) { + if ($iface =~ /^$PVE::Network::PHYSICAL_NIC_RE/) { $ifaces->{$iface} = { type => 'eth', exists => 1, method => 'manual', @@ -1294,7 +1325,7 @@ NETWORKDOC my $pri; if ($iface eq 'lo') { $pri = $if_type_hash->{loopback}; - } elsif ($iface =~ m/^eth\d+$/) { + } elsif ($iface =~ m/^$PVE::Network::PHYSICAL_NIC_RE$/) { $pri = $if_type_hash->{eth} + $child; } elsif ($iface =~ m/^bond\d+$/) { $pri = $if_type_hash->{bond} + $child; @@ -1336,7 +1367,7 @@ NETWORKDOC $printed->{$iface} = 1; $raw .= "auto $iface\n" if $d->{autostart}; my $i = 0; # some options should be printed only once - $raw .= __interface_to_string($iface, $d, $_, !$i++) foreach @{$d->{families}}; + $raw .= __interface_to_string($iface, $d, $_, !$i++, $ifupdown2) foreach @{$d->{families}}; } $raw .= $_->[1] . "\n" foreach @options;