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;
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) = @_;
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")) {
# 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};
}
}
# 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;
my $ret;
if (!$noclone && ref ($ccinfo->{data})) {
- $ret->{data} = dclone ($ccinfo->{data});
+ $ret->{data} = clone ($ccinfo->{data});
} else {
$ret->{data} = $ccinfo->{data};
}
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});
my $saved = $task->{saved} ? 1 : 0;
if ($task->{endtime}) {
if ($task->{status}) {
- $raw .= sprintf("$upid $saved %08X $task->{status}\n", $task->{endtime});
+ $raw .= sprintf("%s %s %08X %s\n", $upid, $saved, $task->{endtime}, $task->{status});
} else {
- $raw .= sprintf("$upid $saved %08X\n", $task->{endtime});
+ $raw .= sprintf("%s %s %08X\n", $upid, $saved, $task->{endtime});
}
} else {
$raw .= "$upid $saved\n";
\&write_active_workers);
-my $bond_modes = { 'balance-rr' => 0,
+our $bond_modes = { 'balance-rr' => 0,
'active-backup' => 1,
'balance-xor' => 2,
'broadcast' => 3,
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} = {};
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;
}
}
}
}
-
+ foreach my $ifname (@$active_ifaces) {
+ if (my $iface = $ifaces->{$ifname}) {
+ $iface->{active} = 1;
+ }
+ }
if (!$ifaces->{lo}) {
$ifaces->{lo}->{priority} = 1;
$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') {
$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 {
# 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";
$done->{bridge_ports} = 1;
} elsif ($d->{type} eq 'bond') {
+ $d->{slaves} =~ s/[;,\s]+/ /g;
my $slaves = $d->{slaves} || 'none';
$raw .= "\tslaves $slaves\n";
$done->{slaves} = 1;
$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',
}
}
- # 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};
my $printed = {};
my $if_type_hash = {
- unknown => 0,
loopback => 100000,
eth => 200000,
bond => 300000,
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;
$pri = $if_type_hash->{bridge} + $child;
}
- return $pri || ($if_type_hash->{unknown} + $child);
+ return $pri;
};
foreach my $iface (sort {
my $ref1 = $ifaces->{$a};
my $ref2 = $ifaces->{$b};
- my $p1 = &$lookup_type_prio($a);
- my $p2 = &$lookup_type_prio($b);
+ my $tp1 = &$lookup_type_prio($a);
+ my $tp2 = &$lookup_type_prio($b);
+
+ # Only recognized types are in relation to each other. If one type
+ # is unknown then only consider the interfaces' priority attributes.
+ $tp1 = $tp2 = 0 if !defined($tp1) || !defined($tp2);
- $p1 += $ref1->{priority} // 50000;
- $p2 += $ref2->{priority} // 50000;
+ my $p1 = $tp1 + ($ref1->{priority} // 50000);
+ my $p2 = $tp2 + ($ref2->{priority} // 50000);
return $p1 <=> $p2 if $p1 != $p2;