commit
492983d7ad
44 changed files with 5029 additions and 3264 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,505 @@ |
|||||||
|
#!/usr/bin/perl |
||||||
|
# |
||||||
|
# This daemon watches for network interface link change (unplugged or plugged in network cables). |
||||||
|
# |
||||||
|
# At this point, the only thing this does is call 'scan-network' when a change is detected. |
||||||
|
# |
||||||
|
# NOTE: This is designed to be minimal overhead, so there is no attempt to connect to the database. As such, |
||||||
|
# be mindful of what this daemon is used for. |
||||||
|
# |
||||||
|
|
||||||
|
use strict; |
||||||
|
use warnings; |
||||||
|
use Data::Dumper; |
||||||
|
use Text::Diff; |
||||||
|
use Anvil::Tools; |
||||||
|
|
||||||
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||||
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||||
|
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||||
|
{ |
||||||
|
$running_directory =~ s/^\./$ENV{PWD}/; |
||||||
|
} |
||||||
|
|
||||||
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||||
|
$| = 1; |
||||||
|
|
||||||
|
my $anvil = Anvil::Tools->new(); |
||||||
|
|
||||||
|
# Read switches |
||||||
|
$anvil->Get->switches({list => [], man => $THIS_FILE}); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); |
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); |
||||||
|
|
||||||
|
# Calculate my sum so that we can exit if it changes later. |
||||||
|
$anvil->Storage->record_md5sums; |
||||||
|
my $next_md5sum_check = time + 30; |
||||||
|
|
||||||
|
my $directory = "/sys/class/net"; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }}); |
||||||
|
|
||||||
|
# Now go into the main loop |
||||||
|
while(1) |
||||||
|
{ |
||||||
|
### NOTE: A lot of this logic comes from scan-network |
||||||
|
my $scan_time = time; |
||||||
|
my $trigger = 0; |
||||||
|
|
||||||
|
# Look for interfaces. |
||||||
|
local(*DIRECTORY); |
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0018", variables => { directory => $directory }}); |
||||||
|
opendir(DIRECTORY, $directory); |
||||||
|
while(my $file = readdir(DIRECTORY)) |
||||||
|
{ |
||||||
|
next if $file eq "."; |
||||||
|
next if $file eq ".."; |
||||||
|
next if $file eq "lo"; |
||||||
|
my $full_path = $directory."/".$file; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { full_path => $full_path }}); |
||||||
|
if (-d $full_path) |
||||||
|
{ |
||||||
|
# Pull out the data I want. Note that some of these don't exist with virtio-net interfaces. |
||||||
|
my $interface = $file; |
||||||
|
my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0; |
||||||
|
$link_state =~ s/\n$//; |
||||||
|
my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0; |
||||||
|
$mtu =~ s/\n$//; |
||||||
|
my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half? |
||||||
|
$duplex =~ s/\n$//; |
||||||
|
my $operational = -e $full_path."/operstate" ? $anvil->Storage->read_file({file => $full_path."/operstate"}) : "unknown"; # up or down |
||||||
|
$operational =~ s/\n$//; |
||||||
|
my $modalias = -e $full_path."/device/modalias" ? $anvil->Storage->read_file({file => $full_path."/device/modalias"}) : "unknown"; |
||||||
|
$modalias =~ s/\n$//; |
||||||
|
my $speed = $link_state ? $anvil->Storage->read_file({file => $full_path."/speed"}) : 0; # Mbps (ie: 1000 = Gbps), gives a very high number for unplugged link |
||||||
|
$speed =~ s/\n$//; |
||||||
|
my $media = "unknown"; |
||||||
|
my $type = "interface"; |
||||||
|
my $driver = ""; |
||||||
|
my $tx_bytes = 0; # How many bytes transmitted |
||||||
|
my $rx_bytes = 0; # How many bytes received |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
interface => $interface, |
||||||
|
link_state => $link_state, |
||||||
|
mtu => $mtu, |
||||||
|
duplex => $duplex, |
||||||
|
operational => $operational, |
||||||
|
speed => $speed, |
||||||
|
modalias => $modalias, |
||||||
|
}}); |
||||||
|
|
||||||
|
# Get the MAC address |
||||||
|
my $mac_address = ""; |
||||||
|
my $shell_call = $anvil->data->{path}{exe}{ethtool}." -P ".$interface; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||||
|
|
||||||
|
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
output => $output, |
||||||
|
return_code => $return_code, |
||||||
|
}}); |
||||||
|
if ($output =~ /(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)$/) |
||||||
|
{ |
||||||
|
$mac_address = lc($1); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }}); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
# Get it by reading the address file. |
||||||
|
if (-e $full_path."/bonding_slave/perm_hwaddr") |
||||||
|
{ |
||||||
|
$mac_address = $anvil->Storage->read_file({file => $full_path."/bonding_slave/perm_hwaddr"}); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }}); |
||||||
|
} |
||||||
|
elsif (-e $full_path."/address") |
||||||
|
{ |
||||||
|
$mac_address = $anvil->Storage->read_file({file => $full_path."/address"}); |
||||||
|
$mac_address =~ s/\n//; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# These are variables that will be needed if this is a bond interface. |
||||||
|
my $ip_address = ""; |
||||||
|
my $subnet_mask = ""; |
||||||
|
my $bond_mode = ""; |
||||||
|
my $primary_interface = ""; |
||||||
|
my $primary_reselect = ""; |
||||||
|
my $active_interface = ""; |
||||||
|
my $mii_polling_interval = ""; |
||||||
|
my $up_delay = ""; |
||||||
|
my $down_delay = ""; |
||||||
|
my $bond_parent = ""; |
||||||
|
|
||||||
|
# These are variables that will be needed if this is a bridge interface |
||||||
|
my $bridge_id = ""; |
||||||
|
my $bridge_stp_enabled = ""; |
||||||
|
|
||||||
|
# If this interface is already a bond slave, the real mac address will be in a |
||||||
|
# sub-directory. |
||||||
|
my $mac_bond_file = $directory."/".$file."/bonding_slave/perm_hwaddr"; |
||||||
|
if (-e $mac_bond_file) |
||||||
|
{ |
||||||
|
# It's a slave. |
||||||
|
$mac_address = $anvil->Storage->read_file({file => $mac_bond_file}); |
||||||
|
$mac_address =~ s/\n$//; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }}); |
||||||
|
} |
||||||
|
|
||||||
|
# Pick out our driver. |
||||||
|
if ($modalias =~ /^virtio:/) |
||||||
|
{ |
||||||
|
$driver = "virtio"; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }}); |
||||||
|
} |
||||||
|
|
||||||
|
# If this is a virtual interface, set some fake values that don't actually exist on |
||||||
|
# the system for the sake of a cleaner display. |
||||||
|
if (($mac_address =~ /^52:54:00/) or ($driver eq "virtio")) |
||||||
|
{ |
||||||
|
### Set some fake values. |
||||||
|
# Speed is "as fast as possible", so we'll record 100 Gbps, but that is really kind of arbitrary. |
||||||
|
if ((not $speed) or ($speed eq "-1")) |
||||||
|
{ |
||||||
|
$speed = 10000; |
||||||
|
} |
||||||
|
if ((not $duplex) or ($duplex eq "unknown")) |
||||||
|
{ |
||||||
|
$duplex = "full"; |
||||||
|
} |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
speed => $speed, |
||||||
|
duplex => $duplex, |
||||||
|
}}); |
||||||
|
} |
||||||
|
# If the state is 'down', set the speed to '0'. |
||||||
|
if (not $link_state) |
||||||
|
{ |
||||||
|
$speed = 0; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed }}); |
||||||
|
} |
||||||
|
|
||||||
|
# Is this a bond interface? |
||||||
|
if (-e "/proc/net/bonding/".$interface) |
||||||
|
{ |
||||||
|
# Yup, we'll neet to dig into the bond proc files to get the proper slaved |
||||||
|
# interface MAC addresses. |
||||||
|
$type = "bond"; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
||||||
|
|
||||||
|
# Read the bond mode. |
||||||
|
$bond_mode = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/mode"}); |
||||||
|
$bond_mode =~ s/\s.*//; |
||||||
|
$bond_mode =~ s/\n$//; |
||||||
|
$primary_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary"}); |
||||||
|
$primary_interface =~ s/\n$//; |
||||||
|
$primary_reselect = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary_reselect"}); |
||||||
|
$primary_reselect =~ s/\s.*//; |
||||||
|
$primary_reselect =~ s/\n$//; |
||||||
|
$active_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/active_slave"}); |
||||||
|
$active_interface =~ s/\n$//; |
||||||
|
$mii_polling_interval = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/miimon"}); |
||||||
|
$mii_polling_interval =~ s/\n$//; |
||||||
|
$up_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/updelay"}); |
||||||
|
$up_delay =~ s/\n$//; |
||||||
|
$down_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/downdelay"}); |
||||||
|
$down_delay =~ s/\n$//; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
active_interface => $active_interface, |
||||||
|
bond_mode => $bond_mode, |
||||||
|
mii_polling_interval => $mii_polling_interval, |
||||||
|
primary_reselect => $primary_reselect, |
||||||
|
primary_interface => $primary_interface, |
||||||
|
type => $type, |
||||||
|
}}); |
||||||
|
} |
||||||
|
elsif ((-e $full_path."/master") && ($interface !~ /^vnet/)) |
||||||
|
{ |
||||||
|
# We're in a bond. |
||||||
|
my $target = readlink($full_path."/master"); |
||||||
|
$bond_parent = ($target =~ /^.*\/(.*)$/)[0]; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
target => $target, |
||||||
|
bond_parent => $bond_parent, |
||||||
|
}}); |
||||||
|
} |
||||||
|
elsif (-d $full_path."/bridge") |
||||||
|
{ |
||||||
|
# It's a bridge |
||||||
|
$type = "bridge"; |
||||||
|
$bridge_id = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/bridge_id"}); |
||||||
|
$bridge_id =~ s/\n$//; |
||||||
|
$bridge_stp_enabled = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/stp_state"}); |
||||||
|
$bridge_stp_enabled =~ s/\n$//; |
||||||
|
$speed = 0; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
type => $type, |
||||||
|
bridge_id => $bridge_id, |
||||||
|
bridge_stp_enabled => $bridge_stp_enabled, |
||||||
|
}}); |
||||||
|
if ($bridge_stp_enabled eq "0") |
||||||
|
{ |
||||||
|
$bridge_stp_enabled = "disabled"; |
||||||
|
} |
||||||
|
elsif ($bridge_stp_enabled eq "1") |
||||||
|
{ |
||||||
|
$bridge_stp_enabled = "enabled_kernel"; |
||||||
|
} |
||||||
|
elsif ($bridge_stp_enabled eq "2") |
||||||
|
{ |
||||||
|
$bridge_stp_enabled = "enabled_userland"; |
||||||
|
} |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_stp_enabled => $bridge_stp_enabled }}); |
||||||
|
} |
||||||
|
|
||||||
|
# If this is a 'vnet' device, set 'operational' to up |
||||||
|
if ($interface =~ /^vnet/) |
||||||
|
{ |
||||||
|
### TODO: We can't assume this, we need to detect virsh net up/down |
||||||
|
$operational = "up"; |
||||||
|
$media = "virtual"; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
operational => $operational, |
||||||
|
media => $media, |
||||||
|
}}); |
||||||
|
} |
||||||
|
|
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
active_interface => $active_interface, |
||||||
|
bond_parent => $bond_parent, |
||||||
|
bond_mode => $bond_mode, |
||||||
|
bridge_id => $bridge_id, |
||||||
|
bridge_stp_enabled => $bridge_stp_enabled, |
||||||
|
down_delay => $down_delay, |
||||||
|
duplex => $duplex, |
||||||
|
interface => $interface, |
||||||
|
mac_address => $mac_address, |
||||||
|
mii_polling_interval => $mii_polling_interval, |
||||||
|
mtu => $mtu, |
||||||
|
operational => $operational, |
||||||
|
primary_reselect => $primary_reselect, |
||||||
|
primary_interface => $primary_interface, |
||||||
|
speed => $speed, |
||||||
|
subnet_mask => $subnet_mask, |
||||||
|
type => $type, |
||||||
|
up_delay => $up_delay, |
||||||
|
}}); |
||||||
|
|
||||||
|
# Find the media, if possible. |
||||||
|
(my $ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ethtool}." ".$interface}); |
||||||
|
foreach my $line (split/\n/, $ethtool) |
||||||
|
{ |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
||||||
|
if ($line =~ /Supported ports: \[ (.*?) \]/i) |
||||||
|
{ |
||||||
|
$media = lc($1); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { media => $media }}); |
||||||
|
|
||||||
|
# This can be 'tp mii', which breaks json. |
||||||
|
if ($media =~ /\t/) |
||||||
|
{ |
||||||
|
$media =~ s/\t/,/g; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { media => $media }}); |
||||||
|
} |
||||||
|
last; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# Trigger? |
||||||
|
if (not exists $anvil->data->{last_scan}{$interface}) |
||||||
|
{ |
||||||
|
print "The interface: [".$interface."] has been found. We will now monitor it for changes.\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
# Now look for differences. |
||||||
|
if ($anvil->data->{last_scan}{$interface}{active_interface} ne $active_interface) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] has a different active interface: [".$anvil->data->{last_scan}{$interface}{active_interface}."] -> [".$active_interface."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{bond_mode} ne $bond_mode) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] mode has changed from: [".$anvil->data->{last_scan}{$interface}{bond_mode}."] -> [".$bond_mode."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{bond_parent} ne $bond_parent) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] bond parent has changed from: [".$anvil->data->{last_scan}{$interface}{bond_parent}."] -> [".$bond_parent."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{bridge_id} ne $bridge_id) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] bridge ID has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_id}."] -> [".$bridge_id."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{bridge_stp_enabled} ne $bridge_stp_enabled) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] spanning tree protocol (STP) setting has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_stp_enabled}."] -> [".$bridge_stp_enabled."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{down_delay} ne $down_delay) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] down delay has changed from: [".$anvil->data->{last_scan}{$interface}{bridge_stp_enabled}."ms] -> [".$bridge_stp_enabled."ms].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{up_delay} ne $up_delay) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] up delay has changed from: [".$anvil->data->{last_scan}{$interface}{up_delay}."ms] -> [".$up_delay."ms].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{duplex} ne $duplex) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] duplex has changed from: [".$anvil->data->{last_scan}{$interface}{duplex}."] -> [".$duplex."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{ip_address} ne $ip_address) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] ip address has changed from: [".$anvil->data->{last_scan}{$interface}{ip_address}."] -> [".$ip_address."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{subnet_mask} ne $subnet_mask) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] subnet_mask has changed from: [".$anvil->data->{last_scan}{$interface}{subnet_mask}."] -> [".$subnet_mask."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{link_state} ne $link_state) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] link status has changed from: [".$anvil->data->{last_scan}{$interface}{link_state}."] -> [".$link_state."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{mac_address} ne $mac_address) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] MAC address has changed from: [".$anvil->data->{last_scan}{$interface}{mac_address}."] -> [".$mac_address."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{media} ne $media) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] media has changed from: [".$anvil->data->{last_scan}{$interface}{media}."] -> [".$media."]. (Excuse me, how?!)\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{mii_polling_interval} ne $mii_polling_interval) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] media independent interface (mii) polling interval has changed from: [".$anvil->data->{last_scan}{$interface}{mii_polling_interval}."ms] -> [".$mii_polling_interval."ms].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{mtu} ne $mtu) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] maximum transmission unit (mtu) has changed from: [".$anvil->data->{last_scan}{$interface}{mtu}." bytes] -> [".$mtu." bytes].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{operational} ne $operational) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] operational status has changed from: [".$anvil->data->{last_scan}{$interface}{operational}."] -> [".$operational."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{primary_reselect} ne $primary_reselect) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] primary reselect policy has changed from: [".$anvil->data->{last_scan}{$interface}{primary_reselect}."] -> [".$primary_reselect."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{primary_interface} ne $primary_interface) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] primary interface has changed from: [".$anvil->data->{last_scan}{$interface}{primary_interface}."] -> [".$primary_interface."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{speed} ne $speed) |
||||||
|
{ |
||||||
|
print "The ".$type.": [".$interface."] speed has changed from: [".$anvil->data->{last_scan}{$interface}{speed}." Mbps] -> [".$speed." Mbps].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
if ($anvil->data->{last_scan}{$interface}{type} ne $type) |
||||||
|
{ |
||||||
|
print "The device: [".$interface."] type has changed from: [".$anvil->data->{last_scan}{$interface}{type}."] -> [".$type."].\n"; |
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# We'll use this to determine when an interface has disappeared. |
||||||
|
$anvil->data->{last_scan}{$interface}{seen} = $scan_time; |
||||||
|
|
||||||
|
# Store new information we found. |
||||||
|
$anvil->data->{last_scan}{$interface}{active_interface} = $active_interface; |
||||||
|
$anvil->data->{last_scan}{$interface}{bond_mode} = $bond_mode; |
||||||
|
$anvil->data->{last_scan}{$interface}{bond_parent} = $bond_parent; |
||||||
|
$anvil->data->{last_scan}{$interface}{bridge_id} = $bridge_id; |
||||||
|
$anvil->data->{last_scan}{$interface}{bridge_stp_enabled} = $bridge_stp_enabled; |
||||||
|
$anvil->data->{last_scan}{$interface}{down_delay} = $down_delay; |
||||||
|
$anvil->data->{last_scan}{$interface}{duplex} = $duplex; |
||||||
|
$anvil->data->{last_scan}{$interface}{ip_address} = $ip_address; |
||||||
|
$anvil->data->{last_scan}{$interface}{link_state} = $link_state; |
||||||
|
$anvil->data->{last_scan}{$interface}{mac_address} = $mac_address; |
||||||
|
$anvil->data->{last_scan}{$interface}{media} = $media; |
||||||
|
$anvil->data->{last_scan}{$interface}{mii_polling_interval} = $mii_polling_interval; |
||||||
|
$anvil->data->{last_scan}{$interface}{mtu} = $mtu; |
||||||
|
$anvil->data->{last_scan}{$interface}{operational} = $operational; |
||||||
|
$anvil->data->{last_scan}{$interface}{primary_reselect} = $primary_reselect; |
||||||
|
$anvil->data->{last_scan}{$interface}{primary_interface} = $primary_interface; |
||||||
|
$anvil->data->{last_scan}{$interface}{speed} = $speed; |
||||||
|
$anvil->data->{last_scan}{$interface}{subnet_mask} = $subnet_mask; |
||||||
|
$anvil->data->{last_scan}{$interface}{type} = $type; |
||||||
|
$anvil->data->{last_scan}{$interface}{up_delay} = $up_delay; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
"last_scan::${interface}::seen" => $anvil->data->{last_scan}{$interface}{seen}, |
||||||
|
"last_scan::${interface}::active_interface" => $anvil->data->{last_scan}{$interface}{active_interface}, |
||||||
|
"last_scan::${interface}::bond_mode" => $anvil->data->{last_scan}{$interface}{bond_mode}, |
||||||
|
"last_scan::${interface}::bond_parent" => $anvil->data->{last_scan}{$interface}{bond_parent}, |
||||||
|
"last_scan::${interface}::bridge_id" => $anvil->data->{last_scan}{$interface}{bridge_id}, |
||||||
|
"last_scan::${interface}::bridge_stp_enabled" => $anvil->data->{last_scan}{$interface}{bridge_stp_enabled}, |
||||||
|
"last_scan::${interface}::down_delay" => $anvil->data->{last_scan}{$interface}{down_delay}, |
||||||
|
"last_scan::${interface}::duplex" => $anvil->data->{last_scan}{$interface}{duplex}, |
||||||
|
"last_scan::${interface}::ip_address" => $anvil->data->{last_scan}{$interface}{ip_address}, |
||||||
|
"last_scan::${interface}::link_state" => $anvil->data->{last_scan}{$interface}{link_state}, |
||||||
|
"last_scan::${interface}::mac_address" => $anvil->data->{last_scan}{$interface}{mac_address}, |
||||||
|
"last_scan::${interface}::media" => $anvil->data->{last_scan}{$interface}{media}, |
||||||
|
"last_scan::${interface}::mii_polling_interval" => $anvil->data->{last_scan}{$interface}{mii_polling_interval}, |
||||||
|
"last_scan::${interface}::mtu" => $anvil->data->{last_scan}{$interface}{mtu}, |
||||||
|
"last_scan::${interface}::operational" => $anvil->data->{last_scan}{$interface}{operational}, |
||||||
|
"last_scan::${interface}::primary_reselect" => $anvil->data->{last_scan}{$interface}{primary_reselect}, |
||||||
|
"last_scan::${interface}::primary_interface" => $anvil->data->{last_scan}{$interface}{primary_interface}, |
||||||
|
"last_scan::${interface}::speed" => $anvil->data->{last_scan}{$interface}{speed}, |
||||||
|
"last_scan::${interface}::subnet_mask" => $anvil->data->{last_scan}{$interface}{subnet_mask}, |
||||||
|
"last_scan::${interface}::type" => $anvil->data->{last_scan}{$interface}{type}, |
||||||
|
"last_scan::${interface}::up_delay" => $anvil->data->{last_scan}{$interface}{up_delay}, |
||||||
|
}}); |
||||||
|
} |
||||||
|
} |
||||||
|
closedir(DIRECTORY); |
||||||
|
|
||||||
|
# Now look for interfaces that disappeared. |
||||||
|
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{last_scan}}) |
||||||
|
{ |
||||||
|
next if $anvil->data->{last_scan}{$interface}{seen} == $scan_time; |
||||||
|
print "The device: [".$interface."] appears to have disappeared!\n"; |
||||||
|
delete $anvil->data->{last_scan}{$interface}; |
||||||
|
|
||||||
|
$trigger = 1; |
||||||
|
} |
||||||
|
|
||||||
|
# Trigger? |
||||||
|
if ($trigger) |
||||||
|
{ |
||||||
|
my $shell_call = $anvil->data->{path}{directories}{scan_agents}."/scan-network/scan-network".$anvil->Log->switches; |
||||||
|
print "Triggering the call to run: [".$shell_call."]\n"; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||||
|
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||||
|
output => $output, |
||||||
|
return_code => $return_code, |
||||||
|
}}); |
||||||
|
} |
||||||
|
|
||||||
|
if (time > $next_md5sum_check) |
||||||
|
{ |
||||||
|
$next_md5sum_check = time + 30; |
||||||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { next_md5sum_check => $next_md5sum_check }}); |
||||||
|
if ($anvil->Storage->check_md5sums) |
||||||
|
{ |
||||||
|
# NOTE: We exit with '0' to prevent systemctl from showing a scary red message. |
||||||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "message_0014"}); |
||||||
|
$anvil->nice_exit({exit_code => 0}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sleep 2; |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@ |
|||||||
|
[Unit] |
||||||
|
Description=Anvil! Intelligent Availability Platform - Network Monitor Daemon |
||||||
|
Wants=network.target |
||||||
|
|
||||||
|
[Service] |
||||||
|
Type=simple |
||||||
|
ExecStart=/usr/sbin/anvil-monitor-network |
||||||
|
ExecStop=/bin/kill -WINCH ${MAINPID} |
||||||
|
Restart=always |
||||||
|
|
||||||
|
[Install] |
||||||
|
WantedBy=multi-user.target |
Loading…
Reference in new issue