#!/usr/bin/perl # # This uses data in the 'fences' database table (any agent starting with 'fence_apc_*' to get a list of APC- # brand PDUs to scan. # # Examples; # # Exit codes; # 0 - Success # 1 - Something went wrong, agent aborted run. # # 255 - The host's UUID isn't in the hosts table yet, ScanCore itself hasn't been run. # # Use my modules. use strict; use warnings; use Anvil::Tools; use Data::Dumper; use Socket; no warnings 'recursion'; =cut OIDs of interest; State data .1.3.6.1.4.1.318.1.1.4.1.5.0 = Serial Number <- Global ID .1.3.6.1.4.1.318.1.1.4.1.4.0 = Model Number .1.3.6.1.4.1.318.1.1.4.1.3.0 = Date of manufacture (mm/dd/yyyy, if 'yy' year 2000 = '00') .1.3.6.1.4.1.318.1.1.4.1.2.0 = Firmware version .1.3.6.1.4.1.318.1.1.4.1.1.0 = Hardware version (never changes) Variables .1.3.6.1.2.1.1.3.0 = Uptime (in timeticks, 900 = 9 seconds) .1.3.6.1.4.1.318.1.1.12.1.16.0 = Wattage draw (seems to be for the full device, not per phase) # Phase info .1.3.6.1.4.1.318.1.1.12.2.1.1.0 = Max Amperage out per phase .1.3.6.1.4.1.318.1.1.12.2.1.2.0 = Number of phases on the PDU .1.3.6.1.4.1.318.1.1.12.2.2.1.1.2.1 = Low amp threshold. (0 = Disabled; No alarm on low power. Any digit is the minimum amperage under which we throw an alert) (NOTE: last digit is phase number, so .1 == phase 1) .1.3.6.1.4.1.318.1.1.12.2.2.1.1.3.1 = High amperage warning threshold. If the power draw exceeds this, throw a warning alert, warn on equal or greater .1.3.6.1.4.1.318.1.1.12.2.2.1.1.4.1 = High amperage critical threshold. If the power draw exceeds this, throw a critical alert (breaker is about to pop), warn on equal or greater (NOTE: Default == max amp per phase, we should set it lower, Max - 2?) .1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.1 = Current Amperage on the phase, in 1/10 Amp (x10 to get Amp) Port information .1.3.6.1.4.1.318.1.1.4.4.1.0 = Number of outlets (ie: 8) .1.3.6.1.4.1.318.1.1.4.4.2.1.2.n = Pending action on state? (1 = command pending, 2 = no command pending, 3 = unknown. If all ports are '3', power cycle is required. If the all devices on the peer report Power is OK, do so immediately) .1.3.6.1.4.1.318.1.1.4.4.2.1.3.n = Current state (read: 1 = on, 2 = off, 4 = unknown --- write: 1 = turn on, 2 = turn off, 3 = cycle (~5s), 5 = on after 'sPDUOutletPowerOnTime' delay, 6 = off after sPDUOutletPowerOffTime delay, 7 = off after sPDUOutletPowerOffTime delay, wait sPDUOutletRebootDuration time, then back on.) .1.3.6.1.4.1.318.1.1.4.5.2.1.3.n = Outlet name (default is 'Outlet N'), Can be read or set, max 20 chars. <- Set this when we map the Anvil! .1.3.6.1.4.1.318.1.1.4.5.2.1.2.n = Power on delay (in seconds), default is '0' seconds. (-1 = stay off, 0 = on with PDU, X = number of seconds to wait before powering on) .1.3.6.1.4.1.318.1.1.4.5.2.1.4.n = Power off delay (in seconds) (-1 = stay on, 0 = off with PDU, X = number of seconds to wait before powering off) .1.3.6.1.4.1.318.1.1.4.5.2.1.5.n = Reboot delay (sleep time), default is '5' seconds. .1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.n = Phase that this outlet is in Network data (NOTE: .1 is the loopback interface, .2 is the physical interface) .1.3.6.1.2.1.2.2.1.4.2 = MTU size .1.3.6.1.2.1.2.2.1.5.2 = Link speed (in bps) .1.3.6.1.2.1.2.2.1.6.2 = MAC address - This is losing the first nibble... It returns type STRING instead of Hex-STRING, even if -Ox is used. If I point to the APC MIB, it returns OK. This is what we should be using. .1.3.6.1.6.3.10.2.1.1.0 = MAC address (with some prefix) in hex. Not sure if this is supported on other PDUs though... =cut # Disable buffering $| = 1; # Prevent a discrepency between UID/GID and EUID/EGID from throwing an error. $< = $>; $( = $); my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $anvil = Anvil::Tools->new(); # Make sure we're running as 'root' # $< == real UID, $> == effective UID if (($< != 0) && ($> != 0)) { # Not root $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0005"}); $anvil->nice_exit({exit_code => 1}); } $anvil->data->{'scan-apc-pdu'} = { # Starts at '2' so that anything set to '1' manually shows first alert_sort => 2, disable => 0, # Ticks are genera lly in 10ms increments ticks_per_second => 100, # By default, the critical amperage is the same as the max amperage. If that is the # case here, we will subtract this number of amps from the max and use that as our # critical warning threshold. So if the max threshold is 12, and the critical # threshold is also 11 or 12, we will drop it to 10. If the critical is set below 10, # we won't adjust it at all. critical_amps_below_max => 2, # This drops the warning to be at least this number of amps below critical's level. warning_amps_below_critical => 2, # A warning or critical alert has to be this number of amps above/below the threshold # for the alert to be cleared. clear_alert_threshold => 2, # This is needed to trick/force the 'scan_apc_pdu_mac_address' OID into returning a Hex-STRING. striker_mib => "/usr/sbin/scancore-agents/".$THIS_FILE."/Striker-MIB.txt", }; $anvil->data->{oids} = { scan_apc_pdu => { scan_apc_pdu_serial_number => ".1.3.6.1.4.1.318.1.1.4.1.5.0", scan_apc_pdu_model_number => ".1.3.6.1.4.1.318.1.1.4.1.4.0", scan_apc_pdu_manufacture_date => ".1.3.6.1.4.1.318.1.1.4.1.3.0", scan_apc_pdu_firmware_version => ".1.3.6.1.4.1.318.1.1.4.1.2.0", scan_apc_pdu_hardware_version => ".1.3.6.1.4.1.318.1.1.4.1.1.0", scan_apc_pdu_mac_address => ".1.3.6.1.2.1.2.2.1.6.2", scan_apc_pdu_mac_address_alt => ".1.3.6.1.2.1.2.2.1.6.1", # Some PDUs use this scan_apc_pdu_mtu_size => ".1.3.6.1.2.1.2.2.1.4.2", scan_apc_pdu_mtu_size_alt => ".1.3.6.1.2.1.2.2.1.4.1", # Some PDUs use this scan_apc_pdu_link_speed => ".1.3.6.1.2.1.2.2.1.5.2", scan_apc_pdu_link_speed_alt => ".1.3.6.1.2.1.2.2.1.5.1", scan_apc_pdu_phase_count => ".1.3.6.1.4.1.318.1.1.12.2.1.2.0", scan_apc_pdu_outlet_count => ".1.3.6.1.4.1.318.1.1.4.4.1.0", }, scan_apc_pdu_phases => { # The phase number will be appended to the OID scan_apc_pdu_phase_current_amperage => ".1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.", scan_apc_pdu_phase_max_amperage => ".1.3.6.1.4.1.318.1.1.12.2.1.1.0", ### NOTE: These aren't recorded, but they are used for alert triggers. phase_low_amp_warning => ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.2.1", # We'll drop these to be at least 2 Amps below max. phase_high_amp_warning => ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.3.1", # If this is less than 'scan-apc-pdu::critical_amps_below_max' below max, it # will be automatically dropped. phase_high_amp_critical => ".1.3.6.1.4.1.318.1.1.12.2.2.1.1.4.1", }, scan_apc_pdu_outlets => { ### The outlet number will be appended to all of these OIDs. scan_apc_pdu_outlet_name => ".1.3.6.1.4.1.318.1.1.4.5.2.1.3.", scan_apc_pdu_outlet_on_phase => ".1.3.6.1.4.1.318.1.1.12.3.5.1.1.3.", # read: 1 = on, 2 = off, 4 = unknown # write: 1 = on, 2 = off, 3 = cycle scan_apc_pdu_outlet_state => ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.", }, scan_apc_pdu_variables => { # This is in ticks, so divide the value by 'scan-apc-pdu::ticks_per_second' uptime => ".1.3.6.1.2.1.1.3.0", total_wattage_draw => ".1.3.6.1.4.1.318.1.1.12.1.16.0", }, }; $anvil->data->{snmp} = { community => { version => "2c", 'read' => "public", 'write' => "private", }, }; $anvil->Storage->read_config(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); # Read switches $anvil->Get->switches({debug => 3, list => ["force", "purge"]}); # Handle start-up tasks my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE}); if ($problem) { $anvil->nice_exit({exit_code => 1}); } # The APC PDUs only allow one connection at a time. As such, we only run on the striker that is also the # active DB. my $host_uuid = $anvil->Get->host_uuid(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid, "sys::database::active_uuid" => $anvil->data->{sys}{database}{active_uuid}, "switches::force" => $anvil->data->{switches}{force}, }}); if ((not $anvil->data->{switches}{force}) && ($anvil->data->{sys}{database}{active_uuid} ne $host_uuid)) { # Don't run. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_pdu_message_0041", variables => { program => $THIS_FILE }}); $anvil->nice_exit({exit_code => 0}); } if ($anvil->data->{switches}{purge}) { # This can be called when doing bulk-database purges. my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"; $anvil->Database->purge_data({ debug => 2, tables => $anvil->Database->get_tables_from_schema({schema_file => $schema_file}), }); $anvil->nice_exit({exit_code => 0}); } # Find the PDUs. The number of PDUs found is returned. If 0, we exit if (not find_pdus($anvil)) { # No PDUs found. $anvil->Log->entry({log_level => 1, message_key => "scan_apc_pdu_message_0001", file => $THIS_FILE, line => __LINE__}); $anvil->nice_exit({exit_code => 1}); } # Read the last state of any PDUs we already know about read_last_scan($anvil); # Collect data from PDUs. gather_pdu_data($anvil); # Look for changes. find_changes($anvil); # Shut down. $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); ############################################################################################################# # Functions # ############################################################################################################# # This reads in the last scan's data. sub read_last_scan { my ($anvil) = @_; # Read in existing data, if any. my $query = " SELECT scan_apc_pdu_uuid, scan_apc_pdu_fence_uuid, scan_apc_pdu_serial_number, scan_apc_pdu_model_number, scan_apc_pdu_manufacture_date, scan_apc_pdu_firmware_version, scan_apc_pdu_hardware_version, scan_apc_pdu_ipv4_address, scan_apc_pdu_mac_address, scan_apc_pdu_mtu_size, scan_apc_pdu_link_speed, scan_apc_pdu_phase_count, scan_apc_pdu_outlet_count FROM scan_apc_pdus ;"; $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 => 3, list => { results => $results, count => $count, }}); # One or more records were found. foreach my $row (@{$results}) { my $scan_apc_pdu_uuid = $row->[0]; my $scan_apc_pdu_fence_uuid = $row->[1]; my $scan_apc_pdu_serial_number = $row->[2]; my $scan_apc_pdu_model_number = $row->[3]; my $scan_apc_pdu_manufacture_date = $row->[4]; my $scan_apc_pdu_firmware_version = $row->[5]; my $scan_apc_pdu_hardware_version = $row->[6]; my $scan_apc_pdu_ipv4_address = $row->[7]; my $scan_apc_pdu_mac_address = $row->[8]; my $scan_apc_pdu_mtu_size = $row->[9]; my $scan_apc_pdu_link_speed = $row->[10]; my $scan_apc_pdu_phase_count = $row->[11]; my $scan_apc_pdu_outlet_count = $row->[12]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, scan_apc_pdu_fence_uuid => $scan_apc_pdu_fence_uuid, scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, scan_apc_pdu_model_number => $scan_apc_pdu_model_number, scan_apc_pdu_manufacture_date => $scan_apc_pdu_manufacture_date, scan_apc_pdu_firmware_version => $scan_apc_pdu_firmware_version, scan_apc_pdu_hardware_version => $scan_apc_pdu_hardware_version, scan_apc_pdu_ipv4_address => $scan_apc_pdu_ipv4_address, scan_apc_pdu_mac_address => $scan_apc_pdu_mac_address, scan_apc_pdu_mtu_size => $scan_apc_pdu_mtu_size, scan_apc_pdu_link_speed => $scan_apc_pdu_link_speed, scan_apc_pdu_phase_count => $scan_apc_pdu_phase_count, scan_apc_pdu_outlet_count => $scan_apc_pdu_outlet_count, }}); $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_serial_number} = $scan_apc_pdu_serial_number; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_fence_uuid} = $scan_apc_pdu_fence_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_model_number} = $scan_apc_pdu_model_number; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_manufacture_date} = $scan_apc_pdu_manufacture_date; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_firmware_version} = $scan_apc_pdu_firmware_version; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_hardware_version} = $scan_apc_pdu_hardware_version; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_ipv4_address} = $scan_apc_pdu_ipv4_address; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mac_address} = $scan_apc_pdu_mac_address; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mtu_size} = $scan_apc_pdu_mtu_size; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_link_speed} = $scan_apc_pdu_link_speed; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phase_count} = $scan_apc_pdu_phase_count; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlet_count} = $scan_apc_pdu_outlet_count; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_serial_number" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_serial_number}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_fence_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_fence_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_model_number" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_model_number}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_manufacture_date" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_manufacture_date}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_firmware_version" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_firmware_version}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_hardware_version" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_hardware_version}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_ipv4_address" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_ipv4_address}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_mac_address" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mac_address}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_mtu_size" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mtu_size}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_link_speed" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_link_speed}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_phase_count" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phase_count}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlet_count" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlet_count}, }}); # Make it possible to find this PDU by serial number and by fence_uuid reference. $anvil->data->{sql}{fence_uuid_to_apc_pdu_uuid}{$scan_apc_pdu_fence_uuid} = $scan_apc_pdu_uuid; $anvil->data->{sql}{serial_number_to_apc_pdu_uuid}{$scan_apc_pdu_serial_number} = $scan_apc_pdu_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::fence_uuid_to_apc_pdu_uuid::${scan_apc_pdu_fence_uuid}" => $anvil->data->{sql}{fence_uuid_to_apc_pdu_uuid}{$scan_apc_pdu_fence_uuid}, "sql::serial_number_to_apc_pdu_uuid::${scan_apc_pdu_serial_number}" => $anvil->data->{sql}{serial_number_to_apc_pdu_uuid}{$scan_apc_pdu_serial_number}, }}); } undef $results; # Read in the phase data $query = " SELECT scan_apc_pdu_phase_uuid, scan_apc_pdu_phase_scan_apc_pdu_uuid, scan_apc_pdu_phase_number, scan_apc_pdu_phase_current_amperage, scan_apc_pdu_phase_max_amperage, scan_apc_pdu_phase_deleted FROM scan_apc_pdu_phases ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); # Do the query against the source DB and loop through the results. $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_pdu_phase_uuid = $row->[0]; my $scan_apc_pdu_phase_scan_apc_pdu_uuid = $row->[1]; my $scan_apc_pdu_phase_number = $row->[2]; my $scan_apc_pdu_phase_current_amperage = $row->[3]; my $scan_apc_pdu_phase_max_amperage = $row->[4]; my $scan_apc_pdu_phase_deleted = $row->[5]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_pdu_phase_uuid => $scan_apc_pdu_phase_uuid, scan_apc_pdu_phase_scan_apc_pdu_uuid => $scan_apc_pdu_phase_scan_apc_pdu_uuid, scan_apc_pdu_phase_number => $scan_apc_pdu_phase_number, scan_apc_pdu_phase_current_amperage => $scan_apc_pdu_phase_current_amperage, scan_apc_pdu_phase_max_amperage => $scan_apc_pdu_phase_max_amperage, scan_apc_pdu_phase_deleted => $scan_apc_pdu_phase_deleted, }}); $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_uuid} = $scan_apc_pdu_phase_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_scan_apc_pdu_uuid} = $scan_apc_pdu_phase_scan_apc_pdu_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage} = $scan_apc_pdu_phase_current_amperage; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_max_amperage} = $scan_apc_pdu_phase_max_amperage; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_deleted} = $scan_apc_pdu_phase_deleted; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_pdu_uuid::${scan_apc_pdu_phase_scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_phase_scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_scan_apc_pdu_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_scan_apc_pdu_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_phase_scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_current_amperage" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_phase_scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_max_amperage" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_max_amperage}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_phase_scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_deleted" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_phase_scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_deleted}, }}); } undef $results; # Read in the outlets. $query = " SELECT scan_apc_pdu_outlet_uuid, scan_apc_pdu_outlet_scan_apc_pdu_uuid, scan_apc_pdu_outlet_number, scan_apc_pdu_outlet_name, scan_apc_pdu_outlet_on_phase, scan_apc_pdu_outlet_state FROM scan_apc_pdu_outlets ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_pdu_outlet_uuid = $row->[0]; my $scan_apc_pdu_outlet_scan_apc_pdu_uuid = $row->[1]; my $scan_apc_pdu_outlet_number = $row->[2]; my $scan_apc_pdu_outlet_name = $row->[3]; my $scan_apc_pdu_outlet_on_phase = $row->[4]; my $scan_apc_pdu_outlet_state = $row->[5]; my $scan_apc_pdu_outlet_note = $row->[6]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_pdu_outlet_uuid => $scan_apc_pdu_outlet_uuid, scan_apc_pdu_outlet_scan_apc_pdu_uuid => $scan_apc_pdu_outlet_scan_apc_pdu_uuid, scan_apc_pdu_outlet_number => $scan_apc_pdu_outlet_number, scan_apc_pdu_outlet_name => $scan_apc_pdu_outlet_name, scan_apc_pdu_outlet_on_phase => $scan_apc_pdu_outlet_on_phase, scan_apc_pdu_outlet_state => $scan_apc_pdu_outlet_state, }}); # Which serial number does this phase belong to? my $scan_apc_pdu_serial_number = $anvil->data->{uuid_to_serial}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number }}); $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid} = $scan_apc_pdu_outlet_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_scan_apc_pdu_uuid} = $scan_apc_pdu_outlet_scan_apc_pdu_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name} = $scan_apc_pdu_outlet_name; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase} = $scan_apc_pdu_outlet_on_phase; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} = $scan_apc_pdu_outlet_state; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_pdu_uuid::${scan_apc_pdu_outlet_scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_outlet_scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_scan_apc_pdu_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_scan_apc_pdu_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_outlet_scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_name" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_outlet_scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_on_phase" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_outlet_scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_state" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, }}); } undef $results; # Read in the variables $query = " SELECT scan_apc_pdu_variable_uuid, scan_apc_pdu_variable_scan_apc_pdu_uuid, scan_apc_pdu_variable_is_temperature, scan_apc_pdu_variable_name, scan_apc_pdu_variable_value FROM scan_apc_pdu_variables ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_pdu_variable_uuid = $row->[0]; my $scan_apc_pdu_variable_scan_apc_pdu_uuid = $row->[1]; my $scan_apc_pdu_variable_is_temperature = $row->[2]; my $scan_apc_pdu_variable_name = $row->[3]; my $scan_apc_pdu_variable_value = $row->[4]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_pdu_variable_uuid => $scan_apc_pdu_variable_uuid, scan_apc_pdu_variable_scan_apc_pdu_uuid => $scan_apc_pdu_variable_scan_apc_pdu_uuid, scan_apc_pdu_variable_is_temperature => $scan_apc_pdu_variable_is_temperature, scan_apc_pdu_variable_name => $scan_apc_pdu_variable_name, scan_apc_pdu_variable_value => $scan_apc_pdu_variable_value, }}); # Store the variables under the PDU it belongs to. $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_uuid} = $scan_apc_pdu_variable_uuid; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_is_temperature} = $scan_apc_pdu_variable_is_temperature; $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_value} = $scan_apc_pdu_variable_value; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_pdu_uuid::${scan_apc_pdu_variable_scan_apc_pdu_uuid}::scan_apc_pdu_variables::scan_apc_pdu_variable_name::${scan_apc_pdu_variable_name}::scan_apc_pdu_variable_uuid" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_uuid}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_variable_scan_apc_pdu_uuid}::scan_apc_pdu_variables::scan_apc_pdu_variable_name::${scan_apc_pdu_variable_name}::scan_apc_pdu_variable_is_temperature" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_is_temperature}, "sql::scan_apc_pdu_uuid::${scan_apc_pdu_variable_scan_apc_pdu_uuid}::scan_apc_pdu_variables::scan_apc_pdu_variable_name::${scan_apc_pdu_variable_name}::scan_apc_pdu_variable_value" => $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_variable_scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{$scan_apc_pdu_variable_name}{scan_apc_pdu_variable_value}, }}); } return(0); } # This reads in the last scan data from one of the databases and compares it against the just-read data. If # anything changed, register an alert. sub find_changes { my ($anvil) = @_; # This stores all the queries so that they're committed in one transaction. $anvil->data->{sys}{queries} = []; # Loop through each PDU we've seen this pass foreach my $scan_apc_pdu_uuid (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}}) { my $new_pdu = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{new_pdu}; my $pdu_host_name = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{pdu_host_name}; my $scan_apc_pdu_fence_uuid = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_fence_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, new_pdu => $new_pdu, scan_apc_pdu_fence_uuid => $scan_apc_pdu_fence_uuid, pdu_host_name => $pdu_host_name, }}); # Convert all the long hashes into shorter variables my $new_scan_apc_pdu_serial_number = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_serial_number}; my $new_scan_apc_pdu_model_number = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_model_number}; my $new_scan_apc_pdu_manufacture_date = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}; my $new_scan_apc_pdu_firmware_version = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_firmware_version}; my $new_scan_apc_pdu_hardware_version = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_hardware_version}; my $new_scan_apc_pdu_ipv4_address = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_ipv4_address}; my $new_scan_apc_pdu_mac_address = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}; my $new_scan_apc_pdu_mtu_size = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}; my $new_scan_apc_pdu_link_speed = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}; my $new_scan_apc_pdu_phase_count = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count}; my $new_scan_apc_pdu_outlet_count = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_scan_apc_pdu_serial_number => $new_scan_apc_pdu_serial_number, new_scan_apc_pdu_model_number => $new_scan_apc_pdu_model_number, new_scan_apc_pdu_manufacture_date => $new_scan_apc_pdu_manufacture_date, new_scan_apc_pdu_firmware_version => $new_scan_apc_pdu_firmware_version, new_scan_apc_pdu_hardware_version => $new_scan_apc_pdu_hardware_version, new_scan_apc_pdu_ipv4_address => $new_scan_apc_pdu_ipv4_address, new_scan_apc_pdu_mac_address => $new_scan_apc_pdu_mac_address, new_scan_apc_pdu_mtu_size => $new_scan_apc_pdu_mtu_size, new_scan_apc_pdu_link_speed => $new_scan_apc_pdu_link_speed, new_scan_apc_pdu_phase_count => $new_scan_apc_pdu_phase_count, new_scan_apc_pdu_outlet_count => $new_scan_apc_pdu_outlet_count, }}); # These are used later for checking the state of the phases. They are not stored in the # database, except for max amps. They should never change. my $new_scan_apc_pdu_phase_max_amperage = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum}; my $new_phase_low_amp_warning = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning}; my $new_phase_high_amp_warning = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning}; my $new_phase_high_amp_critical = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}; my $clear_low_amp_warning = $new_phase_low_amp_warning + $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_low_warning}; my $clear_phase_high_amp_warning = $new_phase_high_amp_warning - $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_warning}; my $clear_phase_high_amp_critical = $new_phase_high_amp_critical - $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_critical}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_scan_apc_pdu_phase_max_amperage => $new_scan_apc_pdu_phase_max_amperage, new_phase_low_amp_warning => $new_phase_low_amp_warning, new_phase_high_amp_warning => $new_phase_high_amp_warning, new_phase_high_amp_critical => $new_phase_high_amp_critical, clear_low_amp_warning => $clear_low_amp_warning, clear_phase_high_amp_warning => $clear_phase_high_amp_warning, clear_phase_high_amp_critical => $clear_phase_high_amp_critical, }}); # Have I seen this PDU before? if (not $new_pdu) { # Yup. Search for changes. my $old_scan_apc_pdu_serial_number = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_serial_number}; my $old_scan_apc_pdu_model_number = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_model_number}; my $old_scan_apc_pdu_manufacture_date = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_manufacture_date}; my $old_scan_apc_pdu_firmware_version = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_firmware_version}; my $old_scan_apc_pdu_hardware_version = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_hardware_version}; my $old_scan_apc_pdu_ipv4_address = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_ipv4_address}; my $old_scan_apc_pdu_mac_address = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mac_address}; my $old_scan_apc_pdu_mtu_size = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_mtu_size}; my $old_scan_apc_pdu_link_speed = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_link_speed}; my $old_scan_apc_pdu_phase_count = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phase_count}; my $old_scan_apc_pdu_outlet_count = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlet_count}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_scan_apc_pdu_serial_number => $old_scan_apc_pdu_serial_number, old_scan_apc_pdu_model_number => $old_scan_apc_pdu_model_number, old_scan_apc_pdu_manufacture_date => $old_scan_apc_pdu_manufacture_date, old_scan_apc_pdu_firmware_version => $old_scan_apc_pdu_firmware_version, old_scan_apc_pdu_hardware_version => $old_scan_apc_pdu_hardware_version, old_scan_apc_pdu_ipv4_address => $old_scan_apc_pdu_ipv4_address, old_scan_apc_pdu_mac_address => $old_scan_apc_pdu_mac_address, old_scan_apc_pdu_mtu_size => $old_scan_apc_pdu_mtu_size, old_scan_apc_pdu_link_speed => $old_scan_apc_pdu_link_speed, old_scan_apc_pdu_phase_count => $old_scan_apc_pdu_phase_count, old_scan_apc_pdu_outlet_count => $old_scan_apc_pdu_outlet_count, }}); # Has the phase data changed? my $changes = 0; if ($new_scan_apc_pdu_model_number ne $old_scan_apc_pdu_model_number) { $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); if ($old_scan_apc_pdu_model_number eq "DELETED") { # It's back. $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, serial_number => $new_scan_apc_pdu_serial_number, ip_address => $new_scan_apc_pdu_ipv4_address, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0006", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0006", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } else { my $variables = { name => $pdu_host_name, old_model_number => $old_scan_apc_pdu_model_number, new_model_number => $new_scan_apc_pdu_model_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0007", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0007", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } if ($new_scan_apc_pdu_serial_number ne $old_scan_apc_pdu_serial_number) { # New PDU? $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_serial_number => $old_scan_apc_pdu_serial_number, new_serial_number => $new_scan_apc_pdu_serial_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0008", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0008", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_manufacture_date ne $old_scan_apc_pdu_manufacture_date) { # New PDU? $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_manufacture_date => $old_scan_apc_pdu_manufacture_date, new_manufacture_date => $new_scan_apc_pdu_manufacture_date, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0009", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0009", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_firmware_version ne $old_scan_apc_pdu_firmware_version) { # Could be a new PDU, or a firmware upgrade $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_firmware_version => $old_scan_apc_pdu_firmware_version, new_firmware_version => $new_scan_apc_pdu_firmware_version, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0010", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0010", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_hardware_version ne $old_scan_apc_pdu_hardware_version) { # Probably a new PDU $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_hardware_version => $old_scan_apc_pdu_hardware_version, new_hardware_version => $new_scan_apc_pdu_hardware_version, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0011", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0011", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_ipv4_address ne $old_scan_apc_pdu_ipv4_address) { # This could change, sure. $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_ipv4_address => $old_scan_apc_pdu_ipv4_address, new_ipv4_address => $new_scan_apc_pdu_ipv4_address, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0012", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0012", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_mac_address ne $old_scan_apc_pdu_mac_address) { # New PDU, likely $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_mac_address => $old_scan_apc_pdu_mac_address, new_mac_address => $new_scan_apc_pdu_mac_address, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0013", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0013", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_mtu_size ne $old_scan_apc_pdu_mtu_size) { # MTU size changed. $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_mtu_size => $old_scan_apc_pdu_mtu_size, new_mtu_size => $new_scan_apc_pdu_mtu_size, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0014", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0014", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_link_speed ne $old_scan_apc_pdu_link_speed) { # This could happen, too. $changes = 1; my $say_new_link_speed_hr = $anvil->Convert->bytes_to_human_readable({ 'bytes' => ($new_scan_apc_pdu_link_speed / 8) })."/#!string!suffix_0002!#"; my $say_new_link_speed_mbps = $anvil->Convert->add_commas({number => ($new_scan_apc_pdu_link_speed / 100000)})." #!string!suffix_0050!#"; my $say_old_link_speed_hr = $anvil->Convert->bytes_to_human_readable({ 'bytes' => ($old_scan_apc_pdu_link_speed / 8) })."/#!string!suffix_0002!#"; my $say_old_link_speed_mbps = $anvil->Convert->add_commas({number => ($old_scan_apc_pdu_link_speed / 100000)})." #!string!suffix_0050!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes, say_new_link_speed_mbps => $say_new_link_speed_mbps, say_new_link_speed_hr => $say_new_link_speed_hr, say_old_link_speed_mbps => $say_old_link_speed_mbps, say_old_link_speed_hr => $say_old_link_speed_hr, }}); my $variables = { name => $pdu_host_name, new_link_speed_mbps => $say_new_link_speed_mbps, new_link_speed_hr => $say_new_link_speed_hr, old_link_speed_mbps => $say_old_link_speed_mbps, old_link_speed_hr => $say_old_link_speed_hr, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0015", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0015", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_phase_count ne $old_scan_apc_pdu_phase_count) { # New PDU, probably $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_phase_count => sprintf("%02d", $old_scan_apc_pdu_phase_count), new_phase_count => sprintf("%02d", $new_scan_apc_pdu_phase_count), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0016", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0016", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_outlet_count ne $old_scan_apc_pdu_outlet_count) { # New PDU $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, old_outlet_count => sprintf("%02d", $old_scan_apc_pdu_outlet_count), new_outlet_count => sprintf("%02d", $new_scan_apc_pdu_outlet_count), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0017", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0017", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); if ($changes) { # Save the changes. my $query = " UPDATE public.scan_apc_pdus SET scan_apc_pdu_serial_number = ".$anvil->Database->quote($new_scan_apc_pdu_serial_number).", scan_apc_pdu_model_number = ".$anvil->Database->quote($new_scan_apc_pdu_model_number).", scan_apc_pdu_manufacture_date = ".$anvil->Database->quote($new_scan_apc_pdu_manufacture_date).", scan_apc_pdu_firmware_version = ".$anvil->Database->quote($new_scan_apc_pdu_firmware_version).", scan_apc_pdu_hardware_version = ".$anvil->Database->quote($new_scan_apc_pdu_hardware_version).", scan_apc_pdu_ipv4_address = ".$anvil->Database->quote($new_scan_apc_pdu_ipv4_address).", scan_apc_pdu_mac_address = ".$anvil->Database->quote($new_scan_apc_pdu_mac_address).", scan_apc_pdu_mtu_size = ".$anvil->Database->quote($new_scan_apc_pdu_mtu_size).", scan_apc_pdu_link_speed = ".$anvil->Database->quote($new_scan_apc_pdu_link_speed).", scan_apc_pdu_phase_count = ".$anvil->Database->quote($new_scan_apc_pdu_phase_count).", scan_apc_pdu_outlet_count = ".$anvil->Database->quote($new_scan_apc_pdu_outlet_count).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; } ### What about other variables? # Do I have a previous uptime? my $new_uptime = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_uptime => $new_uptime }}); if ($anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{uptime}{scan_apc_pdu_variable_uuid}) { # Exists, change? my $scan_apc_pdu_variable_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{uptime}{scan_apc_pdu_variable_uuid}; my $old_uptime = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{uptime}{scan_apc_pdu_variable_value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_variable_uuid => $scan_apc_pdu_variable_uuid, old_uptime => $old_uptime, new_uptime => $new_uptime, }}); if ($new_uptime ne $old_uptime) { update_variables($anvil, $scan_apc_pdu_variable_uuid, "uptime", $new_uptime); # We expect this to change upward. If the new uptime is significantly # less than the old, it rebooted. We put the 300 second buffer # because it's not uncommon for the current uptime to report as # slightly behind the previous read. (Thanks, APC...) my $variables = { name => $pdu_host_name, old_uptime => $anvil->Convert->time({'time' => $old_uptime}), new_uptime => $anvil->Convert->time({'time' => $new_uptime}), }; if ($new_uptime > $old_uptime) { # Normal, info-level $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_pdu_message_0018", variables => $variables}); $anvil->Alert->register({ alert_level => "info", message => "scan_apc_pdu_message_0018", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } elsif (($new_uptime < $old_uptime) && ($new_uptime < 300)) { # It's rebooted. This is notice level as it's generally just # the NIC rebooting and doesn't interfere with power. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0019", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0019", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } } else { # New, INSERT it (is_temperature is always false for now). insert_variables($anvil, $scan_apc_pdu_uuid, "uptime", $new_uptime); } # Do I have a previous wattage? my $new_total_wattage_draw = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_total_wattage_draw => $new_total_wattage_draw }}); if ($anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{total_wattage_draw}{scan_apc_pdu_variable_uuid}) { # Exists, change? my $scan_apc_pdu_variable_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{total_wattage_draw}{scan_apc_pdu_variable_uuid}; my $old_total_wattage_draw = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{scan_apc_pdu_variable_name}{total_wattage_draw}{scan_apc_pdu_variable_value}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_variable_uuid => $scan_apc_pdu_variable_uuid, old_total_wattage_draw => $old_total_wattage_draw, }}); if ($new_total_wattage_draw ne $old_total_wattage_draw) { my $variables = { name => $pdu_host_name, old_total_wattage_draw => $old_total_wattage_draw, new_total_wattage_draw => $new_total_wattage_draw, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_pdu_message_0020", variables => $variables}); $anvil->Alert->register({ alert_level => "info", message => "scan_apc_pdu_message_0020", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); update_variables($anvil, $scan_apc_pdu_variable_uuid, "total_wattage_draw", $new_total_wattage_draw); } } else { # New, INSERT it (is_temperature is always false for now). insert_variables($anvil, $scan_apc_pdu_uuid, "total_wattage_draw", $new_total_wattage_draw); } # Have any phases changed? foreach my $scan_apc_pdu_phase_number (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}}) { my $new_scan_apc_pdu_phase_current_amperage = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_phase_number => $scan_apc_pdu_phase_number, new_scan_apc_pdu_phase_current_amperage => $new_scan_apc_pdu_phase_current_amperage, new_scan_apc_pdu_phase_max_amperage => $new_scan_apc_pdu_phase_max_amperage, new_total_wattage_draw => $new_total_wattage_draw, }}); if ($anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_uuid}) { # We've seen this phase before. Changes? my $scan_apc_pdu_phase_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_uuid}; my $old_scan_apc_pdu_phase_scan_apc_pdu_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_scan_apc_pdu_uuid}; my $old_scan_apc_pdu_phase_current_amperage = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}; my $old_scan_apc_pdu_phase_max_amperage = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_max_amperage}; my $old_scan_apc_pdu_phase_deleted = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_deleted}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_phase_uuid => $scan_apc_pdu_phase_uuid, old_scan_apc_pdu_phase_scan_apc_pdu_uuid => $old_scan_apc_pdu_phase_scan_apc_pdu_uuid, old_scan_apc_pdu_phase_current_amperage => $old_scan_apc_pdu_phase_current_amperage, old_scan_apc_pdu_phase_max_amperage => $old_scan_apc_pdu_phase_max_amperage, old_scan_apc_pdu_phase_deleted => $old_scan_apc_pdu_phase_deleted, }}); # If the 'deleted' was set, the phase has returned. if ($old_scan_apc_pdu_phase_deleted) { # The phase amperage can change all the time. $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, phase => sprintf("%02d", $scan_apc_pdu_phase_number), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0021", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0021", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } # The max amps per phase is set across all phases. if ($new_scan_apc_pdu_phase_max_amperage ne $old_scan_apc_pdu_phase_max_amperage) { # This can be set by the user in the PDU's interface $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, phase => sprintf("%02d", $scan_apc_pdu_phase_number), old_phase_max_amperage => $old_scan_apc_pdu_phase_max_amperage, new_phase_max_amperage => $new_scan_apc_pdu_phase_max_amperage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0022", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0022", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($old_scan_apc_pdu_phase_current_amperage ne $new_scan_apc_pdu_phase_current_amperage) { # The phase amperage can change all the time. That said, is # it over the warning or critical thresholds, or has it # dropped back down? $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, phase => sprintf("%02d", $scan_apc_pdu_phase_number), old_phase_current_amperage => $old_scan_apc_pdu_phase_current_amperage, new_phase_current_amperage => $new_scan_apc_pdu_phase_current_amperage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_pdu_message_0023", variables => $variables}); $anvil->Alert->register({ alert_level => "info", message => "scan_apc_pdu_message_0023", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); # Cheack for low alerts to set or high alerts to clear if ($new_scan_apc_pdu_phase_current_amperage < $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning}) { ### NOTE: We don't care about low amperage warnings, but it ### is a user-configurable value. As such, we'll register alers. # Dropped too low, clear high warn and high crit my $changed = $anvil->Alert->check_alert_sent({ debug => 2, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_low_warning", set_by => $THIS_FILE, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. my $variables = { pdu_name => $pdu_host_name, phase => sprintf("%02d", $scan_apc_pdu_phase_number), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0024", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0024", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } # Clear the high-warning and high-critical, if needed. clear_phase_high_critical($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); clear_phase_high_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } elsif ($new_scan_apc_pdu_phase_current_amperage < $clear_phase_high_amp_warning) { # Dropped low enough to clear high warn and high crit clear_phase_high_critical($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); clear_phase_high_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } elsif ($new_scan_apc_pdu_phase_current_amperage < $clear_phase_high_amp_critical) { # Dropped low enough to clear high crit. clear_phase_high_critical($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } # Cheack for low alerts to clear or high alerts to set if ($new_scan_apc_pdu_phase_current_amperage > $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}) { # Set high crit, clear low warn set_phase_high_critical($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); clear_phase_low_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } elsif ($new_scan_apc_pdu_phase_current_amperage > $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning}) { # Set high warn set_phase_high_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); clear_phase_low_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } elsif ($new_scan_apc_pdu_phase_current_amperage > $clear_low_amp_warning) { # Clear the low warning clear_phase_low_warning($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); if ($changes) { my $query = " UPDATE scan_apc_pdu_phases SET scan_apc_pdu_phase_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).", scan_apc_pdu_phase_number = ".$anvil->Database->quote($scan_apc_pdu_phase_number).", scan_apc_pdu_phase_current_amperage = ".$anvil->Database->quote($new_scan_apc_pdu_phase_current_amperage).", scan_apc_pdu_phase_max_amperage = ".$anvil->Database->quote($new_scan_apc_pdu_phase_max_amperage).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_phase_uuid = ".$anvil->Database->quote($scan_apc_pdu_phase_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; } } delete $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}; } # Any phases that vanished? foreach my $scan_apc_pdu_phase_number (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}}) { # Did it just vanish? my $scan_apc_pdu_phase_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_uuid}; my $scan_apc_pdu_phase_deleted = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_deleted}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_phase_uuid => $scan_apc_pdu_phase_uuid, scan_apc_pdu_phase_deleted => $scan_apc_pdu_phase_deleted, }}); if (not $scan_apc_pdu_phase_deleted) { # Yup my $query = " UPDATE scan_apc_pdu_phases SET scan_apc_pdu_phase_deleted = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_phase_uuid = ".$anvil->Database->quote($scan_apc_pdu_phase_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; my $variables = { name => $pdu_host_name, phase => sprintf("%02d", $scan_apc_pdu_phase_number), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0030", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0030", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } # Have any outlets changed? foreach my $scan_apc_pdu_outlet_number (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}}) { my $scan_apc_pdu_serial_number = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_serial_number}; my $new_scan_apc_pdu_outlet_name = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}; my $new_scan_apc_pdu_outlet_on_phase = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}; my $new_scan_apc_pdu_outlet_state = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, new_scan_apc_pdu_outlet_name => $new_scan_apc_pdu_outlet_name, new_scan_apc_pdu_outlet_on_phase => $new_scan_apc_pdu_outlet_on_phase, new_scan_apc_pdu_outlet_state => $new_scan_apc_pdu_outlet_state, }}); if (($new_scan_apc_pdu_outlet_on_phase ne "!!no_connection!!") or ($new_scan_apc_pdu_outlet_on_phase ne "#!no_value!#")) { $anvil->Alert->check_condition_age({clear => 1, name => "scan_apc_pdu::pdu::".$scan_apc_pdu_serial_number."::phase_lost::".$scan_apc_pdu_outlet_number}); } if (($new_scan_apc_pdu_outlet_state eq "!!no_connection!!") or ($new_scan_apc_pdu_outlet_state eq "#!no_value!#")) { $anvil->Alert->check_condition_age({clear => 1, name => "scan_apc_pdu::pdu::".$scan_apc_pdu_serial_number."::outlet_lost::".$scan_apc_pdu_outlet_number}); } # Do I know about this outlet? if ($anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid}) { # Yup! my $scan_apc_pdu_outlet_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid}; my $old_scan_apc_pdu_outlet_name = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}; my $old_scan_apc_pdu_outlet_on_phase = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}; my $old_scan_apc_pdu_outlet_state = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_outlet_uuid => $scan_apc_pdu_outlet_uuid, old_scan_apc_pdu_outlet_name => $old_scan_apc_pdu_outlet_name, old_scan_apc_pdu_outlet_on_phase => $old_scan_apc_pdu_outlet_on_phase, old_scan_apc_pdu_outlet_state => $old_scan_apc_pdu_outlet_state, }}); # Did a vanished outlet come back? my $changes = 0; if ($old_scan_apc_pdu_outlet_name eq "DELETED") { # It's back! $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0031", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0031", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_outlet_name ne $old_scan_apc_pdu_outlet_name) { # Name changed. $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), old_outlet_name => $old_scan_apc_pdu_outlet_name, new_outlet_name => $new_scan_apc_pdu_outlet_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0032", variables => $variables}); $anvil->Alert->register({ alert_level => "notice", message => "scan_apc_pdu_message_0032", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_outlet_on_phase ne $old_scan_apc_pdu_outlet_on_phase) { # Phase changed. If the new phase is '!!no_connection!!', it # could be contention, so check if this has been the case for # at least five minutes. if (($new_scan_apc_pdu_outlet_on_phase eq "!!no_connection!!") or ($new_scan_apc_pdu_outlet_on_phase eq "#!no_value!#")) { my $age = $anvil->Alert->check_condition_age({name => "scan_apc_pdu::pdu::".$scan_apc_pdu_serial_number."::phase_lost::".$scan_apc_pdu_outlet_number}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); if ($age < 600) { # Ignore it for now. next; } } $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), old_outlet_on_phase => $old_scan_apc_pdu_outlet_on_phase, new_outlet_on_phase => $new_scan_apc_pdu_outlet_on_phase, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0033", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0033", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } if ($new_scan_apc_pdu_outlet_state ne $old_scan_apc_pdu_outlet_state) { # If we had a contention and the new value is '!!no_connection!!'. if (($new_scan_apc_pdu_outlet_state eq "!!no_connection!!") or ($new_scan_apc_pdu_outlet_state eq "#!no_value!#")) { my $age = $anvil->Alert->check_condition_age({name => "scan_apc_pdu::pdu::".$scan_apc_pdu_serial_number."::outlet_lost::".$scan_apc_pdu_outlet_number}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); if ($age < 600) { # Ignore it for now. next; } } # This is likely from a fence action, so we make it critical $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), old_outlet_state => $old_scan_apc_pdu_outlet_state, new_outlet_state => $new_scan_apc_pdu_outlet_state, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0034", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0034", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); if ($changes) { # Save. my $query = " UPDATE scan_apc_pdu_outlets SET scan_apc_pdu_outlet_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).", scan_apc_pdu_outlet_number = ".$anvil->Database->quote($scan_apc_pdu_outlet_number).", scan_apc_pdu_outlet_name = ".$anvil->Database->quote($new_scan_apc_pdu_outlet_name).", scan_apc_pdu_outlet_on_phase = ".$anvil->Database->quote($new_scan_apc_pdu_outlet_on_phase).", scan_apc_pdu_outlet_state = ".$anvil->Database->quote($new_scan_apc_pdu_outlet_state).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_outlet_uuid = ".$anvil->Database->quote($scan_apc_pdu_outlet_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; } } else { # Nope, INSERT it. insert_outlets($anvil, $scan_apc_pdu_uuid, $scan_apc_pdu_outlet_number, $new_scan_apc_pdu_outlet_name, $new_scan_apc_pdu_outlet_on_phase, $new_scan_apc_pdu_outlet_state); my $say_state = "#!string!scan_apc_pdu_unit_0001!#"; if ($new_scan_apc_pdu_outlet_state eq "on") { $say_state = "#!string!scan_apc_pdu_unit_0002!#"; } elsif ($new_scan_apc_pdu_outlet_state eq "off") { $say_state = "#!string!scan_apc_pdu_unit_0003!#"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_scan_apc_pdu_outlet_state => $new_scan_apc_pdu_outlet_state }}); my $variables = { pdu_name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), 'state' => $say_state, on_phase => sprintf("%02d", $new_scan_apc_pdu_outlet_on_phase), name => $new_scan_apc_pdu_outlet_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0035", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0035", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } delete $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}; } # Any outlets vanished? foreach my $scan_apc_pdu_outlet_number (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}}) { # Lost, update the note. my $scan_apc_pdu_outlet_uuid = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid}; my $old_scan_apc_pdu_outlet_name = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_outlet_uuid => $scan_apc_pdu_outlet_uuid, old_scan_apc_pdu_outlet_name => $old_scan_apc_pdu_outlet_name, }}); if ($old_scan_apc_pdu_outlet_name ne "DELETED") { # Yup my $query = " UPDATE scan_apc_pdu_outlets SET scan_apc_pdu_outlet_name = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_outlet_uuid = ".$anvil->Database->quote($scan_apc_pdu_outlet_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changes => $changes }}); my $variables = { name => $pdu_host_name, outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0036", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0036", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } # Delete this from the SQL hash so we know it didn't vanish. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0726", variables => { hash_key => "sql::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}" }}); delete $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}; } else { # OK, now INSERT it. my $query = " INSERT INTO scan_apc_pdus ( scan_apc_pdu_uuid, scan_apc_pdu_fence_uuid, scan_apc_pdu_serial_number, scan_apc_pdu_model_number, scan_apc_pdu_manufacture_date, scan_apc_pdu_firmware_version, scan_apc_pdu_hardware_version, scan_apc_pdu_ipv4_address, scan_apc_pdu_mac_address, scan_apc_pdu_mtu_size, scan_apc_pdu_link_speed, scan_apc_pdu_phase_count, scan_apc_pdu_outlet_count, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_pdu_uuid).", ".$anvil->Database->quote($scan_apc_pdu_fence_uuid).", ".$anvil->Database->quote($new_scan_apc_pdu_serial_number).", ".$anvil->Database->quote($new_scan_apc_pdu_model_number).", ".$anvil->Database->quote($new_scan_apc_pdu_manufacture_date).", ".$anvil->Database->quote($new_scan_apc_pdu_firmware_version).", ".$anvil->Database->quote($new_scan_apc_pdu_hardware_version).", ".$anvil->Database->quote($new_scan_apc_pdu_ipv4_address).", ".$anvil->Database->quote($new_scan_apc_pdu_mac_address).", ".$anvil->Database->quote($new_scan_apc_pdu_mtu_size).", ".$anvil->Database->quote($new_scan_apc_pdu_link_speed).", ".$anvil->Database->quote($new_scan_apc_pdu_phase_count).", ".$anvil->Database->quote($new_scan_apc_pdu_outlet_count).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; # Send an alert telling the user about this new PDU. my $say_link_speed_hr = "#!string!scan_apc_pdu_unit_0004!#"; # "Down" my $say_link_speed_mbps = "#!string!scan_apc_pdu_unit_0004!#"; # "Down" if (($new_scan_apc_pdu_link_speed) && ($new_scan_apc_pdu_link_speed =~ /^\d+$/)) { $say_link_speed_hr = $anvil->Convert->bytes_to_human_readable({'bytes' => ($new_scan_apc_pdu_link_speed / 8)})."/#!string!scan_apc_pdu_unit_0006!#"; $say_link_speed_mbps = ($new_scan_apc_pdu_link_speed / 1000000)." #!string!scan_apc_pdu_unit_0005!#"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_link_speed_hr => $say_link_speed_hr, say_link_speed_mbps => $say_link_speed_mbps, }}); } # Record the variables (uptime and wattage) foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}}) { my $value = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{$variable}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable, value => $value, }}); # NOTE: We don't send an alert here as we incorporated the two variables we care about above. insert_variables($anvil, $scan_apc_pdu_uuid, $variable, $value); } # Load the variables we know about. my $new_uptime = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}; my $new_total_wattage_draw = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_uptime => $new_uptime." (".$anvil->Convert->time({'time' => $new_uptime}).")", new_total_wattage_draw => $new_total_wattage_draw }}); my $variables = { name => $pdu_host_name, serial_number => $new_scan_apc_pdu_serial_number, model_number => $new_scan_apc_pdu_model_number, manufacture_date => $new_scan_apc_pdu_manufacture_date." #!string!scan_apc_pdu_unit_0007!#", firmware_version => $new_scan_apc_pdu_firmware_version, hardware_version => $new_scan_apc_pdu_hardware_version, ipv4_address => $new_scan_apc_pdu_ipv4_address, mac_address => $new_scan_apc_pdu_mac_address, mtu_size => $new_scan_apc_pdu_mtu_size, link_speed_hr => $say_link_speed_hr, link_speed_mbps => $say_link_speed_mbps, phase_count => $new_scan_apc_pdu_phase_count, outlet_count => $new_scan_apc_pdu_outlet_count, phase_max_amperage => $new_scan_apc_pdu_phase_max_amperage, phase_low_amp_warning => $new_phase_low_amp_warning, phase_high_amp_warning => $new_phase_high_amp_warning, phase_high_amp_critical => $new_phase_high_amp_critical, uptime => $anvil->Convert->time({'time' => $new_uptime}), total_wattage_draw => $new_total_wattage_draw, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0037", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0037", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); # Insert the phase data foreach my $scan_apc_pdu_phase_number (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}}) { my $scan_apc_pdu_phase_uuid = $anvil->Get->uuid(); my $new_scan_apc_pdu_phase_current_amperage = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_phase_uuid => $scan_apc_pdu_phase_uuid, new_scan_apc_pdu_phase_current_amperage => $new_scan_apc_pdu_phase_current_amperage, }}); my $query = " INSERT INTO scan_apc_pdu_phases ( scan_apc_pdu_phase_uuid, scan_apc_pdu_phase_scan_apc_pdu_uuid, scan_apc_pdu_phase_number, scan_apc_pdu_phase_current_amperage, scan_apc_pdu_phase_max_amperage, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_pdu_phase_uuid).", ".$anvil->Database->quote($scan_apc_pdu_uuid).", ".$anvil->Database->quote($scan_apc_pdu_phase_number).", ".$anvil->Database->quote($new_scan_apc_pdu_phase_current_amperage).", ".$anvil->Database->quote($new_scan_apc_pdu_phase_max_amperage).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; my $variables = { phase => sprintf("%02d", $scan_apc_pdu_phase_number), amps => $new_scan_apc_pdu_phase_current_amperage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0038", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0038", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } # Insert the outlet data foreach my $scan_apc_pdu_outlet_number (sort {$a cmp $b} keys %{$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}}) { my $scan_apc_pdu_outlet_uuid = $anvil->Get->uuid(); my $new_scan_apc_pdu_outlet_name = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}; my $new_scan_apc_pdu_outlet_on_phase = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}; my $new_scan_apc_pdu_outlet_state = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_outlet_uuid => $scan_apc_pdu_outlet_uuid, new_scan_apc_pdu_outlet_name => $new_scan_apc_pdu_outlet_name, new_scan_apc_pdu_outlet_on_phase => $new_scan_apc_pdu_outlet_on_phase, new_scan_apc_pdu_outlet_state => $new_scan_apc_pdu_outlet_state, }}); insert_outlets($anvil, $scan_apc_pdu_uuid, $scan_apc_pdu_outlet_number, $new_scan_apc_pdu_outlet_name, $new_scan_apc_pdu_outlet_on_phase, $new_scan_apc_pdu_outlet_state); my $say_state = "#!string!scan_apc_pdu_unit_0001!#"; if ($new_scan_apc_pdu_outlet_state eq "on") { $say_state = "#!string!scan_apc_pdu_unit_0002!#"; } elsif ($new_scan_apc_pdu_outlet_state eq "off") { $say_state = "#!string!scan_apc_pdu_unit_0003!#"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_scan_apc_pdu_outlet_state => $new_scan_apc_pdu_outlet_state }}); my $variables = { outlet => sprintf("%02d", $scan_apc_pdu_outlet_number), 'state' => $say_state, on_phase => sprintf("%02d", $new_scan_apc_pdu_outlet_on_phase), name => $new_scan_apc_pdu_outlet_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0039", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0039", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } } # Look for PDUs that we saw before that are gone now. foreach my $scan_apc_pdu_uuid (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_apc_pdu_uuid}}) { # Gone! Is this the first time it's disappeared? my $scan_apc_pdu_serial_number = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_serial_number}; my $scan_apc_pdu_model_number = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_model_number}; my $scan_apc_pdu_ipv4_address = $anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_ipv4_address}; $scan_apc_pdu_ipv4_address = "--" if not defined $scan_apc_pdu_ipv4_address; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, scan_apc_pdu_model_number => $scan_apc_pdu_model_number, scan_apc_pdu_ipv4_address => $scan_apc_pdu_ipv4_address, }}); if ($scan_apc_pdu_model_number ne "DELETED") { # The PDUs only allow one connection at a time, so if another scan agent is # connected, we'll get this issue. As such, check how long it's been missing, and # alert only if it's been missing for 10 minutes. my $age = $anvil->Alert->check_condition_age({name => "scan_apc_pdu::lost_pdu::".$scan_apc_pdu_serial_number}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }}); if ($age > 600) { # Yup! send an alert. my $query = " UPDATE scan_apc_pdus SET scan_apc_pdu_model_number = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; my $variables = { model => $scan_apc_pdu_model_number, serial_numer => $scan_apc_pdu_serial_number, ip_address => $scan_apc_pdu_ipv4_address, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0040", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_pdu_message_0040", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); } } } # Commit the queries. $anvil->Database->write({query => $anvil->data->{sys}{queries}, debug => 2, source => $THIS_FILE, line => __LINE__}); return(0); } # Set the phase-low alert, if not clear before sub clear_phase_low_warning { my ($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid) = @_; my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_low_warning", set_by => $THIS_FILE, clear => 1, }); if ($changed) { # Register an alert-cleared event. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0029", variables => { phase => $scan_apc_pdu_phase_number, name => $pdu_host_name }}); $anvil->Alert->register({ alert_level => "notice", clear => 1, message => "scan_apc_pdu_message_0029,!!phase!".$scan_apc_pdu_phase_number."!!,!!name!".$pdu_host_name."!!", set_by => $THIS_FILE, }); } return(0); } # This sets the phase amparage high warning alert, if set. sub set_phase_high_warning { my ($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid) = @_; my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_high_warning", set_by => $THIS_FILE, }); if ($changed) { # Register an alert-cleared event. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0027", variables => { phase => $scan_apc_pdu_phase_number, name => $pdu_host_name }}); $anvil->Alert->register({ alert_level => "notice", clear => 1, message => "scan_apc_pdu_message_0027,!!phase!".$scan_apc_pdu_phase_number."!!,!!name!".$pdu_host_name."!!", set_by => $THIS_FILE, }); } return(0) } # This clears the phase amparage high warning alert, if set. sub clear_phase_high_warning { my ($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid) = @_; my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_high_warning", set_by => $THIS_FILE, clear => 1, }); if ($changed) { # Register an alert-cleared event. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0028", variables => { phase => $scan_apc_pdu_phase_number, name => $pdu_host_name }}); $anvil->Alert->register({ alert_level => "notice", clear => 1, message => "scan_apc_pdu_message_0028,!!phase!".$scan_apc_pdu_phase_number."!!,!!name!".$pdu_host_name."!!", set_by => $THIS_FILE, }); } return(0) } # This sets the phase high-critical alert, if not already. sub set_phase_high_critical { my ($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid) = @_; my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_high_critical", set_by => $THIS_FILE, }); if ($changed) { # Register an alert-cleared event. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0025", variables => { phase => $scan_apc_pdu_phase_number, name => $pdu_host_name }}); $anvil->Alert->register({ alert_level => "notice", clear => 1, message => "scan_apc_pdu_message_0025,!!phase!".$scan_apc_pdu_phase_number."!!,!!name!".$pdu_host_name."!!", set_by => $THIS_FILE, }); } return(0); } # This clears the phase amparage high critical alert, if set. sub clear_phase_high_critical { my ($anvil, $pdu_host_name, $scan_apc_pdu_phase_number, $scan_apc_pdu_uuid) = @_; my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => "scan_apc-pdu::".$scan_apc_pdu_uuid."::phase::".$scan_apc_pdu_phase_number."::amp_high_critical", set_by => $THIS_FILE, clear => 1, }); if ($changed) { # Register an alert-cleared event. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_message_0026", variables => { phase => $scan_apc_pdu_phase_number, name => $pdu_host_name }}); $anvil->Alert->register({ alert_level => "notice", clear => 1, message => "scan_apc_pdu_message_0026,!!phase!".$scan_apc_pdu_phase_number."!!,!!name!".$pdu_host_name."!!", set_by => $THIS_FILE, }); } return(0) } # This INSERTs a new outlet sub insert_outlets { my ($anvil, $scan_apc_pdu_uuid, $scan_apc_pdu_outlet_number, $scan_apc_pdu_outlet_name, $scan_apc_pdu_outlet_on_phase, $scan_apc_pdu_outlet_state) = @_; my $scan_apc_pdu_outlet_uuid = $anvil->Get->uuid(); my $query = " INSERT INTO scan_apc_pdu_outlets ( scan_apc_pdu_outlet_uuid, scan_apc_pdu_outlet_scan_apc_pdu_uuid, scan_apc_pdu_outlet_number, scan_apc_pdu_outlet_name, scan_apc_pdu_outlet_on_phase, scan_apc_pdu_outlet_state, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_pdu_outlet_uuid).", ".$anvil->Database->quote($scan_apc_pdu_uuid).", ".$anvil->Database->quote($scan_apc_pdu_outlet_number).", ".$anvil->Database->quote($scan_apc_pdu_outlet_name).", ".$anvil->Database->quote($scan_apc_pdu_outlet_on_phase).", ".$anvil->Database->quote($scan_apc_pdu_outlet_state).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; return($scan_apc_pdu_outlet_uuid); } # This UPDATEs a variable sub update_variables { my ($anvil, $scan_apc_pdu_variable_uuid, $variable, $value) = @_; my $query = " UPDATE scan_apc_pdu_variables SET scan_apc_pdu_variable_name = ".$anvil->Database->quote($variable).", scan_apc_pdu_variable_value = ".$anvil->Database->quote($value).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_pdu_variable_uuid = ".$anvil->Database->quote($scan_apc_pdu_variable_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; return(0); } # This INSERTs a new variable sub insert_variables { my ($anvil, $scan_apc_pdu_uuid, $variable, $value) = @_; my $scan_apc_pdu_variable_uuid = $anvil->Get->uuid(); my $query = " INSERT INTO scan_apc_pdu_variables ( scan_apc_pdu_variable_uuid, scan_apc_pdu_variable_scan_apc_pdu_uuid, scan_apc_pdu_variable_is_temperature, scan_apc_pdu_variable_name, scan_apc_pdu_variable_value, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_pdu_variable_uuid).", ".$anvil->Database->quote($scan_apc_pdu_uuid).", FALSE, ".$anvil->Database->quote($variable).", ".$anvil->Database->quote($value).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); push @{$anvil->data->{sys}{queries}}, $query; return($scan_apc_pdu_variable_uuid); } # This calls each PDU, first to get the model number and update the OIDs to use if needed, then gathers the # information from the PDU. sub gather_pdu_data { my ($anvil) = @_; # Loop through the PDUs we found in fences. foreach my $fence_uuid (sort {$a cmp $b} keys %{$anvil->data->{fences}{fence_uuid}}) { my $pdu_ip = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ip_address}; my $pdu_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { fence_uuid => $fence_uuid, pdu_ip => $pdu_ip, pdu_name => $pdu_name, }}); # Have we seen this PDU before? We may have info in our database that's not mapped to fences # yet, so we'll also check by serial number as well. my $scan_apc_pdu_uuid = ""; my $new_pdu = 1; if ((exists $anvil->data->{sql}{fence_uuid_to_apc_pdu_uuid}{$fence_uuid}) && (defined $anvil->data->{sql}{fence_uuid_to_apc_pdu_uuid}{$fence_uuid})) { # Yup! $new_pdu = 0; $scan_apc_pdu_uuid = $anvil->data->{sql}{fence_uuid_to_apc_pdu_uuid}{$fence_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, new_pdu => $new_pdu, }}); } # Can I ping it? This returns '1' if it was pingable, '0' if not. my ($pinged, $average_time) = $anvil->Network->ping({ping => $pdu_ip}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pinged => $pinged, average_time => $average_time, }}); if (not $pinged) { # Can't reach it. $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ping} = 0; $anvil->data->{fences}{fence_uuid}{$fence_uuid}{connected} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fences::fence_uuid::${fence_uuid}::ping" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ping}, "fences::fence_uuid::${fence_uuid}::connected" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{connected}, }}); next; } $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ping} = 1; $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version} = $anvil->data->{snmp}{community}{version}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fences::fence_uuid::${fence_uuid}::ping" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ping}, "fences::fence_uuid::${fence_uuid}::snmp_version" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, }}); my ($scan_apc_pdu_serial_number, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_serial_number}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, data_type => $data_type, }}); # If the serial number is '!!no_connection!!', this might be an old PDU that only supports SNMP v1. if ($scan_apc_pdu_serial_number eq "!!no_connection!!") { # Try SNMP v1 $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fences::fence_uuid::${fence_uuid}::snmp_version" => $anvil->data->{snmp}{community}{version}, }}); ($scan_apc_pdu_serial_number, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_serial_number}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, data_type => $data_type, }}); # If it's still '!!no_connection!!', something else is wrong. Is possible it's a new # PDU with SNMP turned off, perhaps? if ($scan_apc_pdu_serial_number eq "!!no_connection!!") { # No luck $scan_apc_pdu_serial_number = ""; $anvil->data->{fences}{fence_uuid}{$fence_uuid}{connected} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number, "fences::fence_uuid::${fence_uuid}::connected" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{connected}, }}); } } # If we didn't find the PDU using the fence_uuid, see if we can find it by the serial number. if ($new_pdu) { if (($scan_apc_pdu_serial_number) && (exists $anvil->data->{sql}{serial_number_to_apc_pdu_uuid}{$scan_apc_pdu_serial_number})) { # It's new, generate the UUID now. We'll set 'scan_apc_pdu_new' so we know to INSERT # it later. $scan_apc_pdu_uuid = $anvil->data->{sql}{serial_number_to_apc_pdu_uuid}{$scan_apc_pdu_serial_number}; $new_pdu = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, new_pdu => $new_pdu, }}); } else { $scan_apc_pdu_uuid = $anvil->Get->uuid(); $new_pdu = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, new_pdu => $new_pdu, }}); } } $anvil->data->{fences}{fence_uuid}{$fence_uuid}{scan_apc_pdu_uuid} = $scan_apc_pdu_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fences::fence_uuid::${fence_uuid}::scan_apc_pdu_uuid" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{scan_apc_pdu_uuid}, }}); # These are set to avoid 'undefined' variable warnings later if we fail to reach this PDU. $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{pdu_host_name} = $pdu_name; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{new_pdu} = $new_pdu; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_fence_uuid} = $fence_uuid; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_serial_number} = $scan_apc_pdu_serial_number; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_model_number} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_firmware_version} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_hardware_version} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_ipv4_address} = $pdu_ip; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed} = 0; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning} = ""; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical} = ""; # If I got the serial number, I found the PDU. next if not $scan_apc_pdu_serial_number; # In case this PDU disappeared before, this will clear that condition. $anvil->Alert->check_condition_age({clear => 1, name => "scan_apc_pdu::lost_pdu::".$scan_apc_pdu_serial_number}); ############################################################################################# # Base PDU info # ############################################################################################# ### Get the base PDU info. # Model Number ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_model_number}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_model_number}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_model_number" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_model_number}, data_type => $data_type, }}); # Manufacture date ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_manufacture_date" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}, data_type => $data_type, }}); # Firmware version ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_firmware_version}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_firmware_version}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_firmware_version" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_firmware_version}, data_type => $data_type, }}); # Hardware version ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_hardware_version}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_hardware_version}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_hardware_version" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_hardware_version}, data_type => $data_type, }}); # MAC address. Note, this could use a couple different OIDs, depending on the version. It also requires the custom MIB ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_mac_address}, mib => $anvil->data->{'scan-apc-pdu'}{striker_mib}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mac_address" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, data_type => $data_type, }}); if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} eq "#!no_value!#") { # Some older PDUs use a different OID. ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_mac_address_alt}, mib => $anvil->data->{'scan-apc-pdu'}{striker_mib}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mac_address" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, data_type => $data_type, }}); } # Make the MAC address lower case and replace the spaces with colons $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} = lc($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}); $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} =~ s/^\s+//g; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} =~ s/\s+$//g; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} =~ s/ /:/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mac_address" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, }}); # Read the MTU. This again could be at one of two OIDs. ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mtu_size" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, data_type => $data_type, }}); if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size} eq "#!no_value!#") { # Some older PDUs use a different OID. ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_mtu_size_alt}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mtu_size" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, data_type => $data_type, }}); } # Read the link speed. Again, this could be at alternate OIDs. ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_link_speed}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_link_speed" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}, data_type => $data_type, }}); if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed} eq "#!no_value!#") { # Some older PDUs use a different OID. ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_link_speed_alt}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_link_speed" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}, data_type => $data_type, }}); } # Read in the phase count ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_phase_count}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_phase_count" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count}, data_type => $data_type, }}); # Read in the outlet count ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu}{scan_apc_pdu_outlet_count}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_outlet_count" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count}, data_type => $data_type, }}); ### These change often and will go into the 'variables' table # Read the uptime ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_variables}{uptime}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_variables::uptime" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}, data_type => $data_type, }}); # Total watt draw ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_variables}{total_wattage_draw}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_variables::total_wattage_draw" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw}, data_type => $data_type, }}); ### These are used later for checking the state of the phases. They are not stored in the database. # Macimum allowed amperage ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_phases}{scan_apc_pdu_phase_max_amperage}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::maximum" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum}, data_type => $data_type, }}); # Low amperage on a phase threshold ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_phases}{phase_low_amp_warning}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::low_warning" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning}, data_type => $data_type, }}); # High warning ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_phases}{phase_high_amp_warning}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::high_warning" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning}, data_type => $data_type, }}); # Phase high amperage threshold ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $anvil->data->{oids}{scan_apc_pdu_phases}{phase_high_amp_critical}, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::high_critical" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}, data_type => $data_type, }}); ### Convert some unknown values to values we can store in the database # MAC address if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} eq "#!no_value!#") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address} = "xx:xx:xx:xx:xx:xx"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mac_address" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mac_address}, }}); } # MTU if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size} eq "#!no_value!#") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_mtu_size" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_mtu_size}, }}); } # Link speed if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed} eq "#!no_value!#") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_link_speed" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_link_speed}, }}); } # Wattage isn't available on older PDUs if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw} eq "#!no_value!#") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_variables::total_wattage_draw" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{total_wattage_draw}, }}); } ### TODO: We should probably sanity check the various values. Error or set? # If the (high critical amperage + 'scan-apc-pdu::critical_amps_below_max') > maximum # amperage, we'll set the critical warning level to be # (maximum - 'scan-apc-pdu::critical_amps_below_max') $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "scan-apc-pdu::critical_amps_below_max" => $anvil->data->{'scan-apc-pdu'}{critical_amps_below_max}, }}); if (($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical} + $anvil->data->{'scan-apc-pdu'}{critical_amps_below_max}) > $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum}) { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical} = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{maximum} - $anvil->data->{'scan-apc-pdu'}{critical_amps_below_max}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::high_critical" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}, }}); } # Make sure that the warning is at least 'scan-apc-pdu::warning_amps_below_critical' if (($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning} + $anvil->data->{'scan-apc-pdu'}{warning_amps_below_critical}) > $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical}) { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning} = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical} - $anvil->data->{'scan-apc-pdu'}{warning_amps_below_critical}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::high_warning" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning}, }}); } # Set the alert clear levels $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_critical} = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_critical} - $anvil->data->{'scan-apc-pdu'}{clear_alert_threshold}; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_warning} = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{high_warning} - $anvil->data->{'scan-apc-pdu'}{clear_alert_threshold}; $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_low_warning} = $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{low_warning} + $anvil->data->{'scan-apc-pdu'}{clear_alert_threshold}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::clear_high_critical" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_critical}, "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::clear_high_warning" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_high_warning}, "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::amperage::clear_low_warning" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{amperage}{clear_low_warning}, }}); # Uptime is in ticks $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime} /= $anvil->data->{'scan-apc-pdu'}{ticks_per_second}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu:${scan_apc_pdu_serial_number}::scan_apc_pdu_variables::uptime" => $anvil->Convert->add_commas({number => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}})." (".$anvil->Convert->time({'time' => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_variables}{uptime}, translate => 1}).")", }}); # The dates are in 'mm/dd/yyyy' or 'mm/dd/yy' format, convert them to 'yyyy/mm/dd' if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date} =~ /(\d\d)\/(\d\d)\/(\d\d\d\d)$/) { my $year = $3; my $month = $1; my $day = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { year => $year, month => $month, day => $day, }}); $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date} = $year."/".$month."/".$day; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_manufacture_date" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}, }}); } elsif ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date} =~ /(\d\d)\/(\d\d)\/(\d\d)$/) { my $year = $3; my $month = $1; my $day = $2; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "year" => $year, "month" => $month, "day" => $day, }}); if ($year < 70) { $year += 2000; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "year" => $year, }}); } else { $year += 1900; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "year" => $year, }}); } $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date} = $year."/".$month."/".$day; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu::scan_apc_pdu_manufacture_date" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_manufacture_date}, }}); } # If an alert (cleared) message/log is needed for either phase or outlet count, they'll use this hash my $variables = { name => $pdu_name, ip => $pdu_ip, serial_number => $scan_apc_pdu_serial_number, }; # Verify that the phase count is valid my $bad_phase_count_key = "scan_apc_pdu::".$scan_apc_pdu_uuid."::bad_phase_count"; if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count} !~ /^\d+$/) { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_pdu_message_0002", variables => $variables}); my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => $bad_phase_count_key, set_by => $THIS_FILE, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Alert->register({alert_level => "warning", message => "scan_apc_pdu_message_0002", variables => $variables, set_by => $THIS_FILE}); } $anvil->nice_exit({exit_code => 1}); } else { # Clear the alert? my $changed = $anvil->Alert->check_alert_sent({ debug => 3, clear => 1, record_locator => $bad_phase_count_key, set_by => $THIS_FILE, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_pdu_message_0003", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_pdu_message_0003", variables => $variables, set_by => $THIS_FILE}); } } # Now read the phase data foreach my $scan_apc_pdu_phase_number (1..$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_phase_count}) { # Stick the phase onto the end of the OID. my $oid = $anvil->data->{oids}{scan_apc_pdu_phases}{scan_apc_pdu_phase_current_amperage}.$scan_apc_pdu_phase_number; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "scan_apc_pdu_phase_number" => $scan_apc_pdu_phase_number, "oid" => $oid, }}); # Read this phase's amperage ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $oid, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_current_amperage" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}, data_type => $data_type, }}); # The amperage is in 1/10 amps, so divide by 10. if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage} =~ /^\d+$/) { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_phases::${scan_apc_pdu_phase_number}::scan_apc_pdu_phase_current_amperage" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_phases}{$scan_apc_pdu_phase_number}{scan_apc_pdu_phase_current_amperage}, }}); } } # Read the outlet data, if the outlet count is sane. my $bad_outlet_count_key = "scan_apc_pdu::".$scan_apc_pdu_uuid."::bad_outlet_count"; if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count} !~ /^\d+$/) { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_pdu_message_0004", variables => $variables}); my $changed = $anvil->Alert->check_alert_sent({ debug => 3, record_locator => $bad_outlet_count_key, set_by => $THIS_FILE, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Alert->register({alert_level => "warning", message => "scan_apc_pdu_message_0004", variables => $variables, set_by => $THIS_FILE}); } $anvil->nice_exit({exit_code => 1}); } else { # Clear the alert? my $changed = $anvil->Alert->check_alert_sent({ debug => 3, clear => 1, record_locator => $bad_outlet_count_key, set_by => $THIS_FILE, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_pdu_message_0005", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_pdu_message_0005", variables => $variables, set_by => $THIS_FILE}); } } # Now read the outlet data foreach my $scan_apc_pdu_outlet_number (1..$anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu}{scan_apc_pdu_outlet_count}) { # Stick the outlet onto the end of the OIDs. my $outlet_name_oid = $anvil->data->{oids}{scan_apc_pdu_outlets}{scan_apc_pdu_outlet_name}.$scan_apc_pdu_outlet_number; my $outlet_phase_oid = $anvil->data->{oids}{scan_apc_pdu_outlets}{scan_apc_pdu_outlet_on_phase}.$scan_apc_pdu_outlet_number; my $outlet_state_oid = $anvil->data->{oids}{scan_apc_pdu_outlets}{scan_apc_pdu_outlet_state}.$scan_apc_pdu_outlet_number; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "outlet_name_oid" => $outlet_name_oid, "outlet_phase_oid" => $outlet_phase_oid, "outlet_state_oid" => $outlet_state_oid, }}); ### Read the OID # outlet name ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $outlet_name_oid, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_name" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_name}, data_type => $data_type, }}); # Outlet number on phase ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $outlet_phase_oid, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_on_phase" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_on_phase}, data_type => $data_type, }}); # State of the outlet ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $pdu_ip, oid => $outlet_state_oid, version => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_state" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, data_type => $data_type, }}); # The state is; 1 = on, 2 = off, 4 = unknown if ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} eq "1") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} = "on"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_state" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, }}); } elsif ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} eq "2") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} = "off"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_state" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, }}); } elsif ($anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} eq "3") { $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state} = "unknown"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "pdu::scan_apc_pdu_uuid::${scan_apc_pdu_uuid}::scan_apc_pdu_outlets::${scan_apc_pdu_outlet_number}::scan_apc_pdu_outlet_state" => $anvil->data->{pdu}{scan_apc_pdu_uuid}{$scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_state}, }}); } } } return(0); } # This looks for APC PDUs. sub find_pdus { my ($anvil) = @_; # Search in 'fences' for agents starting with 'fence_apc_'. These aren't bound to hosts (or even # Anvil! systems), so not all may be available. my $query = " SELECT fence_uuid, fence_name, fence_arguments FROM fences WHERE fence_agent LIKE 'fence_apc_%' AND fence_arguments != 'DELETED' ORDER BY fence_name ASC ;"; $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 => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $fence_uuid = $row->[0]; my $fence_name = $row->[1]; my $fence_arguments = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { fence_uuid => $fence_uuid, fence_name => $fence_name, fence_arguments => $fence_arguments, }}); if ($fence_arguments =~ /ip=\"(.*?)\"/) { my $ip_address = $1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ip_address => $ip_address }}); $anvil->data->{fences}{fence_uuid}{$fence_uuid}{name} = $fence_name; $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ip_address} = $ip_address; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "fences::fence_uuid::${fence_uuid}::name" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{name}, "fences::fence_uuid::${fence_uuid}::ip_address" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ip_address}, }}); # If there are two or more entries in scan_apc_pdu for this fence UUID, remove the extras. my $query = " SELECT scan_apc_pdu_uuid, scan_apc_pdu_model_number FROM scan_apc_pdus WHERE scan_apc_pdu_fence_uuid = ".$anvil->Database->quote($fence_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); if ($count > 1) { # Duplicate! Is one of them marked as DELETED? foreach my $row (@{$results}) { # Is this one deleted? my $scan_apc_pdu_uuid = $row->[0]; my $scan_apc_pdu_model_number = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid, scan_apc_pdu_model_number => $scan_apc_pdu_model_number, }}); if ($scan_apc_pdu_model_number eq "DELETED") { # Take this one out. my $variables = { name => $fence_name, uuid => $scan_apc_pdu_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_log_0002", variables => $variables}); $anvil->Alert->register({ alert_level => "notice", message => "scan_apc_pdu_log_0002", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); delete_pdu($anvil, $scan_apc_pdu_uuid); $count--; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); } last if $count == 1; } # If count is still > 1, we need to arbitrarily delete an interface. if ($count > 1) { foreach my $row (@{$results}) { # Is this one deleted? my $scan_apc_pdu_uuid = $row->[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid }}); my $variables = { name => $fence_name, uuid => $scan_apc_pdu_uuid, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_log_0002", variables => $variables}); $anvil->Alert->register({ alert_level => "notice", message => "scan_apc_pdu_log_0002", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++, }); delete_pdu($anvil, $scan_apc_pdu_uuid); $count--; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); } last if $count == 1; } } } } my $pdu_count = keys %{$anvil->data->{fences}{fence_uuid}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { pdu_count => $pdu_count }}); return($pdu_count); } sub delete_pdu { my ($anvil, $scan_apc_pdu_uuid) = @_; my $queries = [ "DELETE FROM scan_apc_pdu_variables WHERE scan_apc_pdu_variable_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";", "DELETE FROM scan_apc_pdu_phases WHERE scan_apc_pdu_phase_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";", "DELETE FROM scan_apc_pdu_outlets WHERE scan_apc_pdu_outlet_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";", "DELETE FROM scan_apc_pdus WHERE scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";" ]; $anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); return(0); }