You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4453 lines
204 KiB
4453 lines
204 KiB
#!/usr/bin/perl |
|
# |
|
# This scans the network, bridges, bonds and interfaces. |
|
# |
|
# Examples; |
|
# |
|
# Exit codes; |
|
# 0 = Normal exit. |
|
# 1 = Startup failure (not running as root, no DB, bad file read, etc) |
|
# |
|
# TODO: |
|
# - |
|
# |
|
|
|
use strict; |
|
use warnings; |
|
use Anvil::Tools; |
|
use Data::Dumper; |
|
|
|
# Disable buffering |
|
$| = 1; |
|
|
|
# Prevent a discrepency between UID/GID and EUID/EGID from throwing an error. |
|
$< = $>; |
|
$( = $); |
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
|
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
|
{ |
|
$running_directory =~ s/^\./$ENV{PWD}/; |
|
} |
|
|
|
my $anvil = Anvil::Tools->new(); |
|
|
|
# Make sure we're running as 'root' |
|
# $< == real UID, $> == effective UID |
|
if (($< != 0) && ($> != 0)) |
|
{ |
|
# Not root |
|
print $anvil->Words->string({key => "error_0005"})."\n"; |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# These are the threasholds for when to alert when swap is running out. |
|
$anvil->data->{switches}{force} = 0; |
|
|
|
#$anvil->Storage->read_config(); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0115", variables => { program => $THIS_FILE }}); |
|
|
|
# Read switches |
|
$anvil->Get->switches; |
|
|
|
# Handle start-up tasks |
|
my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE}); |
|
if ($problem) |
|
{ |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
if ($anvil->data->{switches}{purge}) |
|
{ |
|
# This can be called when doing bulk-database purges. |
|
my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"; |
|
$anvil->Database->purge_data({ |
|
debug => 2, |
|
tables => $anvil->Database->get_tables_from_schema({schema_file => $schema_file}), |
|
}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
# If there's no DB (or cached data isn't recorded to the database yet), this will store those records. |
|
$anvil->data->{cache}{new_file} = "# interface (nm_device),timestamp,mac_address,speed,link_state,operational,nm_uuid,nm_name\n"; |
|
process_interface_cache($anvil); |
|
|
|
# Read the data. |
|
collect_data($anvil); |
|
|
|
# Load stored data. |
|
read_last_scan($anvil); |
|
|
|
# Look for changes. |
|
find_changes($anvil); |
|
|
|
# Finally, process health weights. |
|
process_health($anvil); |
|
|
|
# This clears the TX and RX variable data for interfaces older than 'scancore::database::age_out'. |
|
clear_old_variables($anvil); |
|
|
|
# This removes network interfaces that have been marked as DELETED for a while now. |
|
clear_old_interfaces($anvil); |
|
|
|
# Write out the interface cache |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { |
|
"cache::new_file" => $anvil->data->{cache}{new_file}, |
|
"path::data::network_cache" => $anvil->data->{path}{data}{network_cache}, |
|
}}); |
|
$anvil->Storage->write_file({ |
|
body => $anvil->data->{cache}{new_file}, |
|
file => $anvil->data->{path}{data}{network_cache}, |
|
overwrite => 1, |
|
backup => 0, |
|
}); |
|
|
|
# Shut down. |
|
$anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); |
|
|
|
|
|
############################################################################################################# |
|
# Functions # |
|
############################################################################################################# |
|
|
|
# This reads in the interface cache file and looks for records that haven't been stored in the database yet. |
|
sub process_interface_cache |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Does the file exist? If so, read it in. |
|
if (-e $anvil->data->{path}{data}{network_cache}) |
|
{ |
|
my $body = $anvil->Storage->read_file({debug => 2, cache => 0, force_read => 1, file => $anvil->data->{path}{data}{network_cache}}); |
|
foreach my $line (split/\n/, $body) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
next if $line =~ /^#/; |
|
my ($nm_device, $timestamp, $mac_address, $speed, $link_state, $operational, $nm_uuid, $nm_name) = (split/,/, $line); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
timestamp => $timestamp, |
|
speed => $speed, |
|
mac_address => $mac_address, |
|
link_state => $link_state, |
|
operational => $operational, |
|
nm_uuid => $nm_uuid, |
|
nm_device => $nm_device, |
|
}}); |
|
|
|
if ($anvil->data->{sys}{database}{connections}) |
|
{ |
|
my ($network_interface_uuid) = $anvil->Database->insert_or_update_network_interfaces({ |
|
debug => 2, |
|
link_only => 1, |
|
timestamp => $timestamp, |
|
network_interface_name => $nm_device, |
|
network_interface_link_state => $link_state, |
|
network_interface_mac_address => $mac_address, |
|
network_interface_operational => $operational, |
|
network_interface_speed => $speed, |
|
network_interface_nm_uuid => $nm_uuid, |
|
network_interface_device => $nm_device, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { network_interface_uuid => $network_interface_uuid }}); |
|
if (not $network_interface_uuid) |
|
{ |
|
# Failed to update, could be that we cached data for an interface not yet |
|
# seen. If so, the coming scan will add it and this cache should flush out |
|
# next time. |
|
$anvil->data->{cache}{new_file} .= $line."\n"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cache::new_file" => $anvil->data->{cache}{new_file} }}); |
|
} |
|
} |
|
else |
|
{ |
|
# No database, re-cache |
|
$anvil->data->{cache}{new_file} .= $line."\n"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "cache::new_file" => $anvil->data->{cache}{new_file} }}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This removes network interfaces that have been marked as DELETED for a while now. |
|
sub clear_old_interfaces |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Read in all interfaces and for each, delete historical records over the age-out time. |
|
my $age = $anvil->data->{scancore}{database}{age_out}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); |
|
|
|
if ($age =~ /\D/) |
|
{ |
|
# Age is not valid, set it to defaults. |
|
$age = 24; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); |
|
} |
|
|
|
my $query = "SELECT now() - '".$age."h'::interval;"; |
|
my $old_timestamp = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
query => $query, |
|
old_timestamp => $old_timestamp, |
|
}}); |
|
|
|
# It is possible that a record exists on one DB, but not the other. Unsure how this happens, but this |
|
# cleans it up. |
|
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
uuid => $anvil->Database->get_host_from_uuid({debug => 2, short => 1, host_uuid => $uuid})." (".$uuid.")", |
|
}}); |
|
my $query = " |
|
SELECT |
|
ip_address_uuid, |
|
ip_address_address |
|
FROM |
|
ip_addresses |
|
WHERE |
|
ip_address_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
ip_address_note = 'DELETED' |
|
AND |
|
modified_date < '".$old_timestamp."' |
|
ORDER BY |
|
ip_address_address ASC |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $ip_address_uuid = $row->[0]; |
|
my $ip_address_address = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:ip_address_uuid' => $ip_address_uuid, |
|
's2:ip_address_address' => $ip_address_address, |
|
}}); |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0005", variables => { |
|
age => $age, |
|
ip => $ip_address_address, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.ip_addresses WHERE ip_address_uuid = '".$ip_address_uuid."';"; |
|
push @{$queries}, "DELETE FROM ip_addresses WHERE ip_address_uuid = '".$ip_address_uuid."';"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
# Write to both DBs. |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
} |
|
|
|
# Remove interfaces |
|
$query = " |
|
SELECT |
|
network_interface_uuid, |
|
network_interface_mac_address, |
|
network_interface_name |
|
FROM |
|
network_interfaces |
|
WHERE |
|
network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
network_interface_operational = 'DELETED' |
|
AND |
|
modified_date < '".$old_timestamp."' |
|
ORDER BY |
|
network_interface_name ASC |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
$results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $network_interface_uuid = $row->[0]; |
|
my $network_interface_mac_address = $row->[1]; |
|
my $network_interface_name = $row->[2]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:network_interface_uuid' => $network_interface_uuid, |
|
's2:network_interface_mac_address' => $network_interface_mac_address, |
|
's3:network_interface_name' => $network_interface_name, |
|
}}); |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0002", variables => { |
|
age => $age, |
|
mac => $network_interface_mac_address, |
|
name => $network_interface_name, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_uuid = '".$network_interface_uuid."';"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_uuid = '".$network_interface_uuid."';"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
# Write to both DBs. |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
} |
|
|
|
# Delete old bonds |
|
$query = " |
|
SELECT |
|
bond_uuid, |
|
bond_name |
|
FROM |
|
bonds |
|
WHERE |
|
bond_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
bond_mode = 'DELETED' |
|
AND |
|
modified_date < '".$old_timestamp."' |
|
ORDER BY |
|
bond_name ASC |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
$results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bond_uuid = $row->[0]; |
|
my $bond_name = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:bond_uuid' => $bond_uuid, |
|
's2:bond_name' => $bond_name, |
|
}}); |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0003", variables => { |
|
age => $age, |
|
name => $bond_name, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.bonds WHERE bond_uuid = '".$bond_uuid."';"; |
|
push @{$queries}, "DELETE FROM bonds WHERE bond_uuid = '".$bond_uuid."';"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
# Write to both DBs. |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
} |
|
|
|
# Delete old bridges |
|
$query = " |
|
SELECT |
|
bridge_uuid, |
|
bridge_name |
|
FROM |
|
bridges |
|
WHERE |
|
bridge_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
bridge_id = 'DELETED' |
|
AND |
|
modified_date < '".$old_timestamp."' |
|
ORDER BY |
|
bridge_name ASC |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
$results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bridge_uuid = $row->[0]; |
|
my $bridge_name = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:bridge_uuid' => $bridge_uuid, |
|
's2:bridge_name' => $bridge_name, |
|
}}); |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0004", variables => { |
|
age => $age, |
|
name => $bridge_name, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.bridges WHERE bridge_uuid = '".$bridge_uuid."';"; |
|
push @{$queries}, "DELETE FROM bridges WHERE bridge_uuid = '".$bridge_uuid."';"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
# Write to both DBs. |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This clears the TX and RX variable data for interfaces older than 'scancore::database::age_out'. |
|
sub clear_old_variables |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Only Strikers run this. |
|
my $host_type = $anvil->Get->host_type(); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); |
|
if ($host_type ne "striker") |
|
{ |
|
return(0); |
|
} |
|
|
|
# Read in all interfaces and for each, delete historical records over the age-out time. |
|
my $age = $anvil->data->{scancore}{database}{age_out}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }}); |
|
|
|
if ($age =~ /\D/) |
|
{ |
|
# Age is not valid, set it to defaults. |
|
$age = 24; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }}); |
|
} |
|
|
|
# Get the timestamp to delete thermal and power records older than $age hours. |
|
my $query = "SELECT now() - '".$age."h'::interval;"; |
|
my $old_timestamp = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { |
|
query => $query, |
|
old_timestamp => $old_timestamp, |
|
}}); |
|
|
|
# Read in all interface RX and TX variables. |
|
foreach my $uuid (keys %{$anvil->data->{cache}{database_handle}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { |
|
uuid => $uuid, |
|
db_host => $anvil->Get->host_name_from_uuid({host_uuid => $uuid}), |
|
}}); |
|
my $queries = []; |
|
$query = " |
|
SELECT |
|
variable_uuid, |
|
variable_name |
|
FROM |
|
variables |
|
WHERE |
|
variable_name LIKE '%::tx_bytes' |
|
OR |
|
variable_name LIKE '%::rx_bytes' |
|
;"; |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $variable_uuid = $row->[0]; |
|
my $variable_name = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:variable_name' => $variable_name, |
|
's2:variable_uuid' => $variable_uuid, |
|
}}); |
|
|
|
# Find out of there are any records to remove at all. |
|
my $query = "SELECT history_id FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date <= '".$old_timestamp."';"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
|
|
if ($count) |
|
{ |
|
# Find how many records will be left. If it's 0, we'll use an OFFSET 1. |
|
my $query = "SELECT history_id FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date > '".$old_timestamp."';"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
if ($count) |
|
{ |
|
# At least one record will be left, we can do a simple delete. |
|
my $query = "DELETE FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date <= '".$old_timestamp."';"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$queries}, $query; |
|
} |
|
else |
|
{ |
|
# This would delete everything, reserve at least one record. |
|
foreach my $row (@{$results}) |
|
{ |
|
my $history_id = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { history_id => $history_id }}); |
|
|
|
my $query = "DELETE FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND history_id = '".$history_id."';"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$queries}, $query; |
|
} |
|
} |
|
} |
|
} |
|
|
|
my $commits = @{$queries}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { commits => $commits }}); |
|
if ($commits) |
|
{ |
|
# Commit the DELETEs. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_log_0001", variables => { |
|
age => $age, |
|
records => $commits, |
|
host => $anvil->Get->host_name_from_uuid({host_uuid => $uuid}), |
|
}}); |
|
$anvil->Database->write({debug => 2, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
undef $queries; |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This reads in all of the network data |
|
sub collect_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Read in data from Network Manager |
|
$anvil->Network->collect_data({debug => 2}); |
|
|
|
### TODO: We can get the IPs from collect_data, we should phase this out. |
|
# The 'local_host' is needed to pull data recorded by Network->get_ips(); |
|
$anvil->Network->get_ips({debug => 2}); |
|
my $local_host = $anvil->Get->short_host_name(); |
|
my $directory = "/sys/class/net"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
local_host => $local_host, |
|
directory => $directory, |
|
}}); |
|
|
|
### TODO: Convert this to use Sys::Virt |
|
# Make sure there are no virsh bridges, removing any found. |
|
my $host_type = $anvil->Get->host_type(); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); |
|
if (($host_type eq "node") or ($host_type eq "dr")) |
|
{ |
|
my $default_network = "/etc/libvirt/qemu/networks/default.xml"; |
|
if (-e $default_network) |
|
{ |
|
my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-destroy default"; |
|
$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, |
|
}}); |
|
|
|
$shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." net-undefine default"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
|
($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, |
|
}}); |
|
|
|
# Register an alert |
|
my $variables = { |
|
bridge => "default", |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0001", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0001", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
# Collect data from nmcli |
|
$anvil->Network->collect_data({debug => 2}); |
|
|
|
# Walk through the sysfs files. |
|
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) |
|
{ |
|
### NOTE: The 'interface' maps to the network manager 'GENERAL.IP-IFACE', which is |
|
### 'network_interface_device'. The 'network_interface_name' is the biosdevname. |
|
# 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, |
|
}}); |
|
|
|
# Try to find the nm_uuid |
|
my $nm_uuid = ""; |
|
if ((exists $anvil->data->{nmcli}{name}{$interface}) && ($anvil->data->{nmcli}{name}{$interface}{uuid})) |
|
{ |
|
$nm_uuid = $anvil->data->{nmcli}{name}{$interface}{uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { nm_uuid => $nm_uuid }}); |
|
} |
|
elsif ((exists $anvil->data->{nmcli}{device}{$interface}) && ($anvil->data->{nmcli}{device}{$interface}{uuid})) |
|
{ |
|
$nm_uuid = $anvil->data->{nmcli}{device}{$interface}{uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { nm_uuid => $nm_uuid }}); |
|
} |
|
|
|
my $nm_device = ""; # biosdevname |
|
my $nm_name = ""; # ip name |
|
if ($nm_uuid) |
|
{ |
|
$nm_device = $anvil->data->{nmcli}{uuid}{$nm_uuid}{device}; |
|
$nm_name = $anvil->data->{nmcli}{uuid}{$nm_uuid}{name}; |
|
} |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
nm_device => $nm_device, |
|
nm_name => $nm_name, |
|
}}); |
|
|
|
### NOTE: This only parses virtio so far. |
|
# Pick out our driver. |
|
if ($modalias =~ /^virtio:/) |
|
{ |
|
$driver = "virtio"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { driver => $driver }}); |
|
} |
|
|
|
# The MAC address can faked by a number of ways, so we make an explicit call to 'ethtool' to get the permanent 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_master = ""; |
|
|
|
# These are variables that will be needed if this is a bridge interface |
|
my $bridge_id = ""; |
|
my $bridge_stp_enabled = ""; |
|
|
|
# Explicitly check for the existing of the hash so that we don't auto-vivivate the interface. |
|
if (exists $anvil->data->{network}{$local_host}{interface}{$interface}) |
|
{ |
|
$ip_address = defined $anvil->data->{network}{$local_host}{interface}{$interface}{ip} ? $anvil->data->{network}{$local_host}{interface}{$interface}{ip} : ""; |
|
$subnet_mask = defined $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} ? $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} : ""; |
|
$type = defined $anvil->data->{network}{$local_host}{interface}{$interface}{type} ? $anvil->data->{network}{$local_host}{interface}{$interface}{type} : "interface"; |
|
$tx_bytes = defined $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes} ? $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes} : 0; |
|
$rx_bytes = defined $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes} ? $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes} : 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address => $ip_address, |
|
subnet_mask => $subnet_mask, |
|
type => $type, |
|
rx_bytes => $rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $rx_bytes}).")", |
|
tx_bytes => $tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $tx_bytes}).")", |
|
}}); |
|
} |
|
|
|
# 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 }}); |
|
} |
|
|
|
# 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"; |
|
$nm_uuid = $anvil->data->{nmcli}{bond}{$interface}{uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
type => $type, |
|
nm_uuid => $nm_uuid, |
|
}}); |
|
|
|
# Read the bond mode. |
|
$bond_mode = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/mode"}); |
|
$primary_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary"}); |
|
$primary_reselect = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/primary_reselect"}); |
|
$active_interface = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/active_slave"}); |
|
$mii_polling_interval = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/miimon"}); |
|
$up_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/updelay"}); |
|
$down_delay = $anvil->Storage->read_file({file => "/sys/devices/virtual/net/".$interface."/bonding/downdelay"}); |
|
$bond_mode =~ s/\s.*//; |
|
$bond_mode =~ s/\n$//; |
|
$primary_interface =~ s/\n$//; |
|
$primary_reselect =~ s/\s.*//; |
|
$primary_reselect =~ s/\n$//; |
|
$active_interface =~ s/\n$//; |
|
$mii_polling_interval =~ s/\n$//; |
|
$up_delay =~ s/\n$//; |
|
$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_master = ($target =~ /^.*\/(.*)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
target => $target, |
|
bond_master => $bond_master, |
|
}}); |
|
} |
|
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_stp_enabled = $anvil->Storage->read_file({debug => 3, file => $full_path."/bridge/stp_state"}); |
|
$bridge_id =~ s/\n$//; |
|
$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/) |
|
{ |
|
$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_master => $bond_master, |
|
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, |
|
}}); |
|
|
|
# If the MAC address starts with '52:54:00', we've got a virtio NIC. |
|
if ((not defined $speed) or ($speed eq "")) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0001", variables => { file => $full_path."/speed" }}); |
|
next; |
|
} |
|
if ($speed =~ /\D/) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0002", variables => { |
|
file => $full_path."/speed", |
|
speed => $speed, |
|
}}); |
|
next; |
|
} |
|
if ($speed > 100000) |
|
{ |
|
# NOTE: This is probably 0 now... Though someday >100 Gbps will be reasonable |
|
# and we'll need to change this. |
|
$speed = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { speed => $speed }}); |
|
} |
|
|
|
# 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; |
|
} |
|
} |
|
|
|
# Store new information we found. |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid} = $nm_uuid; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_device} = $nm_device; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{nm_name} = $nm_name; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{active_interface} = $active_interface; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode} = $bond_mode; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{bond_master} = $bond_master; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id} = $bridge_id; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{bridge_stp_enabled} = $bridge_stp_enabled; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{down_delay} = $down_delay; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{duplex} = $duplex; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{ip} = $ip_address; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{link_state} = $link_state; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{mac_address} = $mac_address; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{media} = $media; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{mii_polling_interval} = $mii_polling_interval; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{mtu} = $mtu; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{operational} = $operational; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{primary_reselect} = $primary_reselect; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{primary_interface} = $primary_interface; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{speed} = $speed; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask} = $subnet_mask; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{type} = $type; |
|
$anvil->data->{network}{$local_host}{interface}{$interface}{up_delay} = $up_delay; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"network::${local_host}::interface::${interface}::nm_uuid" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid}, |
|
"network::${local_host}::interface::${interface}::nm_device" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_device}, |
|
"network::${local_host}::interface::${interface}::nm_name" => $anvil->data->{network}{$local_host}{interface}{$interface}{nm_name}, |
|
"network::${local_host}::interface::${interface}::active_interface" => $anvil->data->{network}{$local_host}{interface}{$interface}{active_interface}, |
|
"network::${local_host}::interface::${interface}::bond_mode" => $anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode}, |
|
"network::${local_host}::interface::${interface}::bond_master" => $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master}, |
|
"network::${local_host}::interface::${interface}::bridge_id" => $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id}, |
|
"network::${local_host}::interface::${interface}::bridge_stp_enabled" => $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_stp_enabled}, |
|
"network::${local_host}::interface::${interface}::down_delay" => $anvil->data->{network}{$local_host}{interface}{$interface}{down_delay}, |
|
"network::${local_host}::interface::${interface}::duplex" => $anvil->data->{network}{$local_host}{interface}{$interface}{duplex}, |
|
"network::${local_host}::interface::${interface}::ip" => $anvil->data->{network}{$local_host}{interface}{$interface}{ip}, |
|
"network::${local_host}::interface::${interface}::link_state" => $anvil->data->{network}{$local_host}{interface}{$interface}{link_state}, |
|
"network::${local_host}::interface::${interface}::mac_address" => $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address}, |
|
"network::${local_host}::interface::${interface}::media" => $anvil->data->{network}{$local_host}{interface}{$interface}{media}, |
|
"network::${local_host}::interface::${interface}::mii_polling_interval" => $anvil->data->{network}{$local_host}{interface}{$interface}{mii_polling_interval}, |
|
"network::${local_host}::interface::${interface}::mtu" => $anvil->data->{network}{$local_host}{interface}{$interface}{mtu}, |
|
"network::${local_host}::interface::${interface}::operational" => $anvil->data->{network}{$local_host}{interface}{$interface}{operational}, |
|
"network::${local_host}::interface::${interface}::primary_reselect" => $anvil->data->{network}{$local_host}{interface}{$interface}{primary_reselect}, |
|
"network::${local_host}::interface::${interface}::primary_interface" => $anvil->data->{network}{$local_host}{interface}{$interface}{primary_interface}, |
|
"network::${local_host}::interface::${interface}::speed" => $anvil->data->{network}{$local_host}{interface}{$interface}{speed}, |
|
"network::${local_host}::interface::${interface}::subnet_mask" => $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask}, |
|
"network::${local_host}::interface::${interface}::type" => $anvil->data->{network}{$local_host}{interface}{$interface}{type}, |
|
"network::${local_host}::interface::${interface}::up_delay" => $anvil->data->{network}{$local_host}{interface}{$interface}{up_delay}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"network::${local_host}::interface::${interface}::link_state" => $anvil->data->{network}{$local_host}{interface}{$interface}{link_state}, |
|
"network::${local_host}::interface::${interface}::operational" => $anvil->data->{network}{$local_host}{interface}{$interface}{operational}, |
|
}}); |
|
|
|
# If this is a link and there's no database connections, cache the data. |
|
if (($type eq "interface") && (not $anvil->data->{sys}{database}{connections})) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
nm_name => $nm_name, |
|
nm_device => $nm_device, |
|
}}); |
|
# nm_device,timestamp,mac_address,speed,link_state,operational,nm_uuid,nm_name |
|
$anvil->data->{cache}{new_file} .= $nm_device.",".$anvil->Database->refresh_timestamp.",".$mac_address.",".$speed.",".$link_state.",".$operational.",".$nm_uuid.",".$nm_name."\n"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"cache::new_file" => $anvil->data->{cache}{new_file}, |
|
}}); |
|
} |
|
} |
|
} |
|
closedir(DIRECTORY); |
|
|
|
# Find what interfaces are connected to which bridges |
|
$anvil->Network->bridge_info({debug => 2}); |
|
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$local_host}{interface}}) |
|
{ |
|
my $ip_address = $anvil->data->{network}{$local_host}{interface}{$interface}{ip}; |
|
my $type = $anvil->data->{network}{$local_host}{interface}{$interface}{type}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
interface => $interface, |
|
ip_address => $ip_address, |
|
type => $type, |
|
}}); |
|
|
|
$anvil->data->{interface}{name_to_type}{$interface} = $type; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"interface::name_to_type::${interface}" => $anvil->data->{interface}{name_to_type}{$interface}, |
|
}}); |
|
|
|
if ($type eq "bridge") |
|
{ |
|
# Store the bridge |
|
$anvil->data->{new}{bridge}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid}; |
|
$anvil->data->{new}{bridge}{$interface}{id} = $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_id}; |
|
$anvil->data->{new}{bridge}{$interface}{mac_address} = $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address}; |
|
$anvil->data->{new}{bridge}{$interface}{mtu} = $anvil->data->{network}{$local_host}{interface}{$interface}{mtu}; |
|
$anvil->data->{new}{bridge}{$interface}{stp_enabled} = $anvil->data->{network}{$local_host}{interface}{$interface}{bridge_stp_enabled}; |
|
$anvil->data->{new}{bridge}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes}; |
|
$anvil->data->{new}{bridge}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::bridge::${interface}::nm_uuid" => $anvil->data->{new}{bridge}{$interface}{nm_uuid}, |
|
"new::bridge::${interface}::id" => $anvil->data->{new}{bridge}{$interface}{id}, |
|
"new::bridge::${interface}::mac_address" => $anvil->data->{new}{bridge}{$interface}{mac_address}, |
|
"new::bridge::${interface}::mtu" => $anvil->data->{new}{bridge}{$interface}{mtu}, |
|
"new::bridge::${interface}::stp_enabled" => $anvil->data->{new}{bridge}{$interface}{stp_enabled}, |
|
"new::bridge::${interface}::tx_bytes" => $anvil->data->{new}{bridge}{$interface}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{bridge}{$interface}{tx_bytes}}).")", |
|
"new::bridge::${interface}::rx_bytes" => $anvil->data->{new}{bridge}{$interface}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{bridge}{$interface}{rx_bytes}}).")", |
|
}}); |
|
} |
|
elsif ($type eq "bond") |
|
{ |
|
# Store the bond |
|
$anvil->data->{new}{bond}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid}; |
|
$anvil->data->{new}{bond}{$interface}{mode} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode}; |
|
$anvil->data->{new}{bond}{$interface}{mtu} = $anvil->data->{network}{$local_host}{interface}{$interface}{mtu}; |
|
$anvil->data->{new}{bond}{$interface}{master} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master}; |
|
$anvil->data->{new}{bond}{$interface}{link_state} = $anvil->data->{network}{$local_host}{interface}{$interface}{link_state}; |
|
$anvil->data->{new}{bond}{$interface}{operational} = $anvil->data->{network}{$local_host}{interface}{$interface}{operational}; |
|
$anvil->data->{new}{bond}{$interface}{mac_address} = $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address}; |
|
$anvil->data->{new}{bond}{$interface}{primary_interface} = $anvil->data->{network}{$local_host}{interface}{$interface}{primary_interface}; |
|
$anvil->data->{new}{bond}{$interface}{primary_reselect} = $anvil->data->{network}{$local_host}{interface}{$interface}{primary_reselect}; |
|
$anvil->data->{new}{bond}{$interface}{active_interface} = $anvil->data->{network}{$local_host}{interface}{$interface}{active_interface}; |
|
$anvil->data->{new}{bond}{$interface}{mii_polling_interval} = $anvil->data->{network}{$local_host}{interface}{$interface}{mii_polling_interval}; |
|
$anvil->data->{new}{bond}{$interface}{up_delay} = $anvil->data->{network}{$local_host}{interface}{$interface}{up_delay}; |
|
$anvil->data->{new}{bond}{$interface}{down_delay} = $anvil->data->{network}{$local_host}{interface}{$interface}{down_delay}; |
|
$anvil->data->{new}{bond}{$interface}{bridge_uuid} = ""; # We'll dig his out later as the bridge might not be in the database yet. |
|
$anvil->data->{new}{bond}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes}; |
|
$anvil->data->{new}{bond}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::bond::${interface}::nm_uuid" => $anvil->data->{new}{bond}{$interface}{nm_uuid}, |
|
"new::bond::${interface}::mode" => $anvil->data->{new}{bond}{$interface}{mode}, |
|
"new::bond::${interface}::mtu" => $anvil->data->{new}{bond}{$interface}{mtu}, |
|
"new::bond::${interface}::master" => $anvil->data->{new}{bond}{$interface}{master}, |
|
"new::bond::${interface}::link_state" => $anvil->data->{new}{bond}{$interface}{link_state}, |
|
"new::bond::${interface}::operational" => $anvil->data->{new}{bond}{$interface}{operational}, |
|
"new::bond::${interface}::mac_address" => $anvil->data->{new}{bond}{$interface}{mac_address}, |
|
"new::bond::${interface}::primary_interface" => $anvil->data->{new}{bond}{$interface}{primary_interface}, |
|
"new::bond::${interface}::primary_reselect" => $anvil->data->{new}{bond}{$interface}{primary_reselect}, |
|
"new::bond::${interface}::active_interface" => $anvil->data->{new}{bond}{$interface}{active_interface}, |
|
"new::bond::${interface}::mii_polling_interval" => $anvil->data->{new}{bond}{$interface}{mii_polling_interval}, |
|
"new::bond::${interface}::up_delay" => $anvil->data->{new}{bond}{$interface}{up_delay}, |
|
"new::bond::${interface}::down_delay" => $anvil->data->{new}{bond}{$interface}{down_delay}, |
|
"new::bond::${interface}::bridge_uuid" => $anvil->data->{new}{bond}{$interface}{bridge_uuid}, |
|
"new::bond::${interface}::tx_bytes" => $anvil->data->{new}{bond}{$interface}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{bond}{$interface}{tx_bytes}}).")", |
|
"new::bond::${interface}::rx_bytes" => $anvil->data->{new}{bond}{$interface}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{bond}{$interface}{rx_bytes}}).")", |
|
}}); |
|
} |
|
elsif ($type eq "interface") |
|
{ |
|
# Store the interface |
|
$anvil->data->{new}{interface}{$interface}{nm_uuid} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_uuid}; |
|
$anvil->data->{new}{interface}{$interface}{nm_device} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_device}; |
|
$anvil->data->{new}{interface}{$interface}{nm_name} = $anvil->data->{network}{$local_host}{interface}{$interface}{nm_name}; |
|
$anvil->data->{new}{interface}{$interface}{bond_uuid} = ""; |
|
$anvil->data->{new}{interface}{$interface}{bond_name} = $anvil->data->{network}{$local_host}{interface}{$interface}{bond_master}; |
|
$anvil->data->{new}{interface}{$interface}{bridge_uuid} = ""; |
|
$anvil->data->{new}{interface}{$interface}{bridge_name} = ""; |
|
$anvil->data->{new}{interface}{$interface}{duplex} = $anvil->data->{network}{$local_host}{interface}{$interface}{duplex}; |
|
$anvil->data->{new}{interface}{$interface}{link_state} = $anvil->data->{network}{$local_host}{interface}{$interface}{link_state}; |
|
$anvil->data->{new}{interface}{$interface}{operational} = $anvil->data->{network}{$local_host}{interface}{$interface}{operational}; |
|
$anvil->data->{new}{interface}{$interface}{mac_address} = $anvil->data->{network}{$local_host}{interface}{$interface}{mac_address}; |
|
$anvil->data->{new}{interface}{$interface}{medium} = $anvil->data->{network}{$local_host}{interface}{$interface}{media}; |
|
$anvil->data->{new}{interface}{$interface}{mtu} = $anvil->data->{network}{$local_host}{interface}{$interface}{mtu}; |
|
$anvil->data->{new}{interface}{$interface}{speed} = $anvil->data->{network}{$local_host}{interface}{$interface}{speed}; |
|
$anvil->data->{new}{interface}{$interface}{tx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{tx_bytes}; |
|
$anvil->data->{new}{interface}{$interface}{rx_bytes} = $anvil->data->{network}{$local_host}{interface}{$interface}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::interface::${interface}::nm_uuid" => $anvil->data->{new}{interface}{$interface}{nm_uuid}, |
|
"new::interface::${interface}::nm_device" => $anvil->data->{new}{interface}{$interface}{nm_device}, |
|
"new::interface::${interface}::nm_name" => $anvil->data->{new}{interface}{$interface}{nm_name}, |
|
"new::interface::${interface}::bond_uuid" => $anvil->data->{new}{interface}{$interface}{bond_uuid}, |
|
"new::interface::${interface}::bond_name" => $anvil->data->{new}{interface}{$interface}{bond_name}, |
|
"new::interface::${interface}::bridge_uuid" => $anvil->data->{new}{interface}{$interface}{bridge_uuid}, |
|
"new::interface::${interface}::bridge_name" => $anvil->data->{new}{interface}{$interface}{bridge_name}, |
|
"new::interface::${interface}::duplex" => $anvil->data->{new}{interface}{$interface}{duplex}, |
|
"new::interface::${interface}::link_state" => $anvil->data->{new}{interface}{$interface}{link_state}, |
|
"new::interface::${interface}::operational" => $anvil->data->{new}{interface}{$interface}{operational}, |
|
"new::interface::${interface}::mac_address" => $anvil->data->{new}{interface}{$interface}{mac_address}, |
|
"new::interface::${interface}::medium" => $anvil->data->{new}{interface}{$interface}{medium}, |
|
"new::interface::${interface}::mtu" => $anvil->data->{new}{interface}{$interface}{mtu}, |
|
"new::interface::${interface}::speed" => $anvil->data->{new}{interface}{$interface}{speed}, |
|
"new::interface::${interface}::tx_bytes" => $anvil->data->{new}{interface}{$interface}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{interface}{$interface}{tx_bytes}}).")", |
|
"new::interface::${interface}::rx_bytes" => $anvil->data->{new}{interface}{$interface}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{new}{interface}{$interface}{rx_bytes}}).")", |
|
}}); |
|
} |
|
|
|
# Record the IP address info. |
|
if ($ip_address) |
|
{ |
|
$anvil->data->{new}{ip_address}{$ip_address}{on_interface} = $interface; |
|
$anvil->data->{new}{ip_address}{$ip_address}{subnet_mask} = $anvil->data->{network}{$local_host}{interface}{$interface}{subnet_mask}; |
|
$anvil->data->{new}{ip_address}{$ip_address}{gateway} = $anvil->data->{network}{$local_host}{interface}{$interface}{gateway}; |
|
$anvil->data->{new}{ip_address}{$ip_address}{default_gateway} = $anvil->data->{network}{$local_host}{interface}{$interface}{default_gateway}; |
|
$anvil->data->{new}{ip_address}{$ip_address}{dns} = $anvil->data->{network}{$local_host}{interface}{$interface}{dns}; |
|
$anvil->data->{new}{ip_address}{$ip_address}{on_uuid} = ""; |
|
$anvil->data->{new}{ip_address}{$ip_address}{note} = ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::ip_address::${ip_address}::on_interface" => $anvil->data->{new}{ip_address}{$ip_address}{on_interface}, |
|
"new::ip_address::${ip_address}::subnet_mask" => $anvil->data->{new}{ip_address}{$ip_address}{subnet_mask}, |
|
"new::ip_address::${ip_address}::gateway" => $anvil->data->{new}{ip_address}{$ip_address}{gateway}, |
|
"new::ip_address::${ip_address}::default_gateway" => $anvil->data->{new}{ip_address}{$ip_address}{default_gateway}, |
|
"new::ip_address::${ip_address}::dns" => $anvil->data->{new}{ip_address}{$ip_address}{dns}, |
|
"new::ip_address::${ip_address}::on_uuid" => $anvil->data->{new}{ip_address}{$ip_address}{on_uuid}, |
|
"new::ip_address::${ip_address}::note" => $anvil->data->{new}{ip_address}{$ip_address}{note}, |
|
}}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This reads in the states from the last can |
|
sub read_last_scan |
|
{ |
|
my ($anvil) = @_; |
|
|
|
### NOTE: There is a bug somewhere where interfaces are periodically being added twice per host. This |
|
### checks for / cleans those up. Remove this when the core issue is resolved. |
|
clear_duplicates($anvil); |
|
|
|
# Read in the old bridge data. |
|
load_bridge_data($anvil); |
|
load_bond_data($anvil); |
|
load_interface_data($anvil); |
|
load_ip_address_data($anvil); |
|
|
|
return(0); |
|
} |
|
|
|
# There is a bug somewhere where interfaces, bridges and ip addresses are periodically being added twice per |
|
# host. This checks for / cleans those up. Remove this when the core issue is resolved. |
|
sub clear_duplicates |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Look for duplicate bridges. |
|
my $query = " |
|
SELECT |
|
bridge_uuid, |
|
bridge_name, |
|
bridge_id, |
|
bridge_mac_address |
|
FROM |
|
bridges |
|
WHERE |
|
bridge_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
ORDER BY |
|
bridge_name ASC, |
|
bridge_id DESC |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bridge_uuid = $row->[0]; |
|
my $bridge_name = $row->[1]; |
|
my $bridge_id = $row->[2]; |
|
my $bridge_mac_address = $row->[3]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_uuid => $bridge_uuid, |
|
bridge_name => $bridge_name, |
|
bridge_id => $bridge_id, |
|
bridge_mac_address => $bridge_mac_address, |
|
}}); |
|
|
|
if (not exists $anvil->data->{duplicate_bridges}{seen}{$bridge_name}) |
|
{ |
|
$anvil->data->{duplicate_bridges}{seen}{$bridge_name} = []; |
|
} |
|
push @{$anvil->data->{duplicate_bridges}{seen}{$bridge_name}}, $bridge_uuid; |
|
|
|
$anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_name} = $bridge_name; |
|
$anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address} = $bridge_mac_address; |
|
$anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_id} = $bridge_id; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_bridges::bridge_uuid::${bridge_uuid}::bridge_name" => $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_name}, |
|
"duplicate_bridges::bridge_uuid::${bridge_uuid}::bridge_id" => $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}, |
|
"duplicate_bridges::bridge_uuid::${bridge_uuid}::bridge_mac_address" => $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address}, |
|
}}); |
|
|
|
$anvil->data->{deleted_bridges}{$bridge_uuid} = 0; |
|
} |
|
foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{duplicate_bridges}{seen}}) |
|
{ |
|
my $count = @{$anvil->data->{duplicate_bridges}{seen}{$bridge_name}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:bridge_name' => $bridge_name, |
|
's2:count' => $count, |
|
}}); |
|
|
|
if ($count > 1) |
|
{ |
|
# Duplicate! Is one of them marked as DELETED? |
|
foreach my $bridge_uuid (@{$anvil->data->{duplicate_bridges}{seen}{$bridge_name}}) |
|
{ |
|
# Is this one deleted? |
|
my $bridge_mac_address = $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address}; |
|
my $bridge_id = $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_uuid => $bridge_uuid, |
|
bridge_mac_address => $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address}, |
|
bridge_id => $anvil->data->{duplicate_bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}, |
|
}}); |
|
if ($bridge_id eq "DELETED") |
|
{ |
|
# Take this one out. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0685", variables => { |
|
name => $bridge_name, |
|
uuid => $bridge_uuid, |
|
}}); |
|
|
|
# If there's a bond connected to this bridge, get it's bond_uuid so |
|
# we can remove any interfaces linked to it. |
|
my $bond_uuid = ""; |
|
my $query = "SELECT bond_uuid FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
if ($count) |
|
{ |
|
$bond_uuid = $results->[0]->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); |
|
} |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
if ($bond_uuid) |
|
{ |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
} |
|
push @{$queries}, "DELETE FROM history.bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM history.bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
|
|
# Write it out. |
|
$anvil->Database->write({debug => 2, query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
|
|
$anvil->data->{deleted_bridges}{$bridge_uuid} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"deleted_bridges::${bridge_uuid}" => $anvil->data->{deleted_bridges}{$bridge_uuid}, |
|
}}); |
|
} |
|
last if $count == 1; |
|
} |
|
|
|
# If count is still > 1, we need to arbitrarily delete an interface. |
|
if ($count > 1) |
|
{ |
|
foreach my $bridge_uuid (@{$anvil->data->{duplicate_bridges}{seen}{$bridge_name}}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0685", variables => { |
|
name => $bridge_name, |
|
uuid => $bridge_uuid, |
|
}}); |
|
|
|
# If there's a bond connected to this bridge, get it's bond_uuid so |
|
# we can remove any interfaces linked to it. |
|
my $bond_uuid = ""; |
|
my $query = "SELECT bond_uuid FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
if ($count) |
|
{ |
|
$bond_uuid = $results->[0]->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); |
|
} |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
if ($bond_uuid) |
|
{ |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
} |
|
push @{$queries}, "DELETE FROM history.bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM bonds WHERE bond_bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM history.bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
push @{$queries}, "DELETE FROM bridges WHERE bridge_uuid = ".$anvil->Database->quote($bridge_uuid).";"; |
|
|
|
# Write it out. |
|
$anvil->Database->write({debug => 2, query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
|
|
$anvil->data->{deleted_bridges}{$bridge_uuid} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"deleted_bridges::${bridge_uuid}" => $anvil->data->{deleted_bridges}{$bridge_uuid}, |
|
}}); |
|
} |
|
last if $count == 1; |
|
} |
|
} |
|
} |
|
delete $anvil->data->{duplicate_bridges}; |
|
|
|
# Load the bridges again. |
|
$anvil->Database->get_bridges({include_deleted => 1}); |
|
|
|
# Look for duplicate bonds. |
|
$query = " |
|
SELECT |
|
bond_uuid, |
|
bond_name, |
|
bond_operational, |
|
bond_mac_address, |
|
bond_bridge_uuid |
|
FROM |
|
bonds |
|
WHERE |
|
bond_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
ORDER BY |
|
bond_name ASC, |
|
bond_operational DESC |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bond_uuid = $row->[0]; |
|
my $bond_name = $row->[1]; |
|
my $bond_operational = $row->[2]; |
|
my $bond_mac_address = $row->[3]; |
|
my $bond_bridge_uuid = defined $row->[4] ? $row->[4] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bond_uuid => $bond_uuid, |
|
bond_name => $bond_name, |
|
bond_operational => $bond_operational, |
|
bond_mac_address => $bond_mac_address, |
|
bond_bridge_uuid => $bond_bridge_uuid, |
|
}}); |
|
|
|
if (not exists $anvil->data->{duplicate_bonds}{seen}{$bond_name}) |
|
{ |
|
$anvil->data->{duplicate_bonds}{seen}{$bond_name} = []; |
|
} |
|
push @{$anvil->data->{duplicate_bonds}{seen}{$bond_name}}, $bond_uuid; |
|
|
|
$anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_name} = $bond_name; |
|
$anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_mac_address} = $bond_mac_address; |
|
$anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_operational} = $bond_operational; |
|
$anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid} = $bond_bridge_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_bonds::bond_uuid::${bond_uuid}::bond_name" => $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_name}, |
|
"duplicate_bonds::bond_uuid::${bond_uuid}::bond_operational" => $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_operational}, |
|
"duplicate_bonds::bond_uuid::${bond_uuid}::bond_mac_address" => $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_mac_address}, |
|
"duplicate_bonds::bond_uuid::${bond_uuid}::bond_bridge_uuid" => $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid}, |
|
}}); |
|
|
|
$anvil->data->{deleted_bonds}{$bond_uuid} = 0; |
|
} |
|
foreach my $bond_name (sort {$a cmp $b} keys %{$anvil->data->{duplicate_bonds}{seen}}) |
|
{ |
|
my $count = @{$anvil->data->{duplicate_bonds}{seen}{$bond_name}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:bond_name' => $bond_name, |
|
's2:count' => $count, |
|
}}); |
|
|
|
if ($count > 1) |
|
{ |
|
# Duplicate! Is one of them marked as DELETED? |
|
foreach my $bond_uuid (@{$anvil->data->{duplicate_bonds}{seen}{$bond_name}}) |
|
{ |
|
# Is this one deleted? |
|
my $bond_mac_address = $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_mac_address}; |
|
my $bond_operational = $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_operational}; |
|
my $bond_bridge_uuid = $anvil->data->{duplicate_bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bond_uuid => $bond_uuid, |
|
bond_mac_address => $bond_mac_address, |
|
bond_operational => $bond_operational, |
|
bond_bridge_uuid => $bond_bridge_uuid, |
|
}}); |
|
if ((($bond_bridge_uuid) && ($anvil->data->{deleted_bridges}{$bond_bridge_uuid})) or ($bond_operational eq "DELETED")) |
|
{ |
|
# Take this one out. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0685", variables => { |
|
name => $bond_name, |
|
uuid => $bond_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM history.bonds WHERE bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM bonds WHERE bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
|
|
# Write it out. |
|
$anvil->Database->write({debug => 2, query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
|
|
$anvil->data->{deleted_bonds}{$bond_uuid} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"deleted_bonds::${bond_uuid}" => $anvil->data->{deleted_bonds}{$bond_uuid}, |
|
}}); |
|
} |
|
} |
|
|
|
# If count is still > 1, we need to arbitrarily delete an interface. |
|
if ($count > 1) |
|
{ |
|
foreach my $bond_uuid (@{$anvil->data->{duplicate_bonds}{seen}{$bond_name}}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0685", variables => { |
|
name => $bond_name, |
|
uuid => $bond_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM history.bonds WHERE bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
push @{$queries}, "DELETE FROM bonds WHERE bond_uuid = ".$anvil->Database->quote($bond_uuid).";"; |
|
|
|
# Write it out. |
|
$anvil->Database->write({debug => 2, query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
|
|
$anvil->data->{deleted_bonds}{$bond_uuid} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"deleted_bonds::${bond_uuid}" => $anvil->data->{deleted_bonds}{$bond_uuid}, |
|
}}); |
|
} |
|
last if $count == 1; |
|
} |
|
} |
|
} |
|
delete $anvil->data->{duplicate_bonds}; |
|
|
|
|
|
# Look for duplicate network interfaces |
|
$query = " |
|
SELECT |
|
network_interface_uuid, |
|
network_interface_name, |
|
network_interface_mac_address, |
|
network_interface_operational, |
|
network_interface_bond_uuid, |
|
network_interface_bridge_uuid |
|
FROM |
|
network_interfaces |
|
WHERE |
|
network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
ORDER BY |
|
network_interface_name ASC |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $network_interface_uuid = $row->[0]; |
|
my $network_interface_name = $row->[1]; |
|
my $network_interface_mac_address = $row->[2]; |
|
my $network_interface_operational = $row->[3]; |
|
my $network_interface_bond_uuid = defined $row->[4] ? $row->[4] : ""; |
|
my $network_interface_bridge_uuid = defined $row->[5] ? $row->[5] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network_interface_uuid => $network_interface_uuid, |
|
network_interface_name => $network_interface_name, |
|
network_interface_mac_address => $network_interface_mac_address, |
|
network_interface_operational => $network_interface_operational, |
|
network_interface_bond_uuid => $network_interface_bond_uuid, |
|
network_interface_bridge_uuid => $network_interface_bridge_uuid, |
|
}}); |
|
|
|
if (not exists $anvil->data->{duplicate_nics}{seen}{$network_interface_name}) |
|
{ |
|
$anvil->data->{duplicate_nics}{seen}{$network_interface_name} = []; |
|
} |
|
push @{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}}, $network_interface_uuid; |
|
|
|
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_name; |
|
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address} = $network_interface_mac_address; |
|
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $network_interface_operational; |
|
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = $network_interface_bond_uuid; |
|
$anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = $network_interface_bridge_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_name" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_name}, |
|
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_mac_address" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address}, |
|
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_operational" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational}, |
|
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_bond_uuid" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid}, |
|
"duplicate_nics::network_interface_uuid::${network_interface_uuid}::network_interface_bridge_uuid" => $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid}, |
|
}}); |
|
} |
|
foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{duplicate_nics}{seen}}) |
|
{ |
|
my $count = @{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:network_interface_name' => $network_interface_name, |
|
's2:count' => $count, |
|
}}); |
|
|
|
if ($count > 1) |
|
{ |
|
# Duplicate! Is one of them marked as DELETED? |
|
foreach my $network_interface_uuid (@{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}}) |
|
{ |
|
# Is this one deleted? |
|
my $network_interface_mac_address = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address}; |
|
my $network_interface_operational = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational}; |
|
my $network_interface_bond_uuid = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid}; |
|
my $network_interface_bridge_uuid = $anvil->data->{duplicate_nics}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network_interface_uuid => $network_interface_uuid, |
|
network_interface_mac_address => $network_interface_mac_address, |
|
network_interface_operational => $network_interface_operational, |
|
network_interface_bond_uuid => $network_interface_bond_uuid, |
|
network_interface_bridge_uuid => $network_interface_bridge_uuid, |
|
}}); |
|
if ((($network_interface_bond_uuid) && ($anvil->data->{deleted_bonds}{$network_interface_bond_uuid})) or |
|
(($network_interface_bridge_uuid) && ($anvil->data->{deleted_bridges}{$network_interface_bridge_uuid})) or |
|
($network_interface_operational eq "DELETED")) |
|
{ |
|
# Take this one out. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0647", variables => { |
|
name => $network_interface_name, |
|
uuid => $network_interface_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
} |
|
} |
|
|
|
# If count is still > 1, we need to arbitrarily delete an interface. |
|
if ($count > 1) |
|
{ |
|
foreach my $network_interface_uuid (@{$anvil->data->{duplicate_nics}{seen}{$network_interface_name}}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0647", variables => { |
|
name => $network_interface_name, |
|
uuid => $network_interface_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";"; |
|
push @{$queries}, "DELETE FROM network_interfaces WHERE network_interface_uuid = ".$anvil->Database->quote($network_interface_uuid).";"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
} |
|
last if $count == 1; |
|
} |
|
} |
|
} |
|
|
|
delete $anvil->data->{duplicate_nics}; |
|
|
|
$query = " |
|
SELECT |
|
ip_address_uuid, |
|
ip_address_address, |
|
ip_address_note |
|
FROM |
|
ip_addresses |
|
WHERE |
|
ip_address_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
ORDER BY |
|
ip_address_address ASC |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $ip_address_uuid = $row->[0]; |
|
my $ip_address_address = $row->[1]; |
|
my $ip_address_note = $row->[2]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address_uuid => $ip_address_uuid, |
|
ip_address_address => $ip_address_address, |
|
ip_address_note => $ip_address_note, |
|
}}); |
|
|
|
if (not exists $anvil->data->{duplicate_ips}{seen}{$ip_address_address}) |
|
{ |
|
$anvil->data->{duplicate_ips}{seen}{$ip_address_address} = []; |
|
} |
|
push @{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}}, $ip_address_uuid; |
|
|
|
$anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_address} = $ip_address_address; |
|
$anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} = $ip_address_note; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_ips::ip_address_uuid::${ip_address_uuid}::ip_address_address" => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_address}, |
|
"duplicate_ips::ip_address_uuid::${ip_address_uuid}::ip_address_note" => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note}, |
|
}}); |
|
} |
|
foreach my $ip_address_address (sort {$a cmp $b} keys %{$anvil->data->{duplicate_ips}{seen}}) |
|
{ |
|
my $count = @{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:ip_address_address' => $ip_address_address, |
|
's2:count' => $count, |
|
}}); |
|
|
|
if ($count > 1) |
|
{ |
|
# Duplicate! Is one of them marked as DELETED? |
|
foreach my $ip_address_uuid (@{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}}) |
|
{ |
|
# Is this one deleted? |
|
my $ip_address_note = $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address_uuid => $ip_address_uuid, |
|
ip_address_note => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note}, |
|
}}); |
|
if ($ip_address_note eq "DELETED") |
|
{ |
|
# Take this one out. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0664", variables => { |
|
ip => $ip_address_address, |
|
uuid => $ip_address_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";"; |
|
push @{$queries}, "DELETE FROM ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
} |
|
last if $count == 1; |
|
} |
|
|
|
# If count is still > 1, we need to arbitrarily delete an interface. |
|
if ($count > 1) |
|
{ |
|
foreach my $ip_address_uuid (@{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0664", variables => { |
|
ip => $ip_address_address, |
|
uuid => $ip_address_uuid, |
|
}}); |
|
|
|
my $queries = []; |
|
push @{$queries}, "DELETE FROM history.ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";"; |
|
push @{$queries}, "DELETE FROM ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";"; |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
|
|
$count--; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); |
|
} |
|
last if $count == 1; |
|
} |
|
} |
|
} |
|
|
|
|
|
return(0); |
|
} |
|
|
|
sub load_ip_address_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Now record the IPs. |
|
my $query = " |
|
SELECT |
|
ip_address_uuid, |
|
ip_address_on_type, |
|
ip_address_on_uuid, |
|
ip_address_address, |
|
ip_address_subnet_mask, |
|
ip_address_gateway, |
|
ip_address_default_gateway, |
|
ip_address_dns, |
|
ip_address_note |
|
FROM |
|
ip_addresses |
|
WHERE |
|
ip_address_host_uuid = ".$anvil->Database->quote($anvil->data->{sys}{host_uuid})." |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $ip_address_uuid = $row->[0]; |
|
my $ip_address_on_type = $row->[1]; |
|
my $ip_address_address = $row->[3]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address_uuid => $ip_address_uuid, |
|
ip_address_on_type => $ip_address_on_type, |
|
ip_address_address => $ip_address_address, |
|
}}); |
|
|
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_type} = $ip_address_on_type; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_uuid} = $row->[2]; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_address} = $ip_address_address; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_subnet_mask} = $row->[4]; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_gateway} = $row->[5]; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_default_gateway} = $row->[6]; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_dns} = $row->[7]; |
|
$anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} = $row->[8]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_on_type" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_type}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_on_uuid" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_uuid}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_address" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_address}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_subnet_mask" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_subnet_mask}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_gateway" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_gateway}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_default_gateway" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_default_gateway}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_dns" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_dns}, |
|
"old::ip_addresses::ip_address_uuid::${ip_address_uuid}::ip_address_note" => $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note}, |
|
}}); |
|
|
|
$anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address_address} = $ip_address_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::ip_addresses::ip_to_uuid::${ip_address_address}" => $anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address_address}, |
|
}}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub load_interface_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Process interfaces |
|
my $query = " |
|
SELECT |
|
network_interface_uuid, |
|
network_interface_nm_uuid, |
|
network_interface_mac_address, |
|
network_interface_name, |
|
network_interface_device, |
|
network_interface_speed, |
|
network_interface_mtu, |
|
network_interface_link_state, |
|
network_interface_operational, |
|
network_interface_duplex, |
|
network_interface_medium, |
|
network_interface_bond_uuid, |
|
network_interface_bridge_uuid |
|
FROM |
|
network_interfaces |
|
WHERE |
|
network_interface_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
|
|
foreach my $row (@{$results}) |
|
{ |
|
my $network_interface_uuid = $row->[0]; |
|
my $network_interface_mac_address = $row->[2]; |
|
my $network_interface_name = $row->[3]; |
|
my $network_interface_device = $row->[4]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network_interface_uuid => $network_interface_uuid, |
|
network_interface_mac_address => $network_interface_mac_address, |
|
network_interface_name => $network_interface_name, |
|
network_interface_device => $network_interface_device, |
|
}}); |
|
|
|
# Read in the RX/TX values, set to '0' if not found. |
|
my ($rx_bytes, $rx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
variable_name => "network_interface::".$network_interface_name."::rx_bytes", |
|
variable_source_uuid => $network_interface_uuid, |
|
variable_source_table => "network_interfaces", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
rx_bytes => $rx_bytes, |
|
rx_variable_uuid => $rx_variable_uuid, |
|
}}); |
|
(my $tx_bytes, my $tx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
variable_name => "network_interface::".$network_interface_name."::tx_bytes", |
|
variable_source_uuid => $network_interface_uuid, |
|
variable_source_table => "network_interfaces", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
tx_bytes => $tx_bytes, |
|
tx_variable_uuid => $tx_variable_uuid, |
|
}}); |
|
|
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_nm_uuid} = $row->[1]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address} = $network_interface_mac_address; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name} = $network_interface_name; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device} = $network_interface_device; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed} = $row->[5]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu} = $row->[6]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state} = $row->[7]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $row->[8]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex} = $row->[9]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium} = $row->[10]; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = defined $row->[11] ? $row->[11] : ''; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = defined $row->[12] ? $row->[12] : ''; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes} = $rx_bytes =~ /^\d+$/ ? $rx_bytes : 0; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid} = $rx_variable_uuid; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes} = $tx_bytes =~ /^\d+$/ ? $tx_bytes : 0; |
|
$anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid} = $tx_variable_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_nm_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_nm_uuid}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_mac_address" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_name" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_device" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_speed" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_mtu" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_link_state" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_operational" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_duplex" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_medium" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_bond_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::network_interface_bridge_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::rx_bytes" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes}}).")", |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::rx_variable_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid}, |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::tx_bytes" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes}}).")", |
|
"old::network_interfaces::network_interface_uuid::${network_interface_uuid}::tx_variable_uuid" => $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid}, |
|
}}); |
|
|
|
$anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; |
|
$anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_device} = $network_interface_uuid; |
|
$anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid} = $network_interface_name; |
|
$anvil->data->{network_interfaces}{mac_to_uuid}{$network_interface_mac_address} = $network_interface_uuid; |
|
$anvil->data->{interface}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; |
|
$anvil->data->{interface}{device_to_uuid}{$network_interface_device} = $network_interface_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"network_interfaces::name_to_uuid::${network_interface_name}" => $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name}, |
|
"network_interfaces::device_to_uuid::${network_interface_device}" => $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_device}, |
|
"network_interfaces::uuid_to_name::${network_interface_name}" => $anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid}, |
|
"network_interfaces::mac_to_uuid::${network_interface_mac_address}" => $anvil->data->{network_interfaces}{mac_to_uuid}{$network_interface_mac_address}, |
|
"interface::name_to_uuid::${network_interface_name}" => $anvil->data->{interface}{name_to_uuid}{$network_interface_name}, |
|
"interface::device_to_uuid::${network_interface_device}" => $anvil->data->{interface}{device_to_uuid}{$network_interface_device}, |
|
}}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub load_bond_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# 'bond_mode' will be 'DELETED' if the bond was removed. |
|
my $query = " |
|
SELECT |
|
bond_uuid, |
|
bond_name, |
|
bond_mode, |
|
bond_mtu, |
|
bond_primary_interface, |
|
bond_primary_reselect, |
|
bond_active_interface, |
|
bond_mii_polling_interval, |
|
bond_up_delay, |
|
bond_down_delay, |
|
bond_mac_address, |
|
bond_operational, |
|
bond_bridge_uuid |
|
FROM |
|
bonds |
|
WHERE |
|
bond_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bond_uuid = $row->[0]; |
|
my $bond_name = $row->[1]; |
|
my $bond_bridge_uuid = defined $row->[12] ? $row->[12] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bond_uuid => $bond_uuid, |
|
bond_name => $bond_name, |
|
bond_bridge_uuid => $bond_bridge_uuid, |
|
}}); |
|
|
|
# Read in the RX/TX values, set to '0' if not found. |
|
my ($rx_bytes, $rx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::rx_bytes", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
rx_bytes => $rx_bytes, |
|
rx_variable_uuid => $rx_variable_uuid, |
|
}}); |
|
(my $tx_bytes, my $tx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::tx_bytes", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
tx_bytes => $tx_bytes, |
|
tx_variable_uuid => $tx_variable_uuid, |
|
}}); |
|
|
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_name} = $bond_name; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mode} = $row->[2]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mtu} = $row->[3]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_interface} = $row->[4]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_reselect} = $row->[5]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_active_interface} = $row->[6]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mii_polling_interval} = $row->[7]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_up_delay} = $row->[8]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_down_delay} = $row->[9]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mac_address} = $row->[10]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_operational} = $row->[11]; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid} = $bond_bridge_uuid; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_bytes} = $rx_bytes =~ /\d/ ? $rx_bytes : 0; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_variable_uuid} = $rx_variable_uuid; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_bytes} = $tx_bytes =~ /\d/ ? $tx_bytes : 0; |
|
$anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_variable_uuid} = $tx_variable_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_name" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_name}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_mode" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mode}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_mtu" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mtu}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_primary_interface" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_interface}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_primary_reselect" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_reselect}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_active_interface" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_active_interface}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_mii_polling_interval" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mii_polling_interval}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_up_delay" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_up_delay}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_down_delay" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_down_delay}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_mac_address" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mac_address}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_operational" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_operational}, |
|
"old::bonds::bond_uuid::${bond_uuid}::bond_bridge_uuid" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid}, |
|
"old::bonds::bond_uuid::${bond_uuid}::rx_bytes" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_bytes}}).")", |
|
"old::bonds::bond_uuid::${bond_uuid}::rx_variable_uuid" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_variable_uuid}, |
|
"old::bonds::bond_uuid::${bond_uuid}::tx_bytes" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_bytes}}).")", |
|
"old::bonds::bond_uuid::${bond_uuid}::tx_variable_uuid" => $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_variable_uuid}, |
|
}}); |
|
|
|
$anvil->data->{bonds}{name_to_uuid}{$bond_name} = $bond_uuid; |
|
$anvil->data->{bonds}{uuid_to_name}{$bond_uuid} = $bond_name; |
|
$anvil->data->{interface}{name_to_uuid}{$bond_name} = $bond_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bonds::name_to_uuid::${bond_name}" => $anvil->data->{bonds}{name_to_uuid}{$bond_name}, |
|
"bonds::uuid_to_name::${bond_uuid}" => $anvil->data->{bonds}{uuid_to_name}{$bond_uuid}, |
|
"interface::name_to_uuid::${bond_name}" => $anvil->data->{interface}{name_to_uuid}{$bond_name}, |
|
}}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub load_bridge_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# The 'bridge_id' will be DELETED if the bridge was removed earlier. |
|
my $query = " |
|
SELECT |
|
bridge_uuid, |
|
bridge_name, |
|
bridge_id, |
|
bridge_mac_address, |
|
bridge_mtu, |
|
bridge_stp_enabled |
|
FROM |
|
bridges |
|
WHERE |
|
bridge_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $bridge_uuid = $row->[0]; |
|
my $bridge_name = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_uuid => $bridge_uuid, |
|
bridge_name => $bridge_name, |
|
}}); |
|
|
|
# Read in the RX/TX values, set to '0' if not found. |
|
my ($rx_bytes, $rx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::rx_bytes", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
rx_bytes => $rx_bytes, |
|
rx_variable_uuid => $rx_variable_uuid, |
|
}}); |
|
(my $tx_bytes, my $tx_variable_uuid, $modified_date) = $anvil->Database->read_variable({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::tx_bytes", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
tx_bytes => $tx_bytes, |
|
tx_variable_uuid => $tx_variable_uuid, |
|
}}); |
|
|
|
# Record the data in the hash, too. |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_name} = $bridge_name; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_id} = $row->[2]; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address} = $row->[3]; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mtu} = $row->[4]; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_stp_enabled} = $row->[5]; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes} = $rx_bytes =~ /\d/ ? $rx_bytes : 0; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_variable_uuid} = $rx_variable_uuid; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_bytes} = $tx_bytes =~ /\d/ ? $tx_bytes : 0; |
|
$anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_variable_uuid} = $tx_variable_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::bridges::bridge_uuid::${bridge_uuid}::bridge_name" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_name}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::bridge_id" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::bridge_mac_address" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::bridge_mtu" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mtu}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::bridge_stp_enabled" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_stp_enabled}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::rx_bytes" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes}}).")", |
|
"old::bridges::bridge_uuid::${bridge_uuid}::rx_variable_uuid" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_variable_uuid}, |
|
"old::bridges::bridge_uuid::${bridge_uuid}::tx_bytes" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_bytes}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_bytes}}).")", |
|
"old::bridges::bridge_uuid::${bridge_uuid}::tx_variable_uuid" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_variable_uuid}, |
|
}}); |
|
|
|
$anvil->data->{bridges}{name_to_uuid}{$bridge_name} = $bridge_uuid; |
|
$anvil->data->{bridges}{uuid_to_name}{$bridge_uuid} = $bridge_name; |
|
$anvil->data->{interface}{name_to_uuid}{$bridge_name} = $bridge_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bridges::name_to_uuid::${bridge_name}" => $anvil->data->{bridges}{name_to_uuid}{$bridge_name}, |
|
"bridges::uuid_to_name::${bridge_uuid}" => $anvil->data->{bridges}{uuid_to_name}{$bridge_uuid}, |
|
"interface::name_to_uuid::${bridge_name}" => $anvil->data->{interface}{name_to_uuid}{$bridge_name}, |
|
}}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This compares the last scan and the read state info and handles changes. |
|
sub find_changes |
|
{ |
|
my ($anvil) = @_; |
|
|
|
check_bridges($anvil); |
|
check_bonds($anvil); |
|
check_interfaces($anvil); |
|
check_ip_addresses($anvil); |
|
|
|
return(0); |
|
} |
|
|
|
# Handle IP addresses |
|
sub check_ip_addresses |
|
{ |
|
my ($anvil) = @_; |
|
|
|
foreach my $ip_address (sort {$a cmp $b} keys %{$anvil->data->{new}{ip_address}}) |
|
{ |
|
my $on_interface = $anvil->data->{new}{ip_address}{$ip_address}{on_interface}; |
|
my $new_on_type = $anvil->data->{interface}{name_to_type}{$on_interface}; |
|
my $new_subnet_mask = $anvil->data->{new}{ip_address}{$ip_address}{subnet_mask}; |
|
my $new_gateway = $anvil->data->{new}{ip_address}{$ip_address}{gateway}; |
|
my $new_default_gateway = $anvil->data->{new}{ip_address}{$ip_address}{default_gateway}; |
|
my $new_dns = $anvil->data->{new}{ip_address}{$ip_address}{dns}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address => $ip_address, |
|
on_interface => $on_interface, |
|
new_on_type => $new_on_type, |
|
new_subnet_mask => $new_subnet_mask, |
|
new_gateway => $new_gateway, |
|
new_default_gateway => $new_default_gateway, |
|
new_dns => $new_dns, |
|
}}); |
|
my $new_on_uuid = ""; |
|
if ($anvil->data->{interface}{name_to_uuid}{$on_interface}) |
|
{ |
|
$new_on_uuid = $anvil->data->{interface}{name_to_uuid}{$on_interface}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_on_uuid => $new_on_uuid }}); |
|
} |
|
elsif ($anvil->data->{interface}{device_to_uuid}{$on_interface}) |
|
{ |
|
$new_on_uuid = $anvil->data->{interface}{device_to_uuid}{$on_interface}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_on_uuid => $new_on_uuid }}); |
|
} |
|
|
|
if (exists $anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address}) |
|
{ |
|
# Existing, update? |
|
my $ip_address_uuid = $anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address}; |
|
my $old_on_type = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_type}; |
|
my $old_on_uuid = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_on_uuid}; |
|
my $old_subnet_mask = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_subnet_mask}; |
|
my $old_gateway = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_gateway}; |
|
my $old_default_gateway = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_default_gateway}; |
|
my $old_dns = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_dns}; |
|
my $old_note = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
ip_address => $ip_address, |
|
old_on_type => $old_on_type, |
|
old_on_uuid => $old_on_uuid, |
|
old_subnet_mask => $old_subnet_mask, |
|
old_gateway => $old_gateway, |
|
old_default_gateway => $old_default_gateway, |
|
old_dns => $old_dns, |
|
old_note => $old_note, |
|
}}); |
|
|
|
# Delete this old entry so we know we've processed it. |
|
delete $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}; |
|
|
|
my $say_old_interface = "--"; |
|
if ($old_on_type eq "bridge") |
|
{ |
|
$say_old_interface = $anvil->data->{bridges}{uuid_to_name}{$old_on_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_old_interface => $say_old_interface }}); |
|
} |
|
elsif ($old_on_type eq "bond") |
|
{ |
|
$say_old_interface = $anvil->data->{bonds}{uuid_to_name}{$old_on_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_old_interface => $say_old_interface }}); |
|
} |
|
elsif ($old_on_type eq "interface") |
|
{ |
|
$say_old_interface = $anvil->data->{network_interfaces}{uuid_to_name}{$old_on_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_old_interface => $say_old_interface }}); |
|
} |
|
|
|
# Now look for changes. |
|
my $changes = 0; |
|
|
|
# These will always change together. |
|
if (($new_on_type ne $old_on_type) or ($new_on_uuid ne $old_on_uuid)) |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
old => $say_old_interface, |
|
new => $on_interface, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0050", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0050", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_subnet_mask ne $old_subnet_mask) |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
old => $ip_address."/".$old_subnet_mask, |
|
new => $ip_address."/".$new_subnet_mask, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0051", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0051", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_gateway ne $old_gateway) |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
old => $old_gateway eq "" ? "--" : $old_gateway, |
|
new => $new_gateway eq "" ? "--" : $new_gateway, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0052", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0052", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_default_gateway ne $old_default_gateway) |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
old => $old_default_gateway ? "#!string!unit_0001!#" : "#!string!unit_0002!#", |
|
new => $new_default_gateway ? "#!string!unit_0001!#" : "#!string!unit_0002!#", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0053", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0053", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_dns ne $old_dns) |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
old => $old_dns eq "" ? "--" : $old_dns, |
|
new => $new_dns eq "" ? "--" : $new_dns, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0054", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0054", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
|
|
# We only care about 'old_note' if it's set to 'DELETED'. |
|
if ($old_note eq "DELETED") |
|
{ |
|
# This was likely changed by an admin, so it's a notice level alert. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0055", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0055", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
|
|
if ($changes) |
|
{ |
|
# If the note was 'DELETED', change it to ''. Otherwise, use the old note. |
|
$old_note = "" if $old_note eq "DELETED"; |
|
my $ip_address_uuid = $anvil->Database->insert_or_update_ip_addresses({ |
|
debug => 2, |
|
ip_address_uuid => $ip_address_uuid, |
|
ip_address_on_type => $new_on_type, |
|
ip_address_on_uuid => $new_on_uuid, |
|
ip_address_address => $ip_address, |
|
ip_address_subnet_mask => $new_subnet_mask, |
|
ip_address_gateway => $new_gateway, |
|
ip_address_default_gateway => $new_default_gateway, |
|
ip_address_dns => $new_dns, |
|
ip_address_note => $old_note, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }}); |
|
} |
|
} |
|
else |
|
{ |
|
# New, store. |
|
my $ip_address_uuid = $anvil->Database->insert_or_update_ip_addresses({ |
|
debug => 2, |
|
ip_address_on_type => $new_on_type, |
|
ip_address_on_uuid => $new_on_uuid, |
|
ip_address_address => $ip_address, |
|
ip_address_subnet_mask => $new_subnet_mask, |
|
ip_address_gateway => $new_gateway, |
|
ip_address_default_gateway => $new_default_gateway, |
|
ip_address_dns => $new_dns, |
|
ip_address_note => "", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }}); |
|
|
|
# Register a notice level alert. |
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $on_interface, |
|
subnet_mask => $new_subnet_mask, |
|
gateway => $new_gateway eq "" ? "--" : $new_gateway, |
|
default_gateway => $new_default_gateway ? "#!string!unit_0001!#" : "#!string!unit_0002!#", |
|
dns => $new_dns eq "" ? "--" : $new_dns, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0056", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0056", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
# Look for left over / deleted bonds. |
|
$anvil->Database->get_mac_to_ip({debug => 2}); |
|
my $host = $anvil->Get->short_host_name(); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host => $host }}); |
|
foreach my $ip_address_uuid (keys %{$anvil->data->{old}{ip_addresses}{ip_address_uuid}}) |
|
{ |
|
# Skip if already deleted. |
|
next if $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} eq "DELETED"; |
|
|
|
my $ip_address_address = $anvil->data->{old}{ip_addresses}{ip_address_uuid}{$ip_address_uuid}{ip_address_address}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_address => $ip_address_address }}); |
|
|
|
# Is this an alternate IP? |
|
if ((exists $anvil->data->{network}{$host}{ip_address}{$ip_address_address}) && |
|
($anvil->data->{network}{$host}{ip_address}{$ip_address_address}{interface})) |
|
{ |
|
# This is an alternate IP, don't delete it. |
|
next; |
|
} |
|
|
|
my $variables = { ip => $ip_address_address }; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0060", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0060", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $ip_address_uuid = $anvil->Database->insert_or_update_ip_addresses({ |
|
debug => 2, |
|
ip_address_uuid => $ip_address_uuid, |
|
'delete' => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }}); |
|
} |
|
|
|
# Look for alternate IPs |
|
foreach my $ip_address (sort {$a cmp $b} keys %{$anvil->data->{network}{$host}{ip_address}}) |
|
{ |
|
my $interface = $anvil->data->{network}{$host}{ip_address}{$ip_address}{interface}; |
|
my $subnet_mask = $anvil->data->{network}{$host}{ip_address}{$ip_address}{subnet_mask}; |
|
my $mac_address = $anvil->data->{network}{$host}{interface}{$interface}{mac_address}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"s1:ip_address" => $ip_address, |
|
"s2:interface" => $interface, |
|
"s3:subnet_mask" => $subnet_mask, |
|
"s4:mac_address" => $mac_address, |
|
}}); |
|
|
|
# Is this a new IP? |
|
if (($interface) && ($mac_address)) |
|
{ |
|
if (not exists $anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address}) |
|
{ |
|
# Record it. |
|
my ($mac_to_ip_uuid) = $anvil->Database->insert_or_update_mac_to_ip({ |
|
debug => 2, |
|
mac_to_ip_mac_address => $mac_address, |
|
mac_to_ip_ip_address => $ip_address, |
|
mac_to_ip_note => "on ".$host.":".$interface, |
|
update_note => 0, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_to_ip_uuid => $mac_to_ip_uuid }}); |
|
|
|
# reload the mac_to_ips. |
|
$anvil->Database->get_mac_to_ip({debug => 2}); |
|
|
|
my $variables = { |
|
ip_address => $ip_address, |
|
interface => $interface, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0064", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0064", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
if ($anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address}{mac_to_ip_uuid}) |
|
{ |
|
# Add a note that we've got the IP. |
|
my $mac_to_ip_uuid = $anvil->data->{mac_to_ip}{mac_to_ip_ip_address}{$ip_address}{mac_to_ip_uuid}; |
|
my $mac_to_ip_note = $anvil->data->{mac_to_ip}{mac_to_ip_uuid}{$mac_to_ip_uuid}{mac_to_ip_note}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:ip_address' => $ip_address, |
|
's2:mac_to_ip_uuid' => $mac_to_ip_uuid, |
|
's3:mac_to_ip_note' => $mac_to_ip_note, |
|
}}); |
|
|
|
if (($mac_to_ip_uuid) && (not $mac_to_ip_note)) |
|
{ |
|
my ($mac_to_ip_uuid) = $anvil->Database->insert_or_update_mac_to_ip({ |
|
debug => 2, |
|
mac_to_ip_uuid => $mac_to_ip_uuid, |
|
mac_to_ip_mac_address => $mac_address, |
|
mac_to_ip_ip_address => $ip_address, |
|
mac_to_ip_note => "on ".$host.":".$interface, |
|
update_note => 0, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_to_ip_uuid => $mac_to_ip_uuid }}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# Look for changes in network interfaces. |
|
sub check_interfaces |
|
{ |
|
my ($anvil) = @_; |
|
|
|
my $interfaces = keys %{$anvil->data->{new}{interface}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interfaces => $interfaces }}); |
|
foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{new}{interface}}) |
|
{ |
|
my $new_nm_uuid = $anvil->data->{new}{interface}{$network_interface_name}{nm_uuid}; |
|
my $new_nm_name = $anvil->data->{new}{interface}{$network_interface_name}{nm_name}; |
|
my $new_nm_device = $anvil->data->{new}{interface}{$network_interface_name}{nm_device}; |
|
my $new_bond_uuid = $anvil->data->{new}{interface}{$network_interface_name}{bond_uuid}; |
|
my $new_bond_name = $anvil->data->{new}{interface}{$network_interface_name}{bond_name}; |
|
my $new_bridge_uuid = $anvil->data->{new}{interface}{$network_interface_name}{bridge_uuid}; |
|
my $new_bridge_name = $anvil->data->{new}{interface}{$network_interface_name}{bridge_name}; |
|
my $new_duplex = $anvil->data->{new}{interface}{$network_interface_name}{duplex}; |
|
my $new_link_state = $anvil->data->{new}{interface}{$network_interface_name}{link_state}; |
|
my $new_operational = $anvil->data->{new}{interface}{$network_interface_name}{operational}; |
|
my $new_mac_address = $anvil->data->{new}{interface}{$network_interface_name}{mac_address}; |
|
my $new_medium = $anvil->data->{new}{interface}{$network_interface_name}{medium}; |
|
my $new_mtu = $anvil->data->{new}{interface}{$network_interface_name}{mtu}; |
|
my $new_speed = $anvil->data->{new}{interface}{$network_interface_name}{speed}; |
|
my $new_tx_bytes = $anvil->data->{new}{interface}{$network_interface_name}{tx_bytes}; |
|
my $new_rx_bytes = $anvil->data->{new}{interface}{$network_interface_name}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network_interface_name => $network_interface_name, |
|
new_nm_uuid => $new_nm_uuid, |
|
new_nm_name => $new_nm_name, |
|
new_nm_device => $new_nm_device, |
|
new_bond_uuid => $new_bond_uuid, |
|
new_bond_name => $new_bond_name, |
|
new_bridge_uuid => $new_bridge_uuid, |
|
new_bridge_name => $new_bridge_name, |
|
new_duplex => $new_duplex, |
|
new_link_state => $new_link_state, |
|
new_operational => $new_operational, |
|
new_mac_address => $new_mac_address, |
|
new_medium => $new_medium, |
|
new_mtu => $new_mtu, |
|
new_speed => $new_speed, |
|
new_tx_bytes => $new_tx_bytes, |
|
new_rx_bytes => $new_rx_bytes, |
|
}}); |
|
|
|
# Find the bridge, if any, and the bond UUID, if there's a bond name. |
|
if ($new_bond_name) |
|
{ |
|
$new_bond_uuid = $anvil->data->{bonds}{name_to_uuid}{$new_bond_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_bond_uuid => $new_bond_uuid }}); |
|
} |
|
if (exists $anvil->data->{interface_to_bridge}{$network_interface_name}) |
|
{ |
|
# This interface is on a bridge |
|
$new_bridge_name = $anvil->data->{interface_to_bridge}{$network_interface_name}; |
|
$new_bridge_uuid = $anvil->data->{bridges}{name_to_uuid}{$new_bridge_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_bridge_name => $new_bridge_name, |
|
new_bridge_uuid => $new_bridge_uuid, |
|
}}); |
|
} |
|
|
|
# New or existing? |
|
my $network_interface_uuid = ""; |
|
if (exists $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name}) |
|
{ |
|
$network_interface_uuid = $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
} |
|
elsif (exists $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_name}) |
|
{ |
|
$network_interface_uuid = $anvil->data->{network_interfaces}{device_to_uuid}{$network_interface_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
} |
|
elsif (($new_mac_address) && (exists $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address})) |
|
{ |
|
$network_interface_uuid = $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
} |
|
if ($network_interface_uuid) |
|
{ |
|
# Existing. Changes? |
|
my $old_nm_name = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name}; |
|
my $old_nm_device = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_device}; |
|
my $old_bond_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid}; |
|
my $old_bond_name = ""; |
|
my $old_bridge_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid}; |
|
my $old_bridge_name = ""; |
|
my $old_duplex = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex}; |
|
my $old_link_state = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_link_state}; |
|
my $old_operational = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational}; |
|
my $old_mac_address = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mac_address}; |
|
my $old_medium = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium}; |
|
my $old_mtu = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_mtu}; |
|
my $old_speed = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_speed}; |
|
my $old_rx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes}; |
|
my $rx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_variable_uuid}; |
|
my $old_tx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes}; |
|
my $tx_variable_uuid = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_nm_name => $old_nm_name, |
|
old_nm_device => $old_nm_device, |
|
old_bond_uuid => $old_bond_uuid, |
|
old_bridge_uuid => $old_bridge_uuid, |
|
old_duplex => $old_duplex, |
|
old_link_state => $old_link_state, |
|
old_operational => $old_operational, |
|
old_mac_address => $old_mac_address, |
|
old_medium => $old_medium, |
|
old_mtu => $old_mtu, |
|
old_speed => $old_speed, |
|
old_tx_bytes => $old_tx_bytes, |
|
tx_variable_uuid => $tx_variable_uuid, |
|
old_rx_bytes => $old_rx_bytes, |
|
rx_variable_uuid => $rx_variable_uuid, |
|
}}); |
|
|
|
# Delete this so we know it's processed. |
|
delete $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}; |
|
|
|
# Get the old bridge or bond name, if required. |
|
if ($old_bridge_uuid) |
|
{ |
|
# Get the bridge name |
|
$old_bridge_name = $anvil->data->{bridges}{uuid_to_name}{$old_bridge_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_bridge_name => $old_bridge_name }}); |
|
} |
|
if ($old_bond_uuid) |
|
{ |
|
$old_bond_name = $anvil->data->{bonds}{uuid_to_name}{$old_bond_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_bond_name => $old_bond_name }}); |
|
} |
|
|
|
# Look for changes. |
|
my $changes = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_nm_name => $new_nm_name, |
|
old_nm_name => $old_nm_name, |
|
}}); |
|
if ($new_nm_name ne $old_nm_name) |
|
{ |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_nm_name, |
|
new => $new_nm_name, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0062", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0062", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_nm_device => $new_nm_device, |
|
old_nm_device => $old_nm_device, |
|
}}); |
|
if ($new_nm_device ne $old_nm_device) |
|
{ |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_nm_device, |
|
new => $new_nm_device, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0063", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0063", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_bond_uuid ne $old_bond_uuid) |
|
{ |
|
# We're making this a warning level alert as it should not be changing. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $key = "scan_network_alert_0032"; |
|
if (not $new_bond_uuid) |
|
{ |
|
# Left the bond |
|
$key = "scan_network_alert_0031"; |
|
} |
|
elsif (not $old_bond_uuid) |
|
{ |
|
# Joined the bond |
|
$key = "scan_network_alert_0030"; |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_bond_name." (".$old_bond_uuid.")", |
|
new => $new_bond_name." (".$new_bond_uuid.")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_bridge_uuid ne $old_bridge_uuid) |
|
{ |
|
# If this is a vnet* device, it's a notice level alert. Otherwise it's a |
|
# warning level alert. The vnetX devices come and go with VMs. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $log_level = 1; |
|
my $alert_level = "warning"; |
|
my $key = "scan_network_alert_0035"; |
|
if ($network_interface_name =~ /^vnet/) |
|
{ |
|
# Left the bridge |
|
$log_level = 1; |
|
$alert_level = "warning"; |
|
} |
|
if ($new_bridge_uuid) |
|
{ |
|
# Left the bridge |
|
$key = "scan_network_alert_0034"; |
|
} |
|
elsif (not $old_bridge_uuid) |
|
{ |
|
# Joined the bridge |
|
$key = "scan_network_alert_0033"; |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_bridge_name." (".$old_bridge_uuid.")", |
|
new => $new_bridge_name." (".$new_bridge_uuid.")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_duplex ne $old_duplex) |
|
{ |
|
# This is always a warning |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $clear = 0; |
|
my $key = "scan_network_alert_0036"; |
|
my $alert_level = "notice"; |
|
if ($new_duplex eq "full") |
|
{ |
|
# Duplex is back to being OK |
|
$clear = 1; |
|
$key = "scan_network_alert_0037"; |
|
} |
|
|
|
# Is this one of our interface? |
|
if (not $anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Not an interface we care about. |
|
$alert_level = "notice"; |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_duplex, |
|
new => $new_duplex, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
clear_alert => $clear, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_link_state ne $old_link_state) |
|
{ |
|
# This is always a warning, if it's a NIC we care about. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $clear = 0; |
|
my $key = "scan_network_alert_0038"; |
|
my $alert_level = "warning"; |
|
if ($new_link_state) |
|
{ |
|
# Link is up |
|
$clear = 1; |
|
$key = "scan_network_alert_0039"; |
|
} |
|
|
|
# Is this one of our interface? |
|
if (not $anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Not an interface we care about. |
|
$alert_level = "notice"; |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_link_state, |
|
new => $new_link_state, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
clear_alert => $clear, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
# Operation can be DELETED |
|
if ($new_operational ne $old_operational) |
|
{ |
|
# This is always a warning |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
# Is it up or down? |
|
my $clear = 0; |
|
my $key = "scan_network_alert_0040"; |
|
my $alert_level = "notice"; |
|
if ($old_operational eq "DELETED") |
|
{ |
|
# Link is back. Is it up? |
|
if ($new_operational eq "up") |
|
{ |
|
# It's up |
|
$clear = 1; |
|
$key = "scan_network_alert_0042"; |
|
} |
|
else |
|
{ |
|
# It's back, but down |
|
$key = "scan_network_alert_0043"; |
|
} |
|
} |
|
elsif ($new_operational eq "up") |
|
{ |
|
# It's up |
|
$clear = 1; |
|
$key = "scan_network_alert_0041"; |
|
} |
|
|
|
# Is this one of our interface? |
|
if (not $anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Not an interface we care about. |
|
$alert_level = "notice"; |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_operational, |
|
new => $new_operational, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
clear_alert => $clear, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_mac_address ne $old_mac_address) |
|
{ |
|
# This is a notice level alert as it's almost certainly a NIC change |
|
# performed by an admin. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_mac_address, |
|
new => $new_mac_address, |
|
}; |
|
|
|
my $key = "scan_network_alert_0044"; |
|
if ($network_interface_name =~ /^vnet/) |
|
{ |
|
# This is a server booting or migrating |
|
$key = "scan_network_alert_0061"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_medium ne $old_medium) |
|
{ |
|
# This is a notice level alert as it's almost certainly a NIC change |
|
# performed by an admin. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_medium, |
|
new => $new_medium, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0045", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0045", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_mtu ne $old_mtu) |
|
{ |
|
# We're making this a warning level alert if the MTU drops. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_mtu, |
|
new => $new_mtu, |
|
}; |
|
|
|
my $log_level = 2; |
|
my $alert_level = "notice"; |
|
my $key = "scan_network_alert_0046"; |
|
if ($new_mtu < $old_mtu) |
|
{ |
|
# Make it an alert |
|
$log_level = 1; |
|
$alert_level = "warning"; |
|
$key = "scan_network_alert_0047"; |
|
} |
|
|
|
# Is this one of our interface? |
|
if (not $anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Not an interface we care about. |
|
$alert_level = "notice"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_speed ne $old_speed) |
|
{ |
|
# We're making this a warning level as speed shouldn't change |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_speed, |
|
new => $new_speed, |
|
}; |
|
|
|
my $key = "scan_network_alert_0048"; |
|
if ($new_speed > $old_speed) |
|
{ |
|
# Speed dropped, likely a faulty network cable |
|
$key = "scan_network_alert_0049"; |
|
} |
|
|
|
# Is this one of our interface? |
|
my $alert_level = "notice"; |
|
if (not $anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Not an interface we care about. |
|
$alert_level = "notice"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
|
|
if ($changes) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_nm_name => $new_nm_name, |
|
new_nm_device => $new_nm_device, |
|
}}); |
|
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({ |
|
debug => 2, |
|
network_interface_nm_uuid => $new_nm_uuid, |
|
network_interface_bond_uuid => $new_bond_uuid, |
|
network_interface_bridge_uuid => $new_bridge_uuid, |
|
network_interface_name => $new_nm_name, # biosdevname |
|
network_interface_device => $new_nm_device, # ip name |
|
network_interface_duplex => $new_duplex, |
|
network_interface_link_state => $new_link_state, |
|
network_interface_operational => $new_operational, |
|
network_interface_mac_address => $new_mac_address, |
|
network_interface_medium => $new_medium, |
|
network_interface_mtu => $new_mtu, |
|
network_interface_speed => $new_speed, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
} |
|
|
|
# Track usage of interfaces we care about |
|
if ($anvil->Network->is_our_interface({interface => $network_interface_name})) |
|
{ |
|
# Rx and Tx almost always change, so they're only info-level alerts. |
|
if ($new_tx_bytes ne $old_tx_bytes) |
|
{ |
|
if ($tx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $tx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_tx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "network_interface::".$network_interface_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $network_interface_uuid, |
|
variable_source_table => "network_interfaces", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_tx_bytes}).")", |
|
new => $new_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? |
|
my $key = "scan_network_alert_0007"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_tx_bytes > $new_tx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0008"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_rx_bytes ne $old_rx_bytes) |
|
{ |
|
if ($rx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $rx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_rx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "network_interface::".$network_interface_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $network_interface_uuid, |
|
variable_source_table => "network_interfaces", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
old => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", |
|
new => $new_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? |
|
my $key = "scan_network_alert_0009"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_rx_bytes > $new_rx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0010"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# Record the interface |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_nm_name => $new_nm_name, |
|
network_interface_name => $network_interface_name, |
|
new_nm_device => $new_nm_device, |
|
}}); |
|
|
|
# If there's no device and no interface name, ignore it. |
|
next if ((not $new_nm_name) && (not $new_nm_device)); |
|
|
|
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({ |
|
debug => 2, |
|
network_interface_nm_uuid => $new_nm_uuid, |
|
network_interface_bond_uuid => $new_bond_uuid, |
|
network_interface_bridge_uuid => $new_bridge_uuid, |
|
network_interface_name => $new_nm_name, |
|
network_interface_device => $network_interface_name, |
|
network_interface_duplex => $new_duplex, |
|
network_interface_link_state => $new_link_state, |
|
network_interface_operational => $new_operational, |
|
network_interface_mac_address => $new_mac_address, |
|
network_interface_medium => $new_medium, |
|
network_interface_mtu => $new_mtu, |
|
network_interface_speed => $new_speed, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
|
|
# Store the interface so IPs can find our UUID. |
|
$anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; |
|
$anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid} = $network_interface_name; |
|
$anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address} = $network_interface_uuid; |
|
$anvil->data->{interface}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; |
|
$anvil->data->{interface}{device_to_uuid}{$new_nm_device} = $network_interface_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"network_interfaces::name_to_uuid::${network_interface_name}" => $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name}, |
|
"network_interfaces::uuid_to_name::${network_interface_uuid}" => $anvil->data->{network_interfaces}{uuid_to_name}{$network_interface_uuid}, |
|
"network_interfaces::mac_to_uuid::${new_mac_address}" => $anvil->data->{network_interfaces}{mac_to_uuid}{$new_mac_address}, |
|
"interface::name_to_uuid::${network_interface_name}" => $anvil->data->{interface}{name_to_uuid}{$network_interface_name}, |
|
"interface::device_to_uuid::${new_nm_device}" => $anvil->data->{interface}{device_to_uuid}{$new_nm_device}, |
|
}}); |
|
|
|
# Store the rx_bytes and tx_bytes |
|
my $rx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "network_interface::".$network_interface_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $new_bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { rx_variable_uuid => $rx_variable_uuid }}); |
|
my $tx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "network_interface::".$network_interface_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $new_bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { tx_variable_uuid => $tx_variable_uuid }}); |
|
|
|
# Report. |
|
my $say_duplex = "#!string!unit_0004!#"; |
|
if ($new_duplex =~ /full/i) |
|
{ |
|
$say_duplex = "#!string!unit_0015!#"; |
|
} |
|
elsif ($new_duplex =~ /half/i) |
|
{ |
|
$say_duplex = "#!string!unit_0016!#"; |
|
} |
|
my $variables = { |
|
interface_name => $network_interface_name, |
|
bond_name => $new_bond_name ? $new_bond_name : "--", |
|
bridge_name => $new_bridge_name ? $new_bridge_name : "--", |
|
duplex => $say_duplex, |
|
link_state => $new_link_state ? "#!string!unit_0013!#" : "#!string!unit_0014!#", # up / down |
|
operational => $new_operational, |
|
mac_address => $new_mac_address, |
|
medium => $new_medium, |
|
mtu => $new_mtu, |
|
speed => $new_speed, |
|
say_tx => $anvil->Convert->add_commas({number => $new_tx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
say_rx => $anvil->Convert->add_commas({number => $new_rx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0029", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0029", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
# Look for left over / deleted bonds. |
|
foreach my $network_interface_uuid (keys %{$anvil->data->{old}{network_interfaces}{network_interface_uuid}}) |
|
{ |
|
# Skip if already deleted. |
|
next if $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} eq "DELETED"; |
|
|
|
my $network_interface_name = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_name}; |
|
my $tx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{tx_bytes}; |
|
my $rx_bytes = $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{rx_bytes}; |
|
|
|
my $variables = { |
|
name => $network_interface_name, |
|
tx => $anvil->Convert->add_commas({number => $tx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $tx_bytes}).")", |
|
rx => $anvil->Convert->add_commas({number => $rx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $rx_bytes}).")", |
|
}; |
|
|
|
# If this a vnet device, it's only a notice message as this is expected when a VM migrates or |
|
# shuts down. |
|
my $alert_level = $network_interface_name =~ /^vnet/ ? "notice" : "warning"; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0059", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0059", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({ |
|
debug => 2, |
|
network_interface_uuid => $network_interface_uuid, |
|
'delete' => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { network_interface_uuid => $network_interface_uuid }}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# Look for changes in the bonds. |
|
sub check_bonds |
|
{ |
|
my ($anvil) = @_; |
|
|
|
foreach my $bond_name (sort {$a cmp $b} keys %{$anvil->data->{new}{bond}}) |
|
{ |
|
# Store the bond |
|
my $new_nm_uuid = $anvil->data->{new}{bond}{$bond_name}{nm_uuid}; |
|
my $new_mode = $anvil->data->{new}{bond}{$bond_name}{mode}; |
|
my $new_mtu = $anvil->data->{new}{bond}{$bond_name}{mtu}; |
|
my $new_operational = $anvil->data->{new}{bond}{$bond_name}{operational}; |
|
my $new_mac_address = $anvil->data->{new}{bond}{$bond_name}{mac_address}; |
|
my $new_primary_interface = $anvil->data->{new}{bond}{$bond_name}{primary_interface}; |
|
my $new_primary_reselect = $anvil->data->{new}{bond}{$bond_name}{primary_reselect}; |
|
my $new_active_interface = $anvil->data->{new}{bond}{$bond_name}{active_interface}; |
|
my $new_mii_polling_interval = $anvil->data->{new}{bond}{$bond_name}{mii_polling_interval}; |
|
my $new_up_delay = $anvil->data->{new}{bond}{$bond_name}{up_delay}; |
|
my $new_down_delay = $anvil->data->{new}{bond}{$bond_name}{down_delay}; |
|
my $new_tx_bytes = $anvil->data->{new}{bond}{$bond_name}{tx_bytes}; |
|
my $new_rx_bytes = $anvil->data->{new}{bond}{$bond_name}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bond_name => $bond_name, |
|
new_mode => $new_mode, |
|
new_mtu => $new_mtu, |
|
new_operational => $new_operational, |
|
new_mac_address => $new_mac_address, |
|
new_primary_interface => $new_primary_interface, |
|
new_primary_reselect => $new_primary_reselect, |
|
new_active_interface => $new_active_interface, |
|
new_mii_polling_interval => $new_mii_polling_interval, |
|
new_up_delay => $new_up_delay, |
|
new_down_delay => $new_down_delay, |
|
new_tx_bytes => $new_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
new_rx_bytes => $new_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}}); |
|
|
|
# If we don't have a bridge_uuid, find it by the name. |
|
my $new_bridge_uuid = ""; |
|
my $new_bridge_name = ""; |
|
if (exists $anvil->data->{interface_to_bridge}{$bond_name}) |
|
{ |
|
# This bond is on a bridge |
|
$new_bridge_name = $anvil->data->{interface_to_bridge}{$bond_name}; |
|
$new_bridge_uuid = $anvil->data->{bridges}{name_to_uuid}{$new_bridge_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_bridge_name => $new_bridge_name, |
|
new_bridge_uuid => $new_bridge_uuid, |
|
}}); |
|
} |
|
|
|
# New or existing? |
|
if (exists $anvil->data->{bonds}{name_to_uuid}{$bond_name}) |
|
{ |
|
# Existing, look for changes. |
|
my $bond_uuid = $anvil->data->{bonds}{name_to_uuid}{$bond_name}; |
|
my $old_mode = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mode}; |
|
my $old_mtu = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mtu}; |
|
my $old_primary_interface = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_interface}; |
|
my $old_primary_reselect = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_primary_reselect}; |
|
my $old_active_interface = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_active_interface}; |
|
my $old_mii_polling_interval = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mii_polling_interval}; |
|
my $old_up_delay = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_up_delay}; |
|
my $old_down_delay = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_down_delay}; |
|
my $old_mac_address = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_mac_address}; |
|
my $old_operational = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_operational}; |
|
my $old_bridge_uuid = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_bridge_uuid}; |
|
my $old_rx_bytes = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_bytes}; |
|
my $rx_variable_uuid = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_variable_uuid}; |
|
my $old_tx_bytes = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_bytes}; |
|
my $tx_variable_uuid = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bond_uuid => $bond_uuid, |
|
old_mode => $old_mode, |
|
old_mtu => $old_mtu, |
|
old_primary_interface => $old_primary_interface, |
|
old_primary_reselect => $old_primary_reselect, |
|
old_active_interface => $old_active_interface, |
|
old_mii_polling_interval => $old_mii_polling_interval, |
|
old_up_delay => $old_up_delay, |
|
old_down_delay => $old_down_delay, |
|
old_mac_address => $old_mac_address, |
|
old_operational => $old_operational, |
|
old_bridge_uuid => $old_bridge_uuid, |
|
old_rx_bytes => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", |
|
rx_variable_uuid => $rx_variable_uuid, |
|
old_tx_bytes => $old_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_tx_bytes}).")", |
|
tx_variable_uuid => $tx_variable_uuid, |
|
}}); |
|
|
|
# Delete the old record so we know it's been processed. |
|
delete $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}; |
|
|
|
my $old_bridge_name = ""; |
|
if ($old_bridge_uuid) |
|
{ |
|
$old_bridge_name = $anvil->data->{bridges}{uuid_to_name}{$old_bridge_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_bridge_name => $old_bridge_name }}); |
|
} |
|
|
|
my $changes = 0; |
|
if ($new_mode ne $old_mode) |
|
{ |
|
# We're making this a warning level alert as it should not be changing. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $say_old_name = "scan_network_bond_".$old_mode."_name"; |
|
my $say_old_number = "scan_network_bond_".$old_mode."_number"; |
|
my $say_old_description = "scan_network_bond_".$old_mode."_description"; |
|
my $say_new_name = "scan_network_bond_".$new_mode."_name"; |
|
my $say_new_number = "scan_network_bond_".$new_mode."_number"; |
|
my $say_new_description = "scan_network_bond_".$new_mode."_description"; |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $say_old_name, |
|
old_number => $say_old_number, |
|
old_description => $say_old_description, |
|
new => $say_new_name, |
|
new_number => $say_new_number, |
|
new_description => $say_new_description, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0012", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0012", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_mtu ne $old_mtu) |
|
{ |
|
# We're making this a warning level alert if the MTU drops. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_mtu, |
|
new => $new_mtu, |
|
}; |
|
|
|
my $log_level = 2; |
|
my $alert_level = "notice"; |
|
my $key = "scan_network_alert_0013"; |
|
if ($new_mtu < $old_mtu) |
|
{ |
|
# Make it an alert |
|
$log_level = 1; |
|
$alert_level = "warning"; |
|
$key = "scan_network_alert_0014"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_bridge_name ne $old_bridge_name) |
|
{ |
|
# We're making this a warning level alert as it should not be changing. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_bridge_name ? $old_bridge_name : "--", |
|
new => $new_bridge_name ? $new_bridge_name : "--", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0015", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0015", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_operational ne $old_operational) |
|
{ |
|
# We're making this a warning level alert as it should not be changing. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_operational eq "up" ? "#!string!unit_0013!#" : "#!string!unit_0014!#", |
|
new => $new_operational eq "up" ? "#!string!unit_0013!#" : "#!string!unit_0014!#", |
|
}; |
|
|
|
# Gone up, down or returned? |
|
my $key = "scan_network_alert_0016"; |
|
if ($old_operational eq "DELETED") |
|
{ |
|
# Bond is back from being deleted. Is it up or down? |
|
if ($new_operational eq "up") |
|
{ |
|
# Back and up |
|
$key = "scan_network_alert_0027"; |
|
} |
|
else |
|
{ |
|
# Back but down |
|
$key = "scan_network_alert_0028"; |
|
} |
|
} |
|
elsif ($new_operational eq "up") |
|
{ |
|
$key = "scan_network_alert_0017"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_mac_address ne $old_mac_address) |
|
{ |
|
# We're making this a notice as it can change with the active interface |
|
# changing. There will be a warning if a given interface dropped. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_mac_address, |
|
new => $new_mac_address, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0018", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0018", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_primary_interface ne $old_primary_interface) |
|
{ |
|
# We're making this a notice as it will only change if an admin did it. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_primary_interface, |
|
new => $new_primary_interface, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0019", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0019", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_primary_reselect ne $old_primary_reselect) |
|
{ |
|
# We're making this a notice as it will only change if an admin did it. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_primary_reselect, |
|
new => $new_primary_reselect, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0020", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0020", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_active_interface ne $old_active_interface) |
|
{ |
|
# We're making this a warning as this generally happens when a link drops or returns. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_active_interface, |
|
new => $new_active_interface, |
|
}; |
|
|
|
# Did the primary interface return? |
|
my $key = "scan_network_alert_0021"; |
|
if ($new_active_interface eq $new_primary_interface) |
|
{ |
|
# Primary link is back |
|
$key = "scan_network_alert_0022"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_mii_polling_interval ne $old_mii_polling_interval) |
|
{ |
|
# We're making this a notice as this will only ever change by an admin. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_mii_polling_interval, |
|
new => $new_mii_polling_interval, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0023", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0023", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_up_delay ne $old_up_delay) |
|
{ |
|
# We're making this a notice as this will only ever change by an admin. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_up_delay, |
|
new => $new_up_delay, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0024", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0024", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_down_delay ne $old_down_delay) |
|
{ |
|
# We're making this a notice as this will only ever change by an admin. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_down_delay, |
|
new => $new_down_delay, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0024", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0024", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
|
|
# Save the changes, if any. |
|
if ($changes) |
|
{ |
|
my $bond_uuid = $anvil->Database->insert_or_update_bonds({ |
|
debug => 2, |
|
bond_nm_uuid => $new_nm_uuid, |
|
bond_name => $bond_name, |
|
bond_mode => $new_mode, |
|
bond_mtu => $new_mtu, |
|
bond_operational => $new_operational, |
|
bond_mac_address => $new_mac_address, |
|
bond_primary_interface => $new_primary_interface, |
|
bond_primary_reselect => $new_primary_reselect, |
|
bond_active_interface => $new_active_interface, |
|
bond_mii_polling_interval => $new_mii_polling_interval, |
|
bond_up_delay => $new_up_delay, |
|
bond_down_delay => $new_down_delay, |
|
bond_bridge_uuid => $new_bridge_uuid, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); |
|
} |
|
|
|
# Rx and Tx almost always change, so they're only info-level alerts. |
|
if ($new_tx_bytes ne $old_tx_bytes) |
|
{ |
|
if ($tx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $tx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_tx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_tx_bytes}).")", |
|
new => $new_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? |
|
my $key = "scan_network_alert_0007"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_tx_bytes > $new_tx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0008"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_rx_bytes ne $old_rx_bytes) |
|
{ |
|
if ($rx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $rx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_rx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
old => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", |
|
new => $new_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? Reset Normal increase |
|
my $key = "scan_network_alert_0009"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_rx_bytes > $new_rx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0010"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
else |
|
{ |
|
# New bond. Is it on a bridge? |
|
my $bridge_name = ""; |
|
my $bridge_uuid = ""; |
|
if (exists $anvil->data->{interface_to_bridge}{$bond_name}) |
|
{ |
|
$bridge_name = $anvil->data->{interface_to_bridge}{$bond_name}; |
|
$bridge_uuid = $anvil->data->{bridges}{name_to_uuid}{$bridge_name}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_name => $bridge_name, |
|
bridge_uuid => $bridge_uuid, |
|
}}); |
|
} |
|
|
|
# Record the bond |
|
my $bond_uuid = $anvil->Database->insert_or_update_bonds({ |
|
debug => 2, |
|
bond_name => $bond_name, |
|
bond_mode => $new_mode, |
|
bond_mtu => $new_mtu, |
|
bond_operational => $new_operational, |
|
bond_mac_address => $new_mac_address, |
|
bond_primary_interface => $new_primary_interface, |
|
bond_primary_reselect => $new_primary_reselect, |
|
bond_active_interface => $new_active_interface, |
|
bond_mii_polling_interval => $new_mii_polling_interval, |
|
bond_up_delay => $new_up_delay, |
|
bond_down_delay => $new_down_delay, |
|
bond_bridge_uuid => $bridge_uuid, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); |
|
|
|
# Store the bond so our links can find our UUID. |
|
$anvil->data->{bonds}{name_to_uuid}{$bond_name} = $bond_uuid; |
|
$anvil->data->{bonds}{uuid_to_name}{$bond_uuid} = $bond_name; |
|
$anvil->data->{interface}{name_to_uuid}{$bond_name} = $bond_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bonds::name_to_uuid::${bond_name}" => $anvil->data->{bonds}{name_to_uuid}{$bond_name}, |
|
"bonds::uuid_to_name::${bond_uuid}" => $anvil->data->{bonds}{uuid_to_name}{$bond_uuid}, |
|
"interface::name_to_uuid::${bond_name}" => $anvil->data->{interface}{name_to_uuid}{$bond_name}, |
|
}}); |
|
|
|
# Store the rx_bytes and tx_bytes |
|
my $rx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { rx_variable_uuid => $rx_variable_uuid }}); |
|
my $tx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bond::".$bond_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $bond_uuid, |
|
variable_source_table => "bonds", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { tx_variable_uuid => $tx_variable_uuid }}); |
|
|
|
# Report. |
|
my $variables = { |
|
bond_name => $bond_name, |
|
mode => "scan_network_bond_".$new_mode."_name", |
|
number => "scan_network_bond_".$new_mode."_number", |
|
description => "scan_network_bond_".$new_mode."_description", |
|
mtu => $new_mtu, |
|
bridge => $bridge_name ? $bridge_name : "--", |
|
operational => $new_operational eq "up" ? "#!string!unit_0013!#" : "#!string!unit_0014!#", |
|
mac_address => $new_mac_address, |
|
primary_interface => $new_primary_interface, |
|
primary_reselect => $new_primary_reselect, |
|
active_interface => $new_active_interface, |
|
mii_polling_interval => $new_mii_polling_interval, |
|
up_delay => $new_up_delay, |
|
down_delay => $new_down_delay, |
|
say_tx => $anvil->Convert->add_commas({number => $new_tx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
say_rx => $anvil->Convert->add_commas({number => $new_rx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0011", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0011", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
# Look for left over / deleted bonds. |
|
foreach my $bond_uuid (keys %{$anvil->data->{old}{bonds}{bond_uuid}}) |
|
{ |
|
# Skip if already deleted. |
|
next if $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_operational} eq "DELETED"; |
|
|
|
my $bond_name = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{bond_name}; |
|
my $tx_bytes = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{tx_bytes}; |
|
my $rx_bytes = $anvil->data->{old}{bonds}{bond_uuid}{$bond_uuid}{rx_bytes}; |
|
|
|
my $variables = { |
|
name => $bond_name, |
|
tx => $anvil->Convert->add_commas({number => $tx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $tx_bytes}).")", |
|
rx => $anvil->Convert->add_commas({number => $rx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $rx_bytes}).")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0058", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0058", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $bond_uuid = $anvil->Database->insert_or_update_bonds({ |
|
debug => 2, |
|
bond_uuid => $bond_uuid, |
|
'delete' => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bond_uuid => $bond_uuid }}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# Look for changes in the bridges. |
|
sub check_bridges |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Loop through the new stuff found and look for changes. Bridges first. |
|
foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{new}{bridge}}) |
|
{ |
|
# The RX/TX always change. |
|
my $new_bridge_id = $anvil->data->{new}{bridge}{$bridge_name}{id}; |
|
my $new_mac_address = $anvil->data->{new}{bridge}{$bridge_name}{mac_address}; |
|
my $new_mtu = $anvil->data->{new}{bridge}{$bridge_name}{mtu}; |
|
my $new_stp_enabled = $anvil->data->{new}{bridge}{$bridge_name}{stp_enabled}; |
|
my $new_tx_bytes = $anvil->data->{new}{bridge}{$bridge_name}{tx_bytes}; |
|
my $new_rx_bytes = $anvil->data->{new}{bridge}{$bridge_name}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_name => $bridge_name, |
|
new_bridge_id => $new_bridge_id, |
|
new_mac_address => $new_mac_address, |
|
new_mtu => $new_mtu, |
|
new_stp_enabled => $new_stp_enabled, |
|
new_tx_bytes => $new_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
new_rx_bytes => $new_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}}); |
|
|
|
# New or existing? |
|
if (exists $anvil->data->{bridges}{name_to_uuid}{$bridge_name}) |
|
{ |
|
# Existing, look for changes. |
|
my $bridge_uuid = $anvil->data->{bridges}{name_to_uuid}{$bridge_name}; |
|
my $old_bridge_id = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}; |
|
my $old_mac_address = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mac_address}; |
|
my $old_mtu = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_mtu}; |
|
my $old_stp_enabled = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_stp_enabled}; |
|
my $old_tx_bytes = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_bytes}; |
|
my $tx_variable_uuid = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_variable_uuid}; |
|
my $old_rx_bytes = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes}; |
|
my $rx_variable_uuid = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_uuid => $bridge_uuid, |
|
old_bridges_id => $old_bridge_id, |
|
old_mac_address => $old_mac_address, |
|
old_mtu => $old_mtu, |
|
old_stp_enabled => $old_stp_enabled, |
|
old_tx_bytes => $old_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_tx_bytes}).")", |
|
tx_variable_uuid => $tx_variable_uuid, |
|
old_rx_bytes => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", |
|
rx_variable_uuid => $rx_variable_uuid, |
|
}}); |
|
|
|
# Delete the old record so we know it's been processed. |
|
delete $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}; |
|
|
|
my $changes = 0; |
|
if ($new_bridge_id ne $old_bridge_id) |
|
{ |
|
# We're making this a notice level alert as it has no impact on the system, |
|
# unless it's returned from being deleted. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_bridge_id, |
|
new => $new_bridge_id, |
|
}; |
|
|
|
# Did the bridge return? |
|
my $key = "scan_network_alert_0003"; |
|
my $log_level = 2; |
|
my $alert_level = "notice"; |
|
if ($old_bridge_id eq "DELETED") |
|
{ |
|
# Bridge is back. |
|
$key = "scan_network_alert_0026"; |
|
$log_level = 1; |
|
$alert_level = "warning"; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
elsif ($new_mac_address ne $old_mac_address) |
|
{ |
|
# This is odd, but not harmful |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_mac_address, |
|
new => $new_mac_address, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0004", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0004", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
elsif ($new_mtu ne $old_mtu) |
|
{ |
|
# This is a waning, need to ensure the client understands what's going on here. |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_mtu, |
|
new => $new_mtu, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0005", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0005", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
elsif ($new_stp_enabled ne $old_stp_enabled) |
|
{ |
|
# This is a notice |
|
$changes = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_stp_enabled, |
|
new => $new_stp_enabled, |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0006", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_network_alert_0006", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
|
|
if ($changes) |
|
{ |
|
# Update |
|
my $bridge_uuid = $anvil->Database->insert_or_update_bridges({ |
|
debug => 2, |
|
bridge_name => $bridge_name, |
|
bridge_id => $new_bridge_id, |
|
bridge_mac_address => $new_mac_address, |
|
bridge_mtu => $new_mtu, |
|
bridge_stp_enabled => $new_stp_enabled, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_uuid => $bridge_uuid }}); |
|
} |
|
|
|
# Rx and Tx almost always change, so they're only info-level alerts. |
|
if ($new_tx_bytes ne $old_tx_bytes) |
|
{ |
|
if ($tx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $tx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_tx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_tx_bytes}).")", |
|
new => $new_tx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? |
|
my $key = "scan_network_alert_0007"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_tx_bytes > $new_tx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0008"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
if ($new_rx_bytes ne $old_rx_bytes) |
|
{ |
|
if ($rx_variable_uuid) |
|
{ |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_uuid => $rx_variable_uuid, |
|
update_value_only => 1, |
|
variable_value => $new_rx_bytes, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
else |
|
{ |
|
# No value seen before, create |
|
my $variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
|
} |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
old => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", |
|
new => $new_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
# Reset or normal increase? Reset Normal increase |
|
my $key = "scan_network_alert_0009"; |
|
my $alert_level = "info"; |
|
my $log_level = 2; |
|
if ($old_rx_bytes > $new_rx_bytes) |
|
{ |
|
# Reset |
|
$key = "scan_network_alert_0010"; |
|
$alert_level = "notice"; |
|
$log_level = 2; |
|
} |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
message => $key, |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
else |
|
{ |
|
# New, INSERT it and record the new UUID for the interfaces connected on this bridge |
|
# to find. |
|
my $bridge_uuid = $anvil->Database->insert_or_update_bridges({ |
|
debug => 2, |
|
bridge_name => $bridge_name, |
|
bridge_id => $new_bridge_id, |
|
bridge_mac_address => $new_mac_address, |
|
bridge_mtu => $new_mtu, |
|
bridge_stp_enabled => $new_stp_enabled, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_uuid => $bridge_uuid }}); |
|
|
|
$anvil->data->{bridges}{name_to_uuid}{$bridge_name} = $bridge_uuid; |
|
$anvil->data->{bridges}{uuid_to_name}{$bridge_uuid} = $bridge_name; |
|
$anvil->data->{interface}{name_to_uuid}{$bridge_name} = $bridge_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::bridges::name_to_uuid::${bridge_name}" => $anvil->data->{bridges}{name_to_uuid}{$bridge_name}, |
|
"old::bridges::uuid_to_name::${bridge_uuid}" => $anvil->data->{bridges}{uuid_to_name}{$bridge_uuid}, |
|
"interface::name_to_uuid::${bridge_name}" => $anvil->data->{interface}{name_to_uuid}{$bridge_name}, |
|
}}); |
|
|
|
# Store the rx_bytes and tx_bytes |
|
my $rx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::rx_bytes", |
|
variable_value => $new_rx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0290", |
|
variable_section => "stats", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { rx_variable_uuid => $rx_variable_uuid }}); |
|
my $tx_variable_uuid = $anvil->Database->insert_or_update_variables({ |
|
debug => 2, |
|
variable_name => "bridge::".$bridge_name."::tx_bytes", |
|
variable_value => $new_tx_bytes, |
|
variable_default => 0, |
|
variable_description => "striker_0291", |
|
variable_section => "stats", |
|
variable_source_uuid => $bridge_uuid, |
|
variable_source_table => "bridges", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { tx_variable_uuid => $tx_variable_uuid }}); |
|
|
|
# Report. |
|
my $variables = { |
|
bridge_name => $bridge_name, |
|
bridge_id => $new_bridge_id, |
|
mac_address => $new_mac_address, |
|
mtu => $new_mtu, |
|
stp_enabled => $new_stp_enabled, |
|
say_tx => $anvil->Convert->add_commas({number => $new_tx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_tx_bytes}).")", |
|
say_rx => $anvil->Convert->add_commas({number => $new_rx_bytes})." #!string!suffix_0057!# (".$anvil->Convert->bytes_to_human_readable({'bytes' => $new_rx_bytes}).")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0002", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0002", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
} |
|
} |
|
|
|
# Look for left over / deleted bridges. |
|
foreach my $bridge_uuid (keys %{$anvil->data->{old}{bridges}{bridge_uuid}}) |
|
{ |
|
# Skip if already deleted. |
|
if (not $bridge_uuid) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_warning_0001"}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $bridge_name = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_name}; |
|
my $bridge_id = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}; |
|
my $tx_bytes = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_bytes}; |
|
my $rx_bytes = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bridge_uuid => $bridge_uuid, |
|
bridge_name => $bridge_name, |
|
tx_bytes => $tx_bytes, |
|
rx_bytes => $rx_bytes, |
|
}}); |
|
next if $bridge_id eq "DELETED"; |
|
|
|
my $variables = { |
|
name => $bridge_name, |
|
tx => $anvil->Convert->add_commas({number => $tx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $tx_bytes}).")", |
|
rx => $anvil->Convert->add_commas({number => $rx_bytes})." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $rx_bytes}).")", |
|
}; |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0057", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_network_alert_0057", |
|
variables => $variables, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $bridge_uuid = $anvil->Database->insert_or_update_bridges({ |
|
debug => 2, |
|
bridge_uuid => $bridge_uuid, |
|
'delete' => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_uuid => $bridge_uuid }}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This handles health record changes. |
|
sub process_health |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Get the existing health scores, if any. |
|
my $query = " |
|
SELECT |
|
health_uuid, |
|
health_source_name, |
|
health_source_weight |
|
FROM |
|
health |
|
WHERE |
|
health_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
health_source_name LIKE '".$THIS_FILE."%' |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
# We've got an entry in the 'scan_hardware' table, so now we'll look for data in the node and |
|
# services tables. |
|
my $health_source_name = $row->[1]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { health_source_name => $health_source_name }}); |
|
|
|
$anvil->data->{old}{health}{$health_source_name}{health_uuid} = $row->[0]; |
|
$anvil->data->{old}{health}{$health_source_name}{health_source_weight} = $row->[2]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"old::health::${health_source_name}::health_uuid" => $anvil->data->{old}{health}{$health_source_name}{health_uuid}, |
|
"old::health::${health_source_name}::health_source_weight" => $anvil->data->{old}{health}{$health_source_name}{health_source_weight}, |
|
}}); |
|
} |
|
|
|
# Now look for interfaces that are down. For now, that's all we look for to set / clear health. |
|
foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{new}{interface}}) |
|
{ |
|
my $new_duplex = $anvil->data->{new}{interface}{$network_interface_name}{duplex}; |
|
my $new_link_state = $anvil->data->{new}{interface}{$network_interface_name}{link_state}; |
|
my $new_operational = $anvil->data->{new}{interface}{$network_interface_name}{operational}; |
|
my $source_name = $THIS_FILE."::".$network_interface_name."::problem"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
network_interface_name => $network_interface_name, |
|
new_duplex => $new_duplex, |
|
new_link_state => $new_link_state, |
|
new_operational => $new_operational, |
|
source_name => $source_name, |
|
}}); |
|
|
|
# Don't set / clear interfaces that appear down but aren't named ifn/bcn/sn as they're probably |
|
# unconfigured/unusued interfaces. |
|
my $problem = 0; |
|
my $check = 0; |
|
my $monitored = $anvil->Network->is_our_interface({interface => $network_interface_name}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { monitored => $monitored }}); |
|
if ($monitored) |
|
{ |
|
# One we monitor |
|
$check = 1; |
|
} |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { check => $check }}); |
|
|
|
if (($check) && ((not $new_link_state) or ($new_operational eq "down") or ($new_duplex ne "full"))) |
|
{ |
|
$problem = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); |
|
|
|
if (exists $anvil->data->{old}{health}{$source_name}) |
|
{ |
|
# Already registered. |
|
delete $anvil->data->{old}{health}{$source_name}; |
|
} |
|
else |
|
{ |
|
# Has the interface been down for at least a minute? |
|
my $age = $anvil->Alert->check_condition_age({ |
|
debug => 2, |
|
name => $source_name, |
|
host_uuid => $anvil->Get->host_uuid, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); |
|
if ($age > 60) |
|
{ |
|
# New, save. |
|
my ($health_uuid) = $anvil->Database->insert_or_update_health({ |
|
debug => 2, |
|
health_agent_name => $THIS_FILE, |
|
health_source_name => $source_name, |
|
health_source_weight => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { health_uuid => $health_uuid }}); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# Clear any old conditions. |
|
my $age = $anvil->Alert->check_condition_age({ |
|
debug => 2, |
|
clear => 1, |
|
name => $source_name, |
|
host_uuid => $anvil->Get->host_uuid, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); |
|
} |
|
} |
|
|
|
# Any remaining health scores can be deleted. |
|
foreach my $health_source_name (sort {$a cmp $b} keys %{$anvil->data->{old}{health}}) |
|
{ |
|
my $health_uuid = $anvil->data->{old}{health}{$health_source_name}{health_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
health_source_name => $health_source_name, |
|
health_uuid => $health_uuid, |
|
}}); |
|
$anvil->Database->insert_or_update_health({ |
|
debug => 2, |
|
health_uuid => $health_uuid, |
|
'delete' => 1, |
|
}); |
|
} |
|
|
|
return(0); |
|
}
|
|
|