diff --git a/Anvil/Tools/Alert.pm b/Anvil/Tools/Alert.pm index d94ae155..b49b0944 100644 --- a/Anvil/Tools/Alert.pm +++ b/Anvil/Tools/Alert.pm @@ -496,6 +496,51 @@ sub register } } + # Sort the alerts as they come in, if the sort_position was not set. + if ($sort_position == 9999) + { + if (not defined $anvil->data->{sys}{sort_position}{$alert_level}) + { + if (($alert_level eq "critical") or ($alert_level eq "1")) + { + $anvil->data->{sys}{sort_position}{$alert_level} = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::sort_position::${alert_level}" => $anvil->data->{sys}{sort_position}{$alert_level}, + }}); + } + elsif (($alert_level eq "warning") or ($alert_level eq "2")) + { + $anvil->data->{sys}{sort_position}{$alert_level} = 20; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::sort_position::${alert_level}" => $anvil->data->{sys}{sort_position}{$alert_level}, + }}); + } + elsif (($alert_level eq "notice") or ($alert_level eq "3")) + { + $anvil->data->{sys}{sort_position}{$alert_level} = 100; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::sort_position::${alert_level}" => $anvil->data->{sys}{sort_position}{$alert_level}, + }}); + } + else + { + $anvil->data->{sys}{sort_position}{$alert_level} = 1000; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::sort_position::${alert_level}" => $anvil->data->{sys}{sort_position}{$alert_level}, + }}); + } + } + else + { + $anvil->data->{sys}{sort_position}{$alert_level}++; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::sort_position::${alert_level}" => $anvil->data->{sys}{sort_position}{$alert_level}, + }}); + } + $sort_position = $anvil->data->{sys}{sort_position}{$alert_level}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { sort_position => $sort_position }}); + } + # If the alert level was a string, convert it to the numerical version. Also check that we've got a # sane alert level at all. if (lc($alert_level) eq "critical") diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 00f99b19..77a4a0a5 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -6955,7 +6955,7 @@ WHERE DELETE FROM health WHERE - health_uuid = ".$anvil->Database->quote($health_uuid)." + health_uuid = ".$anvil->Database->quote($health_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); $anvil->Database->write({uuid => $uuid, query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__}); diff --git a/notes b/notes index e99ab677..b07f3b27 100644 --- a/notes +++ b/notes @@ -1345,6 +1345,56 @@ May 02 13:35:21 zo-a01n02.zennioptical.com setroubleshoot[5333]: SELinux is prev # ausearch -c 'virsh' --raw | audit2allow -M my-virsh # semodule -X 300 -i my-virsh.pp - - - \ No newline at end of file +==================================== + +### Edit corosync.conf to add 'token' and the node names on one node +# diff -u /root/corosync.conf /etc/corosync/corosync.conf +--- /root/corosync.conf 2021-07-06 15:01:18.956703529 -0400 ++++ /etc/corosync/corosync.conf 2021-07-06 15:15:23.438494607 -0400 +@@ -4,17 +4,20 @@ + transport: knet + crypto_cipher: aes256 + crypto_hash: sha256 ++ token: 10000 + } + + nodelist { + node { +- ring0_addr: an-a02n01 ++ ring0_addr: an-a02n01.bcn1 ++ ring1_addr: an-a02n01.sn1 + name: an-a02n01 + nodeid: 1 + } + + node { +- ring0_addr: an-a02n02 ++ ring0_addr: an-a02n02.bcn1 ++ ring1_addr: an-a02n02.sn1 + name: an-a02n02 + nodeid: 2 + } + +### Update the peer with the new corosync.conf and then tell pacemaker to reload +pcs cluster sync +pcs cluster reload corosync + +### Verify; +corosync-cmapctl | grep -e totem.token -e knet +runtime.config.totem.interface.0.knet_ping_interval (u32) = 2500 +runtime.config.totem.interface.0.knet_ping_timeout (u32) = 5000 +runtime.config.totem.interface.1.knet_ping_interval (u32) = 2500 +runtime.config.totem.interface.1.knet_ping_timeout (u32) = 5000 +runtime.config.totem.knet_compression_level (i32) = 0 +runtime.config.totem.knet_compression_model (str) = none +runtime.config.totem.knet_compression_threshold (u32) = 0 +runtime.config.totem.knet_pmtud_interval (u32) = 30 +runtime.config.totem.token (u32) = 10000 +runtime.config.totem.token_retransmit (u32) = 2380 +runtime.config.totem.token_retransmits_before_loss_const (u32) = 4 +runtime.config.totem.token_warning (u32) = 75 +totem.token (u32) = 10000 +totem.transport (str) = knet + + +==================================== diff --git a/scancore-agents/scan-hardware/scan-hardware b/scancore-agents/scan-hardware/scan-hardware index 53da6c5b..184f05d4 100755 --- a/scancore-agents/scan-hardware/scan-hardware +++ b/scancore-agents/scan-hardware/scan-hardware @@ -1263,10 +1263,10 @@ INSERT INTO UPDATE scan_hardware_ram_modules SET - scan_hardware_ram_module_manufacturer = 'VANISHED', - modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." + scan_hardware_ram_module_manufacturer = 'VANISHED', + modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE - scan_hardware_ram_module_uuid = ".$anvil->Database->quote($scan_hardware_ram_module_uuid)." + scan_hardware_ram_module_uuid = ".$anvil->Database->quote($scan_hardware_ram_module_uuid)." ;"; # Now record the query in the array $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); diff --git a/scancore-agents/scan-network/scan-network b/scancore-agents/scan-network/scan-network index 2f045d08..4c16e0cd 100755 --- a/scancore-agents/scan-network/scan-network +++ b/scancore-agents/scan-network/scan-network @@ -113,15 +113,6 @@ sub collect_data directory => $directory, }}); - # We'll need to know what interfaces to remove, if any. This will store the interfaces we've seen and - # any others will be removed. - $anvil->data->{seen} = { - interface => {}, - bond => {}, - bridge => {}, - ip => {}, - }; - # 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 }}); @@ -416,17 +407,6 @@ sub collect_data } } - # Record this interface - $anvil->data->{seen}{$type}{$interface} = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "seen::${type}::${interface}" => $anvil->data->{seen}{$type}{$interface} }}); - - # Record the IP, if set. - if ($ip_address) - { - $anvil->data->{seen}{ip}{$ip_address} = $interface; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "seen::ip::${ip_address}" => $anvil->data->{seen}{ip}{$ip_address} }}); - } - # Store new information we found. $anvil->data->{network}{$local_host}{interface}{$interface}{active_interface} = $active_interface; $anvil->data->{network}{$local_host}{interface}{$interface}{bond_mode} = $bond_mode; @@ -514,6 +494,11 @@ sub collect_data 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 @@ -572,7 +557,9 @@ sub collect_data { # Store the interface $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}; @@ -584,7 +571,9 @@ sub collect_data $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}::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}, @@ -773,8 +762,8 @@ WHERE $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_operational} = $row->[6]; $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_duplex} = $row->[7]; $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_medium} = $row->[8]; - $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = defined $row->[9] ? $row->[9] : 'NULL'; - $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = defined $row->[10] ? $row->[10] : 'NULL'; + $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bond_uuid} = defined $row->[9] ? $row->[9] : ''; + $anvil->data->{old}{network_interfaces}{network_interface_uuid}{$network_interface_uuid}{network_interface_bridge_uuid} = defined $row->[10] ? $row->[10] : ''; $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; @@ -796,11 +785,15 @@ WHERE "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->{old}{network_interfaces}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; - $anvil->data->{old}{network_interfaces}{mac_to_uuid}{$network_interface_mac_address} = $network_interface_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}{$network_interface_mac_address} = $network_interface_uuid; + $anvil->data->{interface}{name_to_uuid}{$network_interface_name} = $network_interface_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "old::network_interfaces::name_to_uuid::${network_interface_name}" => $anvil->data->{old}{network_interfaces}{name_to_uuid}{$network_interface_name}, - "old::network_interfaces::mac_to_uuid::${network_interface_mac_address}" => $anvil->data->{old}{network_interfaces}{mac_to_uuid}{$network_interface_mac_address}, + "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_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}, }}); } @@ -825,7 +818,8 @@ SELECT bond_up_delay, bond_down_delay, bond_mac_address, - bond_operational + bond_operational, + bond_bridge_uuid FROM bonds WHERE @@ -840,11 +834,13 @@ WHERE }}); foreach my $row (@{$results}) { - my $bond_uuid = $row->[0]; - my $bond_name = $row->[1]; + 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_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. @@ -878,6 +874,7 @@ WHERE $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; @@ -894,15 +891,20 @@ WHERE "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->{old}{bonds}{name_to_uuid}{$bond_name} = $bond_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 => { - "old::bonds::name_to_uuid::${bond_name}" => $anvil->data->{old}{bonds}{name_to_uuid}{$bond_name}, + "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}, }}); } @@ -985,9 +987,13 @@ WHERE "old::bridges::bridge_uuid::${bridge_uuid}::tx_variable_uuid" => $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{tx_variable_uuid}, }}); - $anvil->data->{old}{bridges}{name_to_uuid}{$bridge_name} = $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->{old}{bridges}{name_to_uuid}{$bridge_name}, + "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}, }}); } @@ -1000,433 +1006,1871 @@ sub find_changes my ($anvil) = @_; check_bridges($anvil); - #check_bonds($anvil); - -=cut - # Store the bond - $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}::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}}).")", - }}); - - # Store the interface - $anvil->data->{new}{interface}{$interface}{bond_uuid} = ""; - $anvil->data->{new}{interface}{$interface}{bridge_uuid} = ""; - $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}::bond_uuid" => $anvil->data->{new}{interface}{$interface}{bond_uuid}, - "new::interface::${interface}::bridge_uuid" => $anvil->data->{new}{interface}{$interface}{bridge_uuid}, - "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. - $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}, - }}); -=cut - - return(0); -} + check_bonds($anvil); + check_interfaces($anvil); + check_ip_addresses($anvil); -# Look for changes in the bonds. -sub bridge_name -{ - my ($anvil) = @_; - - foreach my $bond_name (sort {$a cmp $b} keys %{$anvil->data->{new}{bond}}) - { - # Store the bond - my $new_mode = $anvil->data->{new}{bond}{$bond_name}{mode}; - my $new_mtu = $anvil->data->{new}{bond}{$bond_name}{mtu}; - my $new_master = $anvil->data->{new}{bond}{$bond_name}{master}; - my $new_link_state = $anvil->data->{new}{bond}{$bond_name}{link_state}; - 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_master => $new_master, - new_link_state => $new_link_state, - 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_bridge_uuid => $new_bridge_uuid, - 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->{old}{bridges}{name_to_uuid}{$new_bridge_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - new_bridge_uuid => $new_bridge_uuid, - new_bridge_uuid => $new_bridge_uuid, - }}); - } - - } - - return(0); } -# Look for changes in the bridges. -sub check_bridges +# Handle IP addresses +sub check_ip_addresses { 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}}) + foreach my $ip_address (sort {$a cmp $b} keys %{$anvil->data->{new}{ip_address}}) { - # 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}; + 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_on_uuid = $anvil->data->{interface}{name_to_uuid}{$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 => { - 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}).")", + ip_address => $ip_address, + on_interface => $on_interface, + new_on_type => $new_on_type, + new_on_uuid => $new_on_uuid, + new_subnet_mask => $new_subnet_mask, + new_gateway => $new_gateway, + new_default_gateway => $new_default_gateway, + new_dns => $new_dns, }}); - # New or existing? - if (exists $anvil->data->{old}{bridges}{name_to_uuid}{$bridge_name}) + if (exists $anvil->data->{old}{ip_addresses}{ip_to_uuid}{$ip_address}) { - # Existing, look for changes. - my $bridge_uuid = $anvil->data->{old}{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 $old_rx_bytes = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{rx_bytes}; + # 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 => { - 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}).")", - old_rx_bytes => $old_rx_bytes." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $old_rx_bytes}).")", + 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; - if ($new_bridge_id ne $old_bridge_id) + + # These will always change together. + if (($new_on_type ne $old_on_type) or ($new_on_uuid ne $old_on_uuid)) { - # We're making this a notice level alert as it has no impact on the system + # 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 = { - name => $bridge_name, - old => $old_bridge_id, - new => $new_bridge_id, + ip_address => $ip_address, + old => $say_old_interface, + new => $on_interface, }; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_network_alert_0003", variables => $variables}); + $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_0003", + message => "scan_network_alert_0050", variables => $variables, set_by => $THIS_FILE, }); } - elsif ($new_mac_address ne $old_mac_address) + if ($new_subnet_mask ne $old_subnet_mask) { - # This is odd, but not harmful + # 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 = { - name => $bridge_name, - old => $old_mac_address, - new => $new_mac_address, + 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 => 2, key => "scan_network_alert_0004", variables => $variables}); + $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_0004", + message => "scan_network_alert_0051", variables => $variables, set_by => $THIS_FILE, }); } - elsif ($new_mtu ne $old_mtu) + if ($new_gateway ne $old_gateway) { - # This is a waning, need to ensure the client understands what's going on here. + # 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 = { - name => $bridge_name, - old => $old_mtu, - new => $new_mtu, + 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_0005", variables => $variables}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0052", variables => $variables}); $anvil->Alert->register({ - alert_level => "warning", - message => "scan_network_alert_0005", + alert_level => "notice", + message => "scan_network_alert_0052", variables => $variables, set_by => $THIS_FILE, }); } - elsif ($new_stp_enabled ne $old_stp_enabled) + if ($new_default_gateway ne $old_default_gateway) { - # This is a notice + # 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 = { - name => $bridge_name, - old => $old_stp_enabled, - new => $new_stp_enabled, + 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 => 2, key => "scan_network_alert_0006", variables => $variables}); + $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_0006", + message => "scan_network_alert_0053", 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 ($new_dns ne $old_dns) { - if ($anvil->data->{new}{bridge}{$bridge_name}{tx_variable_uuid}) - { - my $variable_uuid = $anvil->Database->insert_or_update_variables({ - debug => 2, - variable_uuid => $anvil->data->{new}{bridge}{$bridge_name}{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_source_uuid => $anvil->Get->host_uuid, - variable_source_table => "hosts", - 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 }}); - } + # 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 = { - 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}).")", + ip_address => $ip_address, + interface => $on_interface, + old => $old_dns eq "" ? "--" : $old_dns, + new => $new_dns eq "" ? "--" : $new_dns, }; - # 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->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0054", variables => $variables}); $anvil->Alert->register({ - alert_level => $alert_level, - message => $key, + alert_level => "notice", + message => "scan_network_alert_0054", variables => $variables, set_by => $THIS_FILE, }); } - if ($new_rx_bytes ne $old_rx_bytes) + + # We only care about 'old_note' if it's set to 'DELETED'. + if ($old_note eq "DELETED") { - if ($anvil->data->{new}{bridge}{$bridge_name}{rx_variable_uuid}) - { - my $variable_uuid = $anvil->Database->insert_or_update_variables({ - debug => 2, - variable_uuid => $anvil->data->{new}{bridge}{$bridge_name}{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_source_uuid => $anvil->Get->host_uuid, - variable_source_table => "hosts", - 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 }}); - } + # 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 = { - 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}).")", + ip_address => $ip_address, + interface => $on_interface, }; - # 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->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0055", variables => $variables}); $anvil->Alert->register({ - alert_level => $alert_level, - message => $key, + 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, 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, + # 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 => { bridge_uuid => $bridge_uuid }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ip_address_uuid => $ip_address_uuid }}); - $anvil->data->{old}{bridges}{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->{old}{bridges}{name_to_uuid}{$bridge_name}, - }}); + # 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, + }; - # Store the rx_bytes and tx_bytes + $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. + 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}; + + 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 }}); + } + + return(0); +} + +# Look for changes in network interfaces. +sub check_interfaces +{ + my ($anvil) = @_; + + foreach my $network_interface_name (sort {$a cmp $b} keys %{$anvil->data->{new}{interface}}) + { + 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_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 (($new_bridge_name) && (exists $anvil->data->{interface_to_bridge}{$new_bridge_name})) + { + # This bond is on a bridge + $new_bridge_name = $anvil->data->{interface_to_bridge}{$network_interface_name}; + $new_bridge_uuid = $anvil->data->{bridges}{name_to_uuid}{$network_interface_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->{network_interfaces}{name_to_uuid}{$network_interface_name}) + { + # Existing. Changes? + my $network_interface_uuid = $anvil->data->{network_interfaces}{name_to_uuid}{$network_interface_name}; + 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_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; + 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 => "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_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"; + if ($new_duplex eq "full") + { + # Duplex is back to being OK + $clear = 1; + $key = "scan_network_alert_0037"; + } + + 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 => "warning", + clear_alert => $clear, + message => $key, + variables => $variables, + set_by => $THIS_FILE, + }); + } + if ($new_link_state ne $old_link_state) + { + # 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_0038"; + if ($new_link_state) + { + # Link is up + $clear = 1; + $key = "scan_network_alert_0039"; + } + + 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 => "warning", + 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"; + 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"; + } + + 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 => "warning", + 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, + }; + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_alert_0044", variables => $variables}); + $anvil->Alert->register({ + alert_level => "notice", + message => "scan_network_alert_0044", + 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"; + } + + $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"; + } + + $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 ($changes) + { + my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({ + debug => 2, + network_interface_bond_uuid => $new_bond_uuid, + network_interface_bridge_uuid => $new_bridge_uuid, + network_interface_name => $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 }}); + } + + # Speed changes? Likely. + + # 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 + my $network_interface_uuid = $anvil->Database->insert_or_update_network_interfaces({ + debug => 2, + network_interface_bond_uuid => $new_bond_uuid, + network_interface_bridge_uuid => $new_bridge_uuid, + network_interface_name => $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->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}, + }}); + + # 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}).")", + }; + + $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_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_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_source_uuid => $anvil->Get->host_uuid, - variable_source_table => "hosts", variable_value => $new_rx_bytes, variable_default => 0, variable_description => "striker_0290", @@ -1438,8 +2882,6 @@ sub check_bridges my $tx_variable_uuid = $anvil->Database->insert_or_update_variables({ debug => 2, variable_name => "bridge::".$bridge_name."::tx_bytes", - variable_source_uuid => $anvil->Get->host_uuid, - variable_source_table => "hosts", variable_value => $new_tx_bytes, variable_default => 0, variable_description => "striker_0291", @@ -1456,6 +2898,8 @@ sub check_bridges 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}); @@ -1467,7 +2911,47 @@ sub check_bridges }); } } - + + # Look for left over / deleted bridges. + foreach my $bridge_uuid (keys %{$anvil->data->{old}{bridges}{bridge_uuid}}) + { + # Skip if already deleted. + die if not $bridge_uuid; + + 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); } @@ -1475,6 +2959,118 @@ sub check_bridges 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, + }}); + + my $problem = 0; + if ((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 + { + 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 > 300) + { + # New, save. + my ($health_uuid) = $anvil->Database->insert_or_update_health({ + debug => 2, + health_agent_name => $THIS_FILE, + 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 condition. + 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); } diff --git a/scancore-agents/scan-network/scan-network.xml b/scancore-agents/scan-network/scan-network.xml index 6f49c6e4..eabc4652 100644 --- a/scancore-agents/scan-network/scan-network.xml +++ b/scancore-agents/scan-network/scan-network.xml @@ -16,10 +16,12 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_hardware_l The bridge: [#!variable!bridge!#] was a libvirtd NAT'ed bridge and has been removed. A new bridge: [#!variable!bridge_name!#] has been found; -- Bridge ID: . [#!variable!bridge_id!#] -- MAC Address: [#!variable!mac_address!#] -- MTU (bytes): [#!variable!mtu!#] -- STP Enabled: [#!variable!stp_enabled!#] +- Bridge ID: ... [#!variable!bridge_id!#] +- MAC Address: . [#!variable!mac_address!#] +- MTU (bytes): . [#!variable!mtu!#] +- STP Enabled: . [#!variable!stp_enabled!#] +- Data Sent: ... [#!variable!say_tx!#] +- Data Received: [#!variable!say_rx!#] The bridge: [#!variable!name!#] bridge ID has changed from: [#!variable!old!#] to: [#!variable!new!#]. The bridge: [#!variable!name!#] MAC address has changed from: [#!variable!old!#] to: [#!variable!new!#]. @@ -29,10 +31,191 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_hardware_l The bridge: [#!variable!name!#] transmitted (tx) size has dropped from: [#!variable!old!#] to: [#!variable!new!#]. This is expected after a network interface is restart. The bridge: [#!variable!name!#] received (rx) size has grown from: [#!variable!old!#] to: [#!variable!new!#]. The bridge: [#!variable!name!#] received (rx) size has dropped from: [#!variable!old!#] to: [#!variable!new!#]. This is expected after a network interface is restart. + A new bond: [#!variable!bond_name!#] has been found; +- Bond mode (see below): . [#!variable!mode!#] +- MTU (bytes): ........... [#!variable!mtu!#] +- Connected to Bridge: ... [#!variable!bridge!#] +- Operation: ............. [#!variable!operational!#] +- MAC Address: ........... [#!variable!mac_address!#] +- Primary Interface: ..... [#!variable!primary_interface!#] +- Primary Reselect Policy: [#!variable!primary_reselect!#] +- Active Interface: ...... [#!variable!active_interface!#] +- Link Check Interval: ... [#!variable!mii_polling_interval!#] ms +- Link Up Delay: ......... [#!variable!up_delay!#] ms +- Link Down Delay: ....... [#!variable!down_delay!#] ms +- Data Sent: ............. [#!variable!say_tx!#] +- Data Received: ......... [#!variable!say_rx!#] + +Bond Mode Description (Mode number: [#!variable!number!#]): +======== +#!variable!description!# +======== + + The bond: [#!variable!name!#] mode has changed from: [#!variable!old!#] to: [#!variable!new!#]. This should not normally change! +Descriptions; + +* New (Mode number: [#!variable!new_number!#]): +======== +#!variable!new_description!# +======== + +* Old (Mode number: [#!variable!old_number!#]): +======== +#!variable!old_description!# +======== + + The bond: [#!variable!name!#] MTU byte size has increased from: [#!variable!old!#] to: [#!variable!new!#]. + The bond: [#!variable!name!#] MTU byte size has dropped from: [#!variable!old!#] to: [#!variable!new!#]. Note that any device with a higher MTU may fail to transmit packages larger than the new byte size! + The bridge that the bond: [#!variable!name!#] connects to has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The bond: [#!variable!name!#] has gone down! There are no operational links available. The operational status has changed from: [#!variable!old!#] to: [#!variable!new!#]. +Note: If this is a Storage Network directly connected to the peer, and the peer is down, then this is expected. Otherwise, this is likely a serious problem. + + The bond: [#!variable!name!#] is back up! The operational status has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The bond: [#!variable!name!#] MAC address has changed from: [#!variable!old!#] to: [#!variable!new!#]. This can happen if the active interface has changed. + The bond: [#!variable!name!#]'s primary interface has changed from: [#!variable!old!#] to: [#!variable!new!#]. Did an admin change this? + The bond: [#!variable!name!#]'s primary reselect policy has changed from: [#!variable!old!#] to: [#!variable!new!#]. Did an admin change this? + The bond: [#!variable!name!#]'s active interface is no longer the primary interface. The active interface changed from: [#!variable!old!#] to: [#!variable!new!#]. + The bond: [#!variable!name!#]'s active interface is back to being the primary interface. The active interface changed from: [#!variable!old!#] to: [#!variable!new!#]. + The bond: [#!variable!name!#]'s MII polling interval, that is how often it checks for a link in case the interface's driver fails to tell us a link state has changed, has changed from: [#!variable!old!#] ms to: [#!variable!new!#] ms. Did an admin change this? + The bond: [#!variable!name!#]'s up delay, that is how long it waits between the link coming up and when the linux is "ready to use", has changed from: [#!variable!old!#] ms to: [#!variable!new!#] ms. Did an admin change this? + The bond: [#!variable!name!#]'s down delay, that is how long after the link drops that the link is considered "down", has changed from: [#!variable!old!#] ms to: [#!variable!new!#] ms. Did an admin change this? This should always be '0'. + The bridge: [#!variable!name!#] woth bridge ID: [#!variable!new!#] has returned! + The bond: [#!variable!name!#] is back and it is up! + The bond: [#!variable!name!#] is back, but it's operational status is still down. It should come up once at least one interface cmes up. + A new network interface: [#!variable!interface_name!#] has been found; +- Member of bond: .. [#!variable!bond_name!#] +- Connect to bridge: [#!variable!bridge_name!#] +- Duplex mode: ..... [#!variable!duplex!#] +- Link state: ...... [#!variable!link_state!#] +- Operational State: [#!variable!operational!#] +- MAC address: ..... [#!variable!mac_address!#] +- Medium: .......... [#!variable!medium!#] (unknown usually means virtual) +- MTU (bytes): ..... [#!variable!mtu!#] +- Link speed (Mbps): [#!variable!speed!#] +- Data Sent: ....... [#!variable!say_tx!#] +- Data Received: ... [#!variable!say_rx!#] + + The network interface: [#!variable!name!#] is now a member of the bond: [#!variable!new!#]. + The network interface: [#!variable!name!#] is no longer a member of the bond: [#!variable!new!#]. + The network interface: [#!variable!name!#] is has moved from the bond: [#!variable!old!#] to: [#!variable!new!#]. + The network interface: [#!variable!name!#] is now connected to the bridge: [#!variable!new!#]. + The network interface: [#!variable!name!#] is no longer connected to the bridge: [#!variable!new!#]. + The network interface: [#!variable!name!#] is has moved from the bridge: [#!variable!old!#] to: [#!variable!new!#]. + The network interface: [#!variable!name!#] duplex has changed from: [#!variable!old!#] to: [#!variable!new!#]. When 'half' duplex, the cable is likely bad and data can only be transmitted or received, not both at the same time. + The network interface: [#!variable!name!#] duplex is back to being "full" (transmit and receive can happen at the same time). + The network interface: [#!variable!name!#] is down! + The network interface: [#!variable!name!#] is back up! + The network interface: [#!variable!name!#] is no longer operational! + The network interface: [#!variable!name!#] is operational again! + The network interface: [#!variable!name!#] is back, and it is operational! + The network interface: [#!variable!name!#] is back, but it is not operational yet. + The network interface: [#!variable!name!#] MAC address has changed from: [#!variable!old!#] to: [#!variable!new!#]. This is normal and expected when a network interface (or the mainboard it's on) is changed. + The network interface: [#!variable!name!#] medium has changed from: [#!variable!old!#] to: [#!variable!new!#]. This is normal and expected when a network interface (or the mainboard it's on) is changed to a different medium (like twisted-pair to fiber optics). + The network interface: [#!variable!name!#] MTU byte size has increased from: [#!variable!old!#] to: [#!variable!new!#]. + The network interface: [#!variable!name!#] MTU byte size has dropped from: [#!variable!old!#] to: [#!variable!new!#]. Note that any device with a higher MTU may fail to transmit packages larger than the new byte size! + The network interface: [#!variable!name!#] speed (in Mbps) has dropped from: [#!variable!old!#] to: [#!variable!new!#]! Is the network cable failing? + The network interface: [#!variable!name!#] speed (in Mbps) has increaed from: [#!variable!old!#] to: [#!variable!new!#]. + The IP address: [#!variable!ip_address!#] has moved from the interface: [#!variable!old!#] to: [#!variable!new!#]. + The subnet mask on the interface: [#!variable!interface!#] has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The gateway on the interface: [#!variable!interface!#] associated with the IP address: [#!variable!ip_address!#] has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The default gateway status on the interface: [#!variable!interface!#] associated with the IP address: [#!variable!ip_address!#] has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The DNS servers on the interface: [#!variable!interface!#] associated with the IP address: [#!variable!ip_address!#] has changed from: [#!variable!old!#] to: [#!variable!new!#]. + The IP address: [#!variable!ip_address!#] is being used again. It has been assigned to the interface: [#!variable!interface!#]. + The new IP address: [#!variable!ip_address!#] has been found. +- On interface: .. [#!variable!interface!#] +- Subnet Mask: ... [#!variable!subnet_mask!#] +- Gateway: ....... [#!variable!gateway!#] +- Default Gateway? [#!variable!default_gateway!#] +- DNS: ........... [#!variable!dns!#] + + The bridge: [#!variable!name!#] appears to have been stopped or deleted. The last time we saw it, it had transmitted: [#!variable!tx!#] and received: [#!variable!rx!#]. + The bond: [#!variable!name!#] appears to have been stopped or deleted. The last time we saw it, it had transmitted: [#!variable!tx!#] and received: [#!variable!rx!#]. + The network interface: [#!variable!name!#] appears to have been removed. The last time we saw it, it had transmitted: [#!variable!tx!#] and received: [#!variable!rx!#]. + The IP address: [#!variable!ip!#] appears to no longer be used on this machine. Failed to read the network interface speed from the file: [#!variable!file!#]. Ignoring interface. The network interface Speed: [#!variable!speed!#] as read from: [#!variable!file!#] isn't numeric. Ignoring interface. + + Balance Round-Robin + 0 + Round-robin policy: Transmit packets in sequential order from the first available slave through the last. + +This mode provides load balancing and fault tolerance. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + Active-Backup + 1 + Active-backup policy: Only one slave in the bond is active. A different slave becomes active if, and only if, the active slave fails. The bond's MAC address is externally visible on only one port (network adapter) to avoid confusing the switch. +When a failover occurs in active-backup mode, bonding will issue one or more gratuitous ARPs on the newly active slave. One gratuitous ARP is issued for the bonding master interface and each VLAN interfaces configured above it, provided that the interface has at least one IP address configured. Gratuitous ARPs issued for VLAN interfaces are tagged with the appropriate VLAN id. + +This mode provides fault tolerance. + +This is the *only* mode supported by the Anvil! Intelligent Availability™ platform. + + Balance XOR (exclusive-or) + 2 + XOR policy: Transmit based on the selected transmit hash policy. The default policy is a simple [(sourceMAC address XOR'd with destination MAC address) modulo slave count]. Alternate transmit policies may be selected via the xmit_hash_policy option, described below. + +This mode provides load balancing and fault tolerance. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + Broadcast + 3 + Broadcast policy: transmits everything on all slave interfaces. +This mode provides fault tolerance. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + Link Aggregation (802.3ad) + 4 + IEEE 802.3ad Dynamic link aggregation. Creates aggregation groups that share the same speed and duplex settings. Utilizes all slaves in the active aggregator according to the 802.3ad specification. + +Slave selection for outgoing traffic is done according to the transmit hash policy, which may be changed from the default simple XOR policy via the xmit_hash_policy option, documented below. Note that not all transmit policies may be 802.3ad compliant, particularly in regards to the packet mis-ordering requirements of section 43.2.4 of the 802.3ad standard. Differing peer implementations will have varying tolerances for noncompliance. + +Prerequisites: + +1. Ethtool support in the base drivers for retrieving the speed and duplex of each slave. + +2. A switch that supports IEEE 802.3ad Dynamic link aggregation. + +Most switches will require some type of configuration to enable 802.3ad mode. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + Adaptive Transmit Load Balancing + 5 + Adaptive transmit load balancing: channel bonding that does not require any special switch support. The outgoing traffic is distributed according to the current load (computed relative to the speed) on each slave. Incoming traffic is received by the current slave. If the receiving slave fails, another slave takes over the MAC address of the failed receiving slave. + +Prerequisite: + +Ethtool support in the base drivers for retrieving the speed of each slave. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + Active Load Balancing + 6 + Adaptive load balancing: includes balance-tlb plus receive load balancing (rlb) for IPV4 traffic, and does not require any special switch support. The receive load balancing is achieved by ARP negotiation. The bonding driver intercepts the ARP Replies sent by the local system on their way out and overwrites the source hardware address with the unique hardware address of one of the slaves in the bond such that different peers use different hardware addresses for the server. + +Receive traffic from connections created by the server is also balanced. When the local system sends an ARP Request the bonding driver copies and saves the peer's IP information from the ARP packet. When the ARP Reply arrives from the peer, its hardware address is retrieved and the bonding driver initiates an ARP reply to this peer assigning it to one of the slaves in the bond. A problematic outcome of using ARP negotiation for balancing is that each time that an ARP request is broadcast it uses the hardware address of the bond. Hence, peers learn the hardware address of the bond and the balancing of receive traffic collapses to the current slave. This is handled by sending updates (ARP Replies) to all the peers with their individually assigned hardware address such that the traffic is redistributed. Receive traffic is also redistributed when a new slave is added to the bond and when an inactive slave is re-activated. The receive load is distributed sequentially (round robin) among the group of highest speed slaves in the bond. + +When a link is reconnected or a new slave joins the bond the receive traffic is redistributed among all active slaves in the bond by initiating ARP Replies with the selected MAC address to each of the clients. The updelay parameter (detailed below) must be set to a value equal or greater than the switch's forwarding delay so that the ARP Replies sent to the peers will not be blocked by the switch. + +Prerequisites: + +1. Ethtool support in the base drivers for retrieving the speed of each slave. + +2. Base driver support for setting the hardware address of a device while it is open. This is required so that there will always be one slave in the team using the bond hardware address (the curr_active_slave) while having a unique hardware address for each slave in the bond. If the curr_active_slave fails its hardware address is swapped with the new curr_active_slave that was chosen. + +This mode is NOT supported by the Anvil! Intelligent Availability™ platform! + + + + + + diff --git a/share/words.xml b/share/words.xml index 60381f2c..7d62a485 100644 --- a/share/words.xml +++ b/share/words.xml @@ -2578,6 +2578,7 @@ If you are comfortable that the target has changed for a known reason, you can s Ebps Zbps Ybps + Bytes Test