You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10186 lines
516 KiB
10186 lines
516 KiB
#!/usr/bin/perl |
|
# |
|
# This software was created by Alteeve's Niche! Inc. and has been released |
|
# under the terms of the GNU GPL version 2. |
|
# |
|
# ScanCore Scan Agent for LSI-based RAID controllers using the 'storcli64' command line tool. |
|
# |
|
# https://alteeve.com |
|
# |
|
# Exit Codes: |
|
# 0 - Success |
|
# 1 - storcli64 not installed |
|
# 2 - storcli64 is installed but it is not executable. |
|
# 3 - No LSI-based controllers found. |
|
# 4 - Got data from the wrong controller. |
|
# 5 - Unexpecte status when querying adapter |
|
# 6 - Failed to parse out the controller's serial number. |
|
# 7 - Failed to match a BBU to a host controller's serial number. |
|
# 8 - Failed to match a controller's serial number to a controller UUID. |
|
# 9 - Failed to match a Cachevault to a host controller's serial number. |
|
# 10 - Failed to match a virtual drive ID string to a host controller's serial number. |
|
# 11 - Failed to match a drive group ID string to a host controller's serial number. |
|
# 12 - Failed to get the controller serial number that a physical drive is connected to. |
|
# 13 - Failed to get the serial number of a physical drive. |
|
# 14 - Drive group UUID doesn't exist when it should have. |
|
# 15 - Controller serial number for an existing drive group wasn't found. |
|
# 16 - Non-numeric value in numeric virtual drive variable. |
|
# |
|
# 255 - The host's UUID isn't in the hosts table yet, ScanCore itself hasn't been run. |
|
# |
|
# TODO: |
|
# - DELETE a remaining_reserve_space variable from a history.scan_storcli_variables on one dashboard and then |
|
# trigger a resync. Appears to be causing a duplicate insert error. |
|
# |
|
# - Check the cache policy and reset it to 'writeback' if the BBU/FBU is healthy and the cache changes to |
|
# write-through. |
|
# - When two or more drives have errors, 'drive:other_error_count' is only set to '1'. It should be the |
|
# number of drives with errors. Also, if the error on one drive got above 100, its weight should be '2' and |
|
# above 1000, set to '3'. |
|
# |
|
# NOTE: |
|
# - LSI seems to flip between "Virtual Drive" and "Virtual Disk". We're standardizing on "Virtual Drive". |
|
# |
|
# NOTE: |
|
# - Health values |
|
# - Controller - Correctable errors = 1 |
|
# - Controller - Uncorrectable errors = 5 |
|
# - Controller - Status changes = 5 |
|
# - Drive group - partially degraded = 5 |
|
# - Drive group - degraded = 10 |
|
# - Cachevault - Replacement needed = 5 |
|
# - BBU - Replacement needed = 5 |
|
# - Temperature - Critical = 2 |
|
# - Temperature - Warning = 1 |
|
|
|
# Use my modules. |
|
use strict; |
|
use warnings; |
|
use Anvil::Tools; |
|
use Data::Dumper; |
|
use Math::BigInt; |
|
no warnings 'recursion'; |
|
|
|
# Disable buffering |
|
$| = 1; |
|
|
|
# Prevent a discrepency between UID/GID and EUID/EGID from throwing an error. |
|
$< = $>; |
|
$( = $); |
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
|
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
|
{ |
|
$running_directory =~ s/^\./$ENV{PWD}/; |
|
} |
|
|
|
my $anvil = Anvil::Tools->new(); |
|
|
|
# Make sure we're running as 'root' |
|
# $< == real UID, $> == effective UID |
|
if (($< != 0) && ($> != 0)) |
|
{ |
|
# Not root |
|
print $anvil->Words->string({key => "error_0005"})."\n"; |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# Here we store data and variables for this agent. |
|
$anvil->data->{'scan-storcli'} = { |
|
alert_sort => 2, |
|
arguments => { |
|
adapter_count => "show ctrlcount", |
|
alarm_state => "show alarm", |
|
# BBU battery or FBU capacitor bank info. |
|
bgi_rate => "show bgirate", |
|
bbu_data => "/bbu show all", |
|
cc_rate => "show ccrate", |
|
cachevault_data => "/cv show all", |
|
controller_info => "show all", |
|
physical_disk_data => "/eall /sall show all", |
|
performance_mode => "show perfmode", |
|
pr_rate => "show prrate", |
|
rebuild_rate => "show rebuildrate", |
|
virtual_drive_data => "/vall show all", |
|
}, |
|
disable => 0, |
|
health => { |
|
old => {}, |
|
new => {}, |
|
}, |
|
# This will keep track of devices with serial numbers so that it is easy to look up |
|
# the UUID from the serial numbers and vice versa. |
|
controllers => { |
|
by_serial => {}, |
|
by_uuid => {}, |
|
}, |
|
cachevaults => { |
|
by_serial => {}, |
|
by_uuid => {}, |
|
}, |
|
bbus => { |
|
by_serial => {}, |
|
by_uuid => {}, |
|
}, |
|
physical_drives => { |
|
by_serial => {}, |
|
by_uuid => {}, |
|
}, |
|
disable => 0, |
|
language => "en_CA", |
|
log_level => 1, |
|
log_language => "en_CA", |
|
log_file => "/var/log/ScanCore.log", |
|
log_db_transactions => 0, |
|
thresholds => { |
|
# 45646-00B_Cache_Backup_Products_SAS_SATA_RAID_Controller_UserGd.pdf -> Specifications for the BBU Models |
|
bbu => { |
|
normal => { |
|
high_warning => 35, |
|
high_critical => 40, |
|
low_warning => 15, |
|
low_critical => 10, |
|
jump => 3, |
|
buffer => 2, |
|
}, |
|
discharging => { |
|
high_warning => 50, |
|
high_critical => 55, |
|
low_warning => 15, |
|
low_critical => 10, |
|
jump => 3, |
|
buffer => 2, |
|
}, |
|
}, |
|
# 45646-00B_Cache_Backup_Products_SAS_SATA_RAID_Controller_UserGd.pdf -> Specifications for the Cachevaul Models |
|
cachevault => { |
|
high_warning => 50, |
|
high_critical => 55, |
|
low_warning => 5, |
|
low_critical => 0, |
|
jump => 5, |
|
buffer => 3, |
|
}, |
|
# This is used for unknown sensors and really shouldn't be used at all. |
|
'default' => { |
|
high_warning => 50, |
|
high_critical => 55, |
|
low_warning => 15, |
|
low_critical => 10, |
|
jump => 5, |
|
buffer => 3, |
|
}, |
|
drives => { |
|
# http://storage.toshiba.com/docs/product-datasheets/mk01grrb-r.pdf |
|
hdd => { |
|
high_warning => 50, |
|
high_critical => 55, |
|
low_warning => 10, |
|
low_critical => 5, |
|
jump => 3, |
|
buffer => 2, |
|
}, |
|
# http://toshiba.semicon-storage.com/us/product/storage-products/enterprise-ssd/px02smb-px02smfxxx.html |
|
ssd => { |
|
high_warning => 50, |
|
high_critical => 55, |
|
low_warning => 5, |
|
low_critical => 0, |
|
jump => 3, |
|
buffer => 2, |
|
}, |
|
}, |
|
# See email from M. Labrosse on 2014/04/14 @ 12:20; Specs not publicly available |
|
raid_on_chip => { |
|
high_warning => 108, |
|
high_critical => 115, |
|
low_warning => 15, |
|
low_critical => 10, |
|
jump => 10, |
|
buffer => 5, |
|
}, |
|
}, |
|
queries => [], |
|
}; |
|
|
|
$anvil->Storage->read_config(); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "log_0115", variables => { program => $THIS_FILE }}); |
|
|
|
# Read switches |
|
$anvil->data->{switches}{force} = 0; |
|
$anvil->data->{switches}{purge} = 0; |
|
$anvil->Get->switches; |
|
|
|
# If we're disabled and '--force' wasn't used, exit. |
|
if (($anvil->data->{scancore}{'scan-storcli'}{disable}) && (not $anvil->data->{switches}{force})) |
|
{ |
|
# Exit. |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
# Handle start-up tasks |
|
my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE}); |
|
if ($problem) |
|
{ |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
if ($anvil->data->{switches}{purge}) |
|
{ |
|
# This can be called when doing bulk-database purges. |
|
my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"; |
|
$anvil->Database->purge_data({ |
|
debug => 2, |
|
tables => $anvil->Database->get_tables_from_schema({schema_file => $schema_file}), |
|
}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "scan_storcli_message_0001"}); |
|
|
|
# This does two things; It checks to see if storcli64 is installed (exits '1' if not, exits '2' if not |
|
# executable) and then checks to see if any controllers are found in the system (exits '3' if not). |
|
find_lsi_controllers($anvil); |
|
|
|
# If we're still alive, start gathering data. |
|
gather_data($anvil); |
|
|
|
# Figure out, other than temperatures, what should be added to or removed from health. |
|
pre_process_health($anvil); |
|
|
|
# Look for changes. |
|
find_changes($anvil); |
|
|
|
# Process temperatures! This also sets health values for warning and critical temperatures so make sure we |
|
# always call this before process_health(). |
|
process_temperatures($anvil); |
|
|
|
# Finally, process health weights. |
|
process_health($anvil); |
|
|
|
# Update the database |
|
$anvil->Database->insert_or_update_updated({updated_by => $THIS_FILE}); |
|
|
|
# Clean up and go away. |
|
$anvil->nice_exit({exit_code => 0}); |
|
|
|
|
|
############################################################################################################# |
|
# Function below # |
|
############################################################################################################# |
|
|
|
# This looks for anything other than temperature sensors that will feed into the health of the node. |
|
sub pre_process_health |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Is the array degraded or partially degraded? |
|
foreach my $id_string (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}}) |
|
{ |
|
foreach my $drive_group (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$id_string}{drive_group}}) |
|
{ |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
|
|
my $value = $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
if ($value eq "Partially Degraded") |
|
{ |
|
# Partially degraded array |
|
my $health_source_name = "drive_group:".$id_string,"-".$drive_group.":".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 5; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
elsif ($value eq "Degraded") |
|
{ |
|
# Degraded array |
|
my $health_source_name = "drive_group:".$id_string,"-".$drive_group.":".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 10; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
} |
|
} |
|
} |
|
|
|
# Controllers. |
|
foreach my $serial_number (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}}) |
|
{ |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}{$serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"controller::serial_number::${serial_number}::variable::$variable" => $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable}, |
|
}}); |
|
|
|
my $value = $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable}; |
|
if (($variable eq "alarm_state") && (lc($value) ne "missing") && (lc($value) ne "off")) |
|
{ |
|
my $health_source_name = "controller:".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
elsif (($variable eq "memory_correctable_errors") && ($value ne "0")) |
|
{ |
|
# TODO: I might want to scale this where 1~X = 1, Y~Z = 3, etc |
|
my $health_source_name = "controller:".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
elsif (($variable eq "memory_uncorrectable_errors") && ($value ne "0")) |
|
{ |
|
# TODO: I might want to scale this where 1~X = 5, Y~Z = 10, etc |
|
my $health_source_name = "controller:".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 5; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
elsif (($variable eq "controller_status") && (lc($value) ne "optimal")) |
|
{ |
|
# 'Needs Attention' when array degrades |
|
my $health_source_name = "controller:".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 5; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Physical Drives. |
|
foreach my $scan_storcli_virtual_drive_id_string (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}}) |
|
{ |
|
foreach my $drive_group (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}}) |
|
{ |
|
foreach my $enclosure_id (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}}) |
|
{ |
|
foreach my $slot_number (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}}) |
|
{ |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::${variable}" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
|
|
my $value = $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}; |
|
if ((($variable eq "media_error_count") or ($variable eq "other_error_count")) && ($value ne "0")) |
|
{ |
|
# If the count is over 50, set to '2'. If over 5, set to 1. |
|
my $health_source_name = "drive:".$variable; |
|
if ($value > 50) |
|
{ |
|
$anvil->data->{health}{new}{$health_source_name} = 2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:alarm-state" => $anvil->data->{health}{new}{'controller:alarm-state'}, |
|
}}); |
|
} |
|
elsif ($value > 5) |
|
{ |
|
$anvil->data->{health}{new}{$health_source_name} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:alarm-state" => $anvil->data->{health}{new}{'controller:alarm-state'}, |
|
}}); |
|
} |
|
} |
|
elsif (($variable eq "predictive_failure_count") && ($value ne "0")) |
|
{ |
|
# A single tick of this requires immediate replacement. |
|
my $health_source_name = "drive:".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::controller:alarm-state" => $anvil->data->{health}{new}{'controller:alarm-state'}, |
|
}}); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
# Cachevaults. |
|
foreach my $cachevault_serial_number (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}}) |
|
{ |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"cachevault::serial_number::${cachevault_serial_number}::variable::$variable" => $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}, |
|
}}); |
|
|
|
my $value = $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
if (($variable eq "replacement_required") && (lc($value) eq "yes")) |
|
{ |
|
my $health_source_name = "cachevault:".$cachevault_serial_number.":".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 5; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# BBUs |
|
foreach my $bbu_serial_number (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}}) |
|
{ |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bbu::serial_number::${bbu_serial_number}::variable::$variable" => $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}, |
|
}}); |
|
|
|
my $value = $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
if (($variable eq "replacement_required") && (lc($value) eq "yes")) |
|
{ |
|
my $health_source_name = "bbu:".$bbu_serial_number.":".$variable; |
|
$anvil->data->{health}{new}{$health_source_name} = 5; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This reads in all health wieghts previously set, alters ones as needed, INSERTs new ones and DELETEs old |
|
# ones. |
|
sub process_health |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# This will hold our updates. |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
# Read in previous health values. |
|
my $query = " |
|
SELECT |
|
health_uuid, |
|
health_agent_name, |
|
health_source_name, |
|
health_source_weight |
|
FROM |
|
health |
|
WHERE |
|
health_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
health_agent_name = ".$anvil->Database->quote($THIS_FILE)." |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"results" => $results, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $health_uuid = $row->[0]; |
|
my $health_agent_name = $row->[1]; |
|
my $health_source_name = $row->[2]; |
|
my $health_source_weight = $row->[3]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health_uuid" => $health_uuid, |
|
"health_agent_name" => $health_agent_name, |
|
"health_source_name" => $health_source_name, |
|
"health_source_weight" => $health_source_weight, |
|
}}); |
|
|
|
$anvil->data->{health}{old}{$health_source_name}{uuid} = $health_uuid; |
|
$anvil->data->{health}{old}{$health_source_name}{value} = $health_source_weight; |
|
} |
|
|
|
# Read in the new ones |
|
foreach my $health_source_name (sort {$a cmp $b} keys %{$anvil->data->{health}{new}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
|
|
my $health_uuid = ""; |
|
if (exists $anvil->data->{health}{old}{$health_source_name}) |
|
{ |
|
$health_uuid = $anvil->data->{health}{old}{$health_source_name}{uuid}; |
|
} |
|
$health_uuid = $anvil->Database->insert_or_update_health({ |
|
debug => 2, |
|
cache => $anvil->data->{'scan-storcli'}{queries}, |
|
health_uuid => $health_uuid, |
|
health_host_uuid => $anvil->Get->host_uuid, |
|
health_agent_name => $THIS_FILE, |
|
health_source_name => $health_source_name, |
|
health_source_weight => $anvil->data->{health}{new}{$health_source_name}, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { health_uuid => $health_uuid }}); |
|
} |
|
|
|
# Delete any old entries that are left. |
|
foreach my $health_source_name (sort {$a cmp $b} keys %{$anvil->data->{health}{old}}) |
|
{ |
|
# Well set the source name to 'DELETED'. |
|
my $health_uuid = $anvil->Database->insert_or_update_health({ |
|
debug => 2, |
|
cache => $anvil->data->{'scan-storcli'}{queries}, |
|
'delete' => 1, |
|
health_uuid => $anvil->data->{health}{old}{$health_source_name}{uuid}, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { health_uuid => $health_uuid }}); |
|
} |
|
|
|
# Now commit the changes. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
# This reads in the various temperature sensors we read from this run and will set the temperature table |
|
# and/or set/clear warnings/critical states. |
|
sub process_temperatures |
|
{ |
|
my ($anvil) = @_; |
|
|
|
### NOTE: We use 'sensor_host' to hold the serial number of the device hosting the sensor. |
|
# First, read in all existing entries. We'll compare and UPDATE or INSERT as needed and DELETE any |
|
# stale entries. |
|
my $query = " |
|
SELECT |
|
temperature_uuid, |
|
temperature_sensor_name, |
|
temperature_sensor_host, |
|
temperature_value_c, |
|
temperature_weight, |
|
temperature_state, |
|
temperature_is |
|
FROM |
|
temperature |
|
WHERE |
|
temperature_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
temperature_agent_name = ".$anvil->Database->quote($THIS_FILE)." |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
|
|
# One or more records were found. |
|
foreach my $row (@{$results}) |
|
{ |
|
my $temperature_uuid = $row->[0]; |
|
my $temperature_sensor_name = $row->[1]; |
|
my $temperature_sensor_host = $row->[2]; |
|
my $temperature_value_c = $row->[3]; |
|
my $temperature_weight = $row->[4]; |
|
my $temperature_state = $row->[5]; |
|
my $temperature_is = $row->[6]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_uuid => $temperature_uuid, |
|
temperature_sensor_name => $temperature_sensor_name, |
|
temperature_sensor_host => $temperature_sensor_host, |
|
temperature_value_c => $temperature_value_c, |
|
temperature_weight => $temperature_weight, |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
|
|
$anvil->data->{old}{temperature}{$temperature_sensor_name}{$temperature_sensor_host} = { |
|
temperature_uuid => $temperature_uuid, |
|
temperature_value_c => $temperature_value_c, |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}; |
|
} |
|
|
|
# Loop through the temperature from this scan. |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{new}{temperature}}) |
|
{ |
|
foreach my $serial_number (sort {$a cmp $b} keys %{$anvil->data->{new}{temperature}{$variable}}) |
|
{ |
|
my $new_temperature_value_c = $anvil->data->{new}{temperature}{$variable}{$serial_number}{temperature_value_c}; |
|
my $new_temperature_state = $anvil->data->{new}{temperature}{$variable}{$serial_number}{temperature_state}; |
|
my $new_temperature_is = $anvil->data->{new}{temperature}{$variable}{$serial_number}{temperature_is}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
serial_number => $serial_number, |
|
new_temperature_value_c => $new_temperature_value_c, |
|
new_temperature_state => $new_temperature_state, |
|
new_temperature_is => $new_temperature_is, |
|
}}); |
|
|
|
# If the state is 'warning', set a health weight of 1 and set critical to 2. |
|
my $health_source_name = ""; |
|
if ($new_temperature_state eq "warning") |
|
{ |
|
$health_source_name = "temperature:".$serial_number; |
|
$anvil->data->{health}{new}{$health_source_name} = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
elsif ($new_temperature_state eq "critical") |
|
{ |
|
$health_source_name = "temperature:".$serial_number; |
|
$anvil->data->{health}{new}{$health_source_name} = 2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"health::new::$health_source_name" => $anvil->data->{health}{new}{$health_source_name}, |
|
}}); |
|
} |
|
|
|
# Store |
|
my $temperature_uuid = ""; |
|
if (exists $anvil->data->{old}{temperature}{$variable}{$serial_number}) |
|
{ |
|
$temperature_uuid = $anvil->data->{old}{temperature}{$variable}{$serial_number}{temperature_uuid}; |
|
delete $anvil->data->{old}{temperature}{$variable}{$serial_number}; |
|
} |
|
$temperature_uuid = $anvil->Database->insert_or_update_temperature({ |
|
cache => $anvil->data->{'scan-storcli'}{queries}, |
|
debug => 2, |
|
temperature_uuid => $temperature_uuid, |
|
temperature_host_uuid => $anvil->Get->host_uuid, |
|
temperature_agent_name => $THIS_FILE, |
|
temperature_sensor_host => $serial_number, |
|
temperature_sensor_name => $variable, |
|
temperature_value_c => $new_temperature_value_c, |
|
temperature_state => $new_temperature_state, |
|
temperature_is => $new_temperature_is, |
|
temperature_weight => $anvil->data->{health}{new}{$health_source_name}, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_uuid => $temperature_uuid }}); |
|
} |
|
} |
|
|
|
# Now, if any undeleted old entries remain, delete them from the database. |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{old}{temperature}}) |
|
{ |
|
foreach my $serial_number (sort {$a cmp $b} keys %{$anvil->data->{old}{temperature}{$variable}}) |
|
{ |
|
my $temperature_uuid = $anvil->data->{old}{temperature}{$variable}{$serial_number}{temperature_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_uuid => $temperature_uuid }}); |
|
|
|
$temperature_uuid = $anvil->Database->insert_or_update_temperature({ |
|
cache => $anvil->data->{'scan-storcli'}{queries}, |
|
debug => 2, |
|
'delete' => 1, |
|
temperature_uuid => $temperature_uuid, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_uuid => $temperature_uuid }}); |
|
} |
|
} |
|
|
|
# Commit the queries. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
# This returns the value for a given storcli DB variable from this host. |
|
sub get_scan_storcli_variable |
|
{ |
|
my ($anvil, $scan_storcli_variable_name, $scan_storcli_variable_source_table, $scan_storcli_variable_source_uuid) = @_; |
|
|
|
my $query = " |
|
SELECT |
|
scan_storcli_variable_value |
|
FROM |
|
scan_storcli_variables |
|
WHERE |
|
scan_storcli_variable_name = ".$anvil->Database->quote($scan_storcli_variable_name)." |
|
AND |
|
scan_storcli_variable_source_table = ".$anvil->Database->quote($scan_storcli_variable_source_table)." |
|
AND |
|
scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_variable_source_uuid)." |
|
AND |
|
scan_storcli_variable_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $value = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; |
|
$value = "" if not defined $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
|
|
return($value); |
|
} |
|
|
|
# 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) = @_; |
|
|
|
# Read in the old data. As we compare and UPDATE if needed, then we'll delete. If any are not found, |
|
# then it must be new and will be INSERTed. Any old records left over will have vanished. |
|
read_last_scan($anvil); |
|
|
|
### NOTE: We will loop through each section of data we scanned, deleting records as we process them |
|
### that existed in the DB, and then marking as removed anything left in the databased data not |
|
### seen in this scan. |
|
process_controllers($anvil); |
|
process_bbus($anvil); |
|
process_cachevaults($anvil); |
|
process_virtual_drives($anvil); # This calls process_drive_groups(); |
|
process_physical_disks($anvil); |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted drive groups. |
|
sub process_drive_groups |
|
{ |
|
my ($anvil, $scan_storcli_virtual_drive_id_string, $scan_storcli_drive_group_virtual_drive_uuid, $controller_uuid, $host_controller_serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
scan_storcli_drive_group_virtual_drive_uuid => $scan_storcli_drive_group_virtual_drive_uuid, |
|
controller_uuid => $controller_uuid, |
|
host_controller_serial_number => $host_controller_serial_number, |
|
}}); |
|
|
|
### NOTE: The parent VD may be VANISHED, in which case this DG is likely VANISHED, too. |
|
# Show the drive group and drives. |
|
foreach my $drive_group (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}}) |
|
{ |
|
my $scan_storcli_drive_group_id_string = $scan_storcli_virtual_drive_id_string."-dg".$drive_group; |
|
my $virtual_drive = ($scan_storcli_virtual_drive_id_string =~ /-vd(\d+)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
virtual_drive => $virtual_drive, |
|
drive_group => $drive_group, |
|
}}); |
|
|
|
# Make sure I have the host's serial number and UUID. |
|
if (not $host_controller_serial_number) |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0011", variables => { id_string => $scan_storcli_virtual_drive_id_string }}); |
|
$anvil->nice_exit({exit_code => 11}); |
|
} |
|
if (not $controller_uuid) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0008", variables => { serial_number => $host_controller_serial_number }}); |
|
$anvil->nice_exit({exit_code => 8}); |
|
} |
|
|
|
### NOTE: This is here purely for debugging. |
|
# Show the basic drive group data |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
$anvil->Log->variables({ |
|
source => $THIS_FILE, |
|
line => __LINE__, |
|
level => 2, |
|
prefix => $scan_storcli_drive_group_id_string." (".$drive_group.") - ".$type, |
|
list => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{$type}, |
|
}); |
|
} |
|
|
|
# Is this a new Drive Group? |
|
my $scan_storcli_drive_group_uuid = ""; |
|
my $is_new = 0; |
|
if (exists $anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string}) |
|
{ |
|
# Yes! |
|
$scan_storcli_drive_group_uuid = $anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_drive_group_uuid => $scan_storcli_drive_group_uuid }}); |
|
} |
|
else |
|
{ |
|
# No, this is a new Drive Group. Create a new UUID for it. |
|
$scan_storcli_drive_group_uuid = $anvil->Get->uuid(); |
|
$is_new = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_drive_group_uuid => $scan_storcli_drive_group_uuid, |
|
is_new => $is_new, |
|
}}); |
|
|
|
# Add the keys for looking it up by UUID or serial number. |
|
$anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string} = $scan_storcli_drive_group_uuid; |
|
$anvil->data->{'scan-storcli'}{drive_groups}{by_uuid}{$scan_storcli_drive_group_uuid} = $scan_storcli_virtual_drive_id_string; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::drive_groups::by_id_string::$scan_storcli_virtual_drive_id_string" => $anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string}, |
|
"scan-storcli::drive_groups::by_uuid::$scan_storcli_drive_group_uuid" => $anvil->data->{'scan-storcli'}{drive_groups}{by_uuid}{$scan_storcli_drive_group_uuid}, |
|
}}); |
|
} |
|
|
|
my $new_drive_group_access = ""; |
|
my $new_drive_group_array_size = ""; |
|
my $new_drive_group_array_state = ""; |
|
my $new_drive_group_cache = ""; |
|
my $new_drive_group_cachecade = ""; |
|
my $new_drive_group_consistent = ""; |
|
my $new_drive_group_disk_cache = ""; |
|
my $new_drive_group_raid_type = ""; |
|
my $new_drive_group_read_cache = ""; |
|
my $new_drive_group_scheduled_cc = ""; |
|
my $new_drive_group_write_cache = ""; |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::drive_group::${drive_group}::variable::${variable}" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
|
|
# Store and delete the value |
|
if ($variable eq "access") |
|
{ |
|
$new_drive_group_access = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_access => $new_drive_group_access }}); |
|
next; |
|
} |
|
if ($variable eq "array_size") |
|
{ |
|
$new_drive_group_array_size = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_array_size => $new_drive_group_array_size }}); |
|
next; |
|
} |
|
if ($variable eq "array_state") |
|
{ |
|
$new_drive_group_array_state = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_array_state => $new_drive_group_array_state }}); |
|
next; |
|
} |
|
if ($variable eq "cache") |
|
{ |
|
$new_drive_group_cache = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_cache => $new_drive_group_cache }}); |
|
next; |
|
} |
|
if ($variable eq "cachecade") |
|
{ |
|
$new_drive_group_cachecade = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_cachecade => $new_drive_group_cachecade }}); |
|
next; |
|
} |
|
if ($variable eq "consistent") |
|
{ |
|
$new_drive_group_consistent = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_consistent => $new_drive_group_consistent }}); |
|
next; |
|
} |
|
if ($variable eq "disk_cache") |
|
{ |
|
$new_drive_group_disk_cache = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_disk_cache => $new_drive_group_disk_cache }}); |
|
next; |
|
} |
|
if ($variable eq "raid_type") |
|
{ |
|
$new_drive_group_raid_type = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_raid_type => $new_drive_group_raid_type }}); |
|
next; |
|
} |
|
if ($variable eq "read_cache") |
|
{ |
|
$new_drive_group_read_cache = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_read_cache => $new_drive_group_read_cache }}); |
|
next; |
|
} |
|
if ($variable eq "scheduled_consistency_check") |
|
{ |
|
$new_drive_group_scheduled_cc = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_scheduled_cc => $new_drive_group_scheduled_cc }}); |
|
next; |
|
} |
|
if ($variable eq "write_cache") |
|
{ |
|
$new_drive_group_write_cache = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drive_group_write_cache => $new_drive_group_write_cache }}); |
|
next; |
|
} |
|
} |
|
|
|
# Pull out the rest of the variables now. If the Drive Group is new, all variables will be |
|
# INSERTed. If the Drive Group exists, each variable will be examined and new ones will be |
|
# INSERTed, existing ones will be checked for changes and UPDATEd as needed. If the Drive |
|
# Group is NOT new, then variables from the old data will be deleted as we go and any not |
|
# found in the current data set will be left over. We'll use this to determine variables that |
|
# have vanished. They will not be deleted, but their value will be set to 'VANISHED'. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { is_new => $is_new }}); |
|
if ($is_new) |
|
{ |
|
### NOTE: DG 9999 will be mostly blank and that is fine |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_drive_group_uuid => $scan_storcli_drive_group_uuid, |
|
controller_uuid => $controller_uuid, |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
new_drive_group_access => $new_drive_group_access, |
|
new_drive_group_array_size => $new_drive_group_array_size, |
|
new_drive_group_array_state => $new_drive_group_array_state, |
|
new_drive_group_cache => $new_drive_group_cache, |
|
new_drive_group_cachecade => $new_drive_group_cachecade, |
|
new_drive_group_consistent => $new_drive_group_consistent, |
|
new_drive_group_disk_cache => $new_drive_group_disk_cache, |
|
new_drive_group_raid_type => $new_drive_group_raid_type, |
|
new_drive_group_read_cache => $new_drive_group_read_cache, |
|
new_drive_group_scheduled_cc => $new_drive_group_scheduled_cc, |
|
new_drive_group_write_cache => $new_drive_group_write_cache, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
on_controller => $host_controller_serial_number, |
|
id_string => $scan_storcli_drive_group_id_string, |
|
access => $new_drive_group_access, |
|
array_size => $new_drive_group_array_size, |
|
array_state => $new_drive_group_array_state, |
|
cache => $new_drive_group_cache, |
|
cachecade => $new_drive_group_cachecade, |
|
consistent => $new_drive_group_consistent, |
|
disk_cache => $new_drive_group_disk_cache, |
|
raid_type => $new_drive_group_raid_type, |
|
read_cache => $new_drive_group_read_cache, |
|
scheduled_cc => $new_drive_group_scheduled_cc, |
|
write_cache => $new_drive_group_write_cache, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0005", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0005", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_drive_groups |
|
( |
|
scan_storcli_drive_group_uuid, |
|
scan_storcli_drive_group_host_uuid, |
|
scan_storcli_drive_group_virtual_drive_uuid, |
|
scan_storcli_drive_group_id_string, |
|
scan_storcli_drive_group_access, |
|
scan_storcli_drive_group_array_size, |
|
scan_storcli_drive_group_array_state, |
|
scan_storcli_drive_group_cache, |
|
scan_storcli_drive_group_cachecade, |
|
scan_storcli_drive_group_consistent, |
|
scan_storcli_drive_group_disk_cache, |
|
scan_storcli_drive_group_raid_type, |
|
scan_storcli_drive_group_read_cache, |
|
scan_storcli_drive_group_scheduled_cc, |
|
scan_storcli_drive_group_write_cache, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($scan_storcli_drive_group_uuid).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($scan_storcli_drive_group_virtual_drive_uuid).", |
|
".$anvil->Database->quote($scan_storcli_drive_group_id_string).", |
|
".$anvil->Database->quote($new_drive_group_access).", |
|
".$anvil->Database->quote($new_drive_group_array_size).", |
|
".$anvil->Database->quote($new_drive_group_array_state).", |
|
".$anvil->Database->quote($new_drive_group_cache).", |
|
".$anvil->Database->quote($new_drive_group_cachecade).", |
|
".$anvil->Database->quote($new_drive_group_consistent).", |
|
".$anvil->Database->quote($new_drive_group_disk_cache).", |
|
".$anvil->Database->quote($new_drive_group_raid_type).", |
|
".$anvil->Database->quote($new_drive_group_read_cache).", |
|
".$anvil->Database->quote($new_drive_group_scheduled_cc).", |
|
".$anvil->Database->quote($new_drive_group_write_cache).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
name => $variable, |
|
value => $value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0002", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0002", |
|
show_header => 0, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_drive_groups', |
|
".$anvil->Database->quote($scan_storcli_drive_group_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change (a changed SN/Drive Group should be |
|
### picked up as a new Drive Group), but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_drive_group_id_string = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_id_string}; |
|
my $old_drive_group_virtual_drive_uuid = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_virtual_drive_uuid}; |
|
my $old_drive_group_access = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_access}; |
|
my $old_drive_group_array_size = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_array_size}; |
|
my $old_drive_group_array_state = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_array_state}; |
|
my $old_drive_group_cache = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_cache}; |
|
my $old_drive_group_cachecade = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_cachecade}; |
|
my $old_drive_group_consistent = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_consistent}; |
|
my $old_drive_group_disk_cache = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_disk_cache}; |
|
my $old_drive_group_raid_type = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_raid_type}; |
|
my $old_drive_group_read_cache = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_read_cache}; |
|
my $old_drive_group_scheduled_cc = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_scheduled_cc}; |
|
my $old_drive_group_write_cache = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_write_cache}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
old_drive_group_id_string => $old_drive_group_id_string, |
|
scan_storcli_drive_group_virtual_drive_uuid => $scan_storcli_drive_group_virtual_drive_uuid, |
|
old_drive_group_virtual_drive_uuid => $old_drive_group_virtual_drive_uuid, |
|
new_drive_group_access => $new_drive_group_access, |
|
old_drive_group_access => $old_drive_group_access, |
|
new_drive_group_array_size => $new_drive_group_array_size, |
|
old_drive_group_array_size => $old_drive_group_array_size, |
|
new_drive_group_array_state => $new_drive_group_array_state, |
|
old_drive_group_array_state => $old_drive_group_array_state, |
|
new_drive_group_cache => $new_drive_group_cache, |
|
old_drive_group_cache => $old_drive_group_cache, |
|
new_drive_group_cachecade => $new_drive_group_cachecade, |
|
old_drive_group_cachecade => $old_drive_group_cachecade, |
|
new_drive_group_consistent => $new_drive_group_consistent, |
|
old_drive_group_consistent => $old_drive_group_consistent, |
|
new_drive_group_disk_cache => $new_drive_group_disk_cache, |
|
old_drive_group_disk_cache => $old_drive_group_disk_cache, |
|
new_drive_group_raid_type => $new_drive_group_raid_type, |
|
old_drive_group_raid_type => $old_drive_group_raid_type, |
|
new_drive_group_read_cache => $new_drive_group_read_cache, |
|
old_drive_group_read_cache => $old_drive_group_read_cache, |
|
new_drive_group_scheduled_cc => $new_drive_group_scheduled_cc, |
|
old_drive_group_scheduled_cc => $old_drive_group_scheduled_cc, |
|
new_drive_group_write_cache => $new_drive_group_write_cache, |
|
old_drive_group_write_cache => $old_drive_group_write_cache, |
|
}}); |
|
|
|
if (not defined $old_drive_group_virtual_drive_uuid) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0014", variables => { drive_group => $drive_group }}); |
|
$anvil->nice_exit({exit_code => 14}); |
|
} |
|
|
|
if (($scan_storcli_drive_group_id_string ne $old_drive_group_id_string) or |
|
($scan_storcli_drive_group_virtual_drive_uuid ne $old_drive_group_virtual_drive_uuid) or |
|
($new_drive_group_access ne $old_drive_group_access) or |
|
($new_drive_group_array_size ne $old_drive_group_array_size) or |
|
($new_drive_group_array_state ne $old_drive_group_array_state) or |
|
($new_drive_group_cache ne $old_drive_group_cache) or |
|
($new_drive_group_cachecade ne $old_drive_group_cachecade) or |
|
($new_drive_group_consistent ne $old_drive_group_consistent) or |
|
($new_drive_group_disk_cache ne $old_drive_group_disk_cache) or |
|
($new_drive_group_raid_type ne $old_drive_group_raid_type) or |
|
($new_drive_group_read_cache ne $old_drive_group_read_cache) or |
|
($new_drive_group_scheduled_cc ne $old_drive_group_scheduled_cc) or |
|
($new_drive_group_write_cache ne $old_drive_group_write_cache)) |
|
{ |
|
# Send a warning level alert because nothing should change here, ever. |
|
my $message_key = "scan_storcli_warning_0024"; |
|
if ($new_drive_group_access ne $old_drive_group_access) |
|
{ |
|
if ($new_drive_group_access eq "VANISHED") |
|
{ |
|
# Drive Group has returned. |
|
$message_key = "scan_storcli_warning_0025"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
} |
|
|
|
my $variables = { |
|
old_id_string => $old_drive_group_id_string, |
|
new_id_string => $scan_storcli_drive_group_id_string, |
|
new_access => $new_drive_group_access, |
|
old_access => $old_drive_group_access, |
|
new_array_size => $new_drive_group_array_size, |
|
old_array_size => $old_drive_group_array_size, |
|
new_array_state => $new_drive_group_array_state, |
|
old_array_state => $old_drive_group_array_state, |
|
new_cache => $new_drive_group_cache, |
|
old_cache => $old_drive_group_cache, |
|
new_cachecade => $new_drive_group_cachecade, |
|
old_cachecade => $old_drive_group_cachecade, |
|
new_consistent => $new_drive_group_consistent, |
|
old_consistent => $old_drive_group_consistent, |
|
new_disk_cache => $new_drive_group_disk_cache, |
|
old_disk_cache => $old_drive_group_disk_cache, |
|
new_raid_type => $new_drive_group_raid_type, |
|
old_raid_type => $old_drive_group_raid_type, |
|
new_read_cache => $new_drive_group_read_cache, |
|
old_read_cache => $old_drive_group_read_cache, |
|
new_scheduled_cc => $new_drive_group_scheduled_cc, |
|
old_scheduled_cc => $old_drive_group_scheduled_cc, |
|
new_write_cache => $new_drive_group_write_cache, |
|
old_write_cache => $old_drive_group_write_cache, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $message_key, |
|
show_header => 0, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
$main_table_changed = 1; |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_drive_groups |
|
SET |
|
scan_storcli_drive_group_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_virtual_drive_uuid).", |
|
scan_storcli_drive_group_id_string = ".$anvil->Database->quote($scan_storcli_drive_group_id_string).", |
|
scan_storcli_drive_group_access = ".$anvil->Database->quote($new_drive_group_access).", |
|
scan_storcli_drive_group_array_size = ".$anvil->Database->quote($new_drive_group_array_size).", |
|
scan_storcli_drive_group_array_state = ".$anvil->Database->quote($new_drive_group_array_state).", |
|
scan_storcli_drive_group_cache = ".$anvil->Database->quote($new_drive_group_cache).", |
|
scan_storcli_drive_group_cachecade = ".$anvil->Database->quote($new_drive_group_cachecade).", |
|
scan_storcli_drive_group_consistent = ".$anvil->Database->quote($new_drive_group_consistent).", |
|
scan_storcli_drive_group_disk_cache = ".$anvil->Database->quote($new_drive_group_disk_cache).", |
|
scan_storcli_drive_group_raid_type = ".$anvil->Database->quote($new_drive_group_raid_type).", |
|
scan_storcli_drive_group_read_cache = ".$anvil->Database->quote($new_drive_group_read_cache).", |
|
scan_storcli_drive_group_scheduled_cc = ".$anvil->Database->quote($new_drive_group_scheduled_cc).", |
|
scan_storcli_drive_group_write_cache = ".$anvil->Database->quote($new_drive_group_write_cache).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_drive_group_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{$type}}) |
|
{ |
|
my $new_variable_value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}; |
|
|
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
$anvil->data->{'scan-storcli'}{alert_sort}++; |
|
|
|
my $message_key = "scan_storcli_warning_0026"; |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0027"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
my $variables = { |
|
id_string => $scan_storcli_drive_group_id_string, |
|
name => $variable, |
|
old_value => $old_variable_value, |
|
new_value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => $message_key, |
|
show_header => $main_table_changed ? 0 : 1, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
id_string => $scan_storcli_drive_group_id_string, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0043", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0043", |
|
show_header => $main_table_changed ? 0 : 1, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_drive_groups', |
|
".$anvil->Database->quote($scan_storcli_drive_group_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and |
|
# delete) this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_drive_groups'}{source_uuid}{$scan_storcli_drive_group_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
id_string => $scan_storcli_drive_group_id_string, |
|
name => $variable, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0028", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0028", |
|
show_header => $main_table_changed ? 0 : 1, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now commit the changes. We do this here so that the VD is in place before processing drive |
|
# groups under it. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
# Delete the Drive Group from the last scan so that we can find controllers that have been removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::$scan_storcli_drive_group_uuid" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}, |
|
}}); |
|
delete $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}; |
|
} |
|
} |
|
|
|
### NOTE: We can't check for vanished drive groups here as we're called by each virtual drive. |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted virtual drives. |
|
sub process_virtual_drives |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# This method is a little different because as we process virtual drives, we will also process and |
|
# drive groups under them. |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
foreach my $scan_storcli_virtual_drive_id_string (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}}) |
|
{ |
|
# The identifying string '<host_controller_sn>-vd<x>' where 'x' is the virtual drive number. |
|
my $host_controller_serial_number = $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{on_controller}; |
|
my $controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}; |
|
my $virtual_drive = ($scan_storcli_virtual_drive_id_string =~ /-vd(\d+)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
host_controller_serial_number => $host_controller_serial_number, |
|
controller_uuid => $controller_uuid, |
|
virtual_drive => $virtual_drive, |
|
}}); |
|
|
|
# Make sure I have the host's serial number and UUID. |
|
if (not $host_controller_serial_number) |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0010", variables => { id_string => $scan_storcli_virtual_drive_id_string }}); |
|
$anvil->nice_exit({exit_code => 10}); |
|
} |
|
if (not $controller_uuid) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0008", variables => { serial_number => $host_controller_serial_number }}); |
|
$anvil->nice_exit({exit_code => 8}); |
|
} |
|
|
|
### NOTE: This is here purely for debugging. |
|
# Show the basic virtual drive data. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::${type}" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}, |
|
}}); |
|
next if not defined $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}; |
|
|
|
# Log the hash with a prefix |
|
$anvil->Log->variables({ |
|
source => $THIS_FILE, |
|
line => __LINE__, |
|
level => 2, |
|
prefix => "VD ".$virtual_drive." - ".$type, |
|
list => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}, |
|
}); |
|
} |
|
|
|
# Is this a new Virtual Drive? |
|
my $scan_storcli_virtual_drive_uuid = ""; |
|
my $is_new = 0; |
|
if (exists $anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string}) |
|
{ |
|
# Yes! |
|
$scan_storcli_virtual_drive_uuid = $anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_virtual_drive_uuid => $scan_storcli_virtual_drive_uuid }}); |
|
} |
|
else |
|
{ |
|
# No, this is a new Virtual Drive. Create a new UUID for it. |
|
$scan_storcli_virtual_drive_uuid = $anvil->Get->uuid(); |
|
$is_new = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_uuid => $scan_storcli_virtual_drive_uuid, |
|
is_new => $is_new, |
|
}}); |
|
|
|
# Add the keys for looking it up by UUID or serial number. |
|
$anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string} = $scan_storcli_virtual_drive_uuid; |
|
$anvil->data->{'scan-storcli'}{virtual_drives}{by_uuid}{$scan_storcli_virtual_drive_uuid} = $scan_storcli_virtual_drive_id_string; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::virtual_drives::by_id_string::$scan_storcli_virtual_drive_id_string" => $anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string}, |
|
"scan-storcli::virtual_drives::by_uuid::$scan_storcli_virtual_drive_uuid" => $anvil->data->{'scan-storcli'}{virtual_drives}{by_uuid}{$scan_storcli_virtual_drive_uuid}, |
|
}}); |
|
} |
|
|
|
### These are the values for the main table. Anything else will go in the variables table. |
|
# Creation date is a combination of two variables. |
|
my $creation_date = ""; |
|
my $creation_time = ""; |
|
my $new_creation_date = ""; |
|
my $new_data_protection = ""; |
|
my $new_disk_cache_policy = ""; |
|
my $new_emulation_type = ""; |
|
my $new_encryption = ""; |
|
my $new_blocks = ""; |
|
my $new_strip_size = ""; |
|
my $new_drives_per_span = ""; |
|
my $new_span_depth = ""; |
|
my $new_scsi_naa_id = ""; |
|
if ($virtual_drive eq "9999") |
|
{ |
|
# This is the fake VD |
|
$creation_date = "2020/01/01"; |
|
$creation_time = "00:00:00"; |
|
$new_creation_date = "2020/01/01 00:00:00"; |
|
$new_data_protection = "na"; |
|
$new_disk_cache_policy = "na"; |
|
$new_emulation_type = "na"; |
|
$new_encryption = "na"; |
|
$new_blocks = 0; |
|
$new_strip_size = 0; |
|
$new_drives_per_span = 0; |
|
$new_span_depth = 0; |
|
$new_scsi_naa_id = "placeholder"; |
|
} |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::variable::${variable}" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}, |
|
}}); |
|
|
|
# Store and delete the value |
|
if ($variable eq "creation_date") |
|
{ |
|
# The creation date we store is a combination of two variables. That's why |
|
# these first two entries are a little odd. |
|
$creation_date = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
creation_date => $creation_date, |
|
creation_time => $creation_time, |
|
}}); |
|
|
|
# If I have the time, assemble. |
|
if ($creation_time) |
|
{ |
|
$new_creation_date = $creation_date." ".$creation_time; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_creation_date => $new_creation_date }}); |
|
} |
|
next; |
|
} |
|
if ($variable eq "creation_time") |
|
{ |
|
$creation_time = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
creation_date => $creation_date, |
|
creation_time => $creation_time, |
|
}}); |
|
|
|
# If I have the date, assemble. |
|
if ($creation_date) |
|
{ |
|
$new_creation_date = $creation_date." ".$creation_time; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_creation_date => $new_creation_date }}); |
|
} |
|
next; |
|
} |
|
# Back to our regularly scheduled programming... |
|
if ($variable eq "data_protection") |
|
{ |
|
$new_data_protection = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_data_protection => $new_data_protection }}); |
|
next; |
|
} |
|
if ($variable eq "disk_cache_policy") |
|
{ |
|
$new_disk_cache_policy = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_disk_cache_policy => $new_disk_cache_policy }}); |
|
next; |
|
} |
|
if ($variable eq "emulation_type") |
|
{ |
|
$new_emulation_type = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_emulation_type => $new_emulation_type }}); |
|
next; |
|
} |
|
if ($variable eq "encryption") |
|
{ |
|
$new_encryption = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_encryption => $new_encryption }}); |
|
next; |
|
} |
|
if ($variable eq "number_of_blocks") |
|
{ |
|
$new_blocks = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_blocks => $new_blocks }}); |
|
next; |
|
} |
|
if ($variable eq "strip_size") |
|
{ |
|
$new_strip_size = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_strip_size => $new_strip_size }}); |
|
next; |
|
} |
|
if ($variable eq "number_of_drives_per_span") |
|
{ |
|
$new_drives_per_span = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_drives_per_span => $new_drives_per_span }}); |
|
next; |
|
} |
|
if ($variable eq "span_depth") |
|
{ |
|
$new_span_depth = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_span_depth => $new_span_depth }}); |
|
next; |
|
} |
|
if ($variable eq "scsi_naa_id") |
|
{ |
|
$new_scsi_naa_id = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_scsi_naa_id => $new_scsi_naa_id }}); |
|
next; |
|
} |
|
} |
|
|
|
# Pull out the rest of the variables now. If the Virtual Drive is new, all variables will be |
|
# INSERTed. If the Virtual Drive exists, each variable will be examined and new ones will be |
|
# INSERTed, existing ones will be checked for changes and UPDATEd as needed. If the |
|
# Virtual Drive is NOT new, then variables from the old data will be deleted as we go and any |
|
# not found in the current data set will be left over. We'll use this to determine variables |
|
# that have vanished. They will not be deleted, but their value will be set to 'VANISHED'. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { is_new => $is_new }}); |
|
if ($is_new) |
|
{ |
|
### NOTE: VD 9999 will be mostly blank and that is fine |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_uuid => $scan_storcli_virtual_drive_uuid, |
|
controller_uuid => $controller_uuid, |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
new_creation_date => $new_creation_date, |
|
new_data_protection => $new_data_protection, |
|
new_disk_cache_policy => $new_disk_cache_policy, |
|
new_emulation_type => $new_emulation_type, |
|
new_encryption => $new_encryption, |
|
new_blocks => $new_blocks, |
|
new_strip_size => $new_strip_size, |
|
new_drives_per_span => $new_drives_per_span, |
|
new_span_depth => $new_span_depth, |
|
new_scsi_naa_id => $new_scsi_naa_id, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
my $variables = { |
|
on_controller => $host_controller_serial_number, |
|
id_string => $scan_storcli_virtual_drive_id_string, |
|
creation_date => $new_creation_date, |
|
data_protection => $new_data_protection, |
|
disk_cache_policy => $new_disk_cache_policy, |
|
emulation_type => $new_emulation_type, |
|
encryption => $new_encryption, |
|
blocks => $new_blocks, |
|
strip_size => $new_strip_size, |
|
drives_per_span => $new_drives_per_span, |
|
span_depth => $new_span_depth, |
|
scsi_naa_id => $new_scsi_naa_id, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0004", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0004", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_virtual_drives |
|
( |
|
scan_storcli_virtual_drive_uuid, |
|
scan_storcli_virtual_drive_host_uuid, |
|
scan_storcli_virtual_drive_controller_uuid, |
|
scan_storcli_virtual_drive_id_string, |
|
scan_storcli_virtual_drive_creation_date, |
|
scan_storcli_virtual_drive_data_protection, |
|
scan_storcli_virtual_drive_disk_cache_policy, |
|
scan_storcli_virtual_drive_emulation_type, |
|
scan_storcli_virtual_drive_encryption, |
|
scan_storcli_virtual_drive_blocks, |
|
scan_storcli_virtual_drive_strip_size, |
|
scan_storcli_virtual_drive_drives_per_span, |
|
scan_storcli_virtual_drive_span_depth, |
|
scan_storcli_virtual_drive_scsi_naa_id, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($scan_storcli_virtual_drive_id_string).", |
|
".$anvil->Database->quote($new_creation_date).", |
|
".$anvil->Database->quote($new_data_protection).", |
|
".$anvil->Database->quote($new_disk_cache_policy).", |
|
".$anvil->Database->quote($new_emulation_type).", |
|
".$anvil->Database->quote($new_encryption).", |
|
".$anvil->Database->quote($new_blocks).", |
|
".$anvil->Database->quote($new_strip_size).", |
|
".$anvil->Database->quote($new_drives_per_span).", |
|
".$anvil->Database->quote($new_span_depth).", |
|
".$anvil->Database->quote($new_scsi_naa_id).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
name => $variable, |
|
value => $value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0004", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
show_header => 0, |
|
message => "scan_storcli_note_0002", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_virtual_drives', |
|
".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change (a changed SN/Virtual Drive should be |
|
### picked up as a new Virtual Drive), but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_scan_storcli_virtual_drive_id_string = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_id_string}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_controller_uuid}; |
|
my $old_creation_date = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_creation_date}; |
|
my $old_data_protection = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_data_protection}; |
|
my $old_disk_cache_policy = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_disk_cache_policy}; |
|
my $old_emulation_type = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_emulation_type}; |
|
my $old_encryption = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_encryption}; |
|
my $old_blocks = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_blocks}; |
|
my $old_strip_size = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_strip_size}; |
|
my $old_drives_per_span = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_drives_per_span}; |
|
my $old_span_depth = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_span_depth}; |
|
my $old_scsi_naa_id = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_scsi_naa_id}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
old_scan_storcli_virtual_drive_id_string => $old_scan_storcli_virtual_drive_id_string, |
|
controller_uuid => $controller_uuid, |
|
old_controller_uuid => $old_controller_uuid, |
|
new_creation_date => $new_creation_date, |
|
old_creation_date => $old_creation_date, |
|
new_data_protection => $new_data_protection, |
|
old_data_protection => $old_data_protection, |
|
new_disk_cache_policy => $new_disk_cache_policy, |
|
old_disk_cache_policy => $old_disk_cache_policy, |
|
new_emulation_type => $new_emulation_type, |
|
old_emulation_type => $old_emulation_type, |
|
new_encryption => $new_encryption, |
|
old_encryption => $old_encryption, |
|
new_blocks => $new_blocks, |
|
old_blocks => $old_blocks, |
|
new_strip_size => $new_strip_size, |
|
old_strip_size => $old_strip_size, |
|
new_drives_per_span => $new_drives_per_span, |
|
old_drives_per_span => $old_drives_per_span, |
|
new_span_depth => $new_span_depth, |
|
old_span_depth => $old_span_depth, |
|
new_scsi_naa_id => $new_scsi_naa_id, |
|
old_scsi_naa_id => $old_scsi_naa_id, |
|
}}); |
|
|
|
if (($scan_storcli_virtual_drive_id_string ne $old_scan_storcli_virtual_drive_id_string) or |
|
($controller_uuid ne $old_controller_uuid) or |
|
($new_creation_date ne $old_creation_date) or |
|
($new_data_protection ne $old_data_protection) or |
|
($new_disk_cache_policy ne $old_disk_cache_policy) or |
|
($new_emulation_type ne $old_emulation_type) or |
|
($new_encryption ne $old_encryption) or |
|
($new_blocks ne $old_blocks) or |
|
($new_strip_size ne $old_strip_size) or |
|
($new_drives_per_span ne $old_drives_per_span) or |
|
($new_span_depth ne $old_span_depth) or |
|
($new_scsi_naa_id ne $old_scsi_naa_id)) |
|
{ |
|
# I need the serial numbers for the controller UUIDs. |
|
my $new_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_controller_serial_number => $new_controller_serial_number, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Send a warning level alert because nothing should change here, ever. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0017"; |
|
if ($new_creation_date ne $old_creation_date) |
|
{ |
|
if ($old_creation_date eq "VANISHED") |
|
{ |
|
# Virtual Drive has returned. |
|
$cleared = 1; |
|
$message_key = "scan_storcli_warning_0018"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
|
|
my $variables = { |
|
old_on_controller => $old_controller_serial_number, |
|
new_on_controller => $new_controller_serial_number, |
|
old_id_string => $old_scan_storcli_virtual_drive_id_string, |
|
new_id_string => $scan_storcli_virtual_drive_id_string, |
|
old_creation_date => $old_creation_date, |
|
new_creation_date => $new_creation_date, |
|
old_data_protection => $old_data_protection, |
|
new_data_protection => $new_data_protection, |
|
old_disk_cache_policy => $old_disk_cache_policy, |
|
new_disk_cache_policy => $new_disk_cache_policy, |
|
old_emulation_type => $old_emulation_type, |
|
new_emulation_type => $new_emulation_type, |
|
old_encryption => $old_encryption, |
|
new_encryption => $new_encryption, |
|
old_blocks => $old_blocks, |
|
new_blocks => $new_blocks, |
|
old_strip_size => $old_strip_size, |
|
new_strip_size => $new_strip_size, |
|
old_drives_per_span => $old_drives_per_span, |
|
new_drives_per_span => $new_drives_per_span, |
|
old_span_depth => $old_span_depth, |
|
new_span_depth => $new_span_depth, |
|
old_scsi_naa_id => $old_scsi_naa_id, |
|
new_scsi_naa_id => $new_scsi_naa_id, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => $cleared, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
$main_table_changed = 1; |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_virtual_drives |
|
SET |
|
scan_storcli_virtual_drive_controller_uuid = ".$anvil->Database->quote($controller_uuid).", |
|
scan_storcli_virtual_drive_id_string = ".$anvil->Database->quote($scan_storcli_virtual_drive_id_string).", |
|
scan_storcli_virtual_drive_creation_date = ".$anvil->Database->quote($new_creation_date).", |
|
scan_storcli_virtual_drive_data_protection = ".$anvil->Database->quote($new_data_protection).", |
|
scan_storcli_virtual_drive_disk_cache_policy = ".$anvil->Database->quote($new_disk_cache_policy).", |
|
scan_storcli_virtual_drive_emulation_type = ".$anvil->Database->quote($new_emulation_type).", |
|
scan_storcli_virtual_drive_encryption = ".$anvil->Database->quote($new_encryption).", |
|
scan_storcli_virtual_drive_blocks = ".$anvil->Database->quote($new_blocks).", |
|
scan_storcli_virtual_drive_strip_size = ".$anvil->Database->quote($new_strip_size).", |
|
scan_storcli_virtual_drive_drives_per_span = ".$anvil->Database->quote($new_drives_per_span).", |
|
scan_storcli_virtual_drive_span_depth = ".$anvil->Database->quote($new_span_depth).", |
|
scan_storcli_virtual_drive_scsi_naa_id = ".$anvil->Database->quote($new_scsi_naa_id).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}}) |
|
{ |
|
my $new_variable_value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}; |
|
|
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
$anvil->data->{'scan-storcli'}{alert_sort}++; |
|
|
|
my $cleared = 0; |
|
my $level = "warning"; |
|
my $message_key = "scan_storcli_warning_0019"; |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0020"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
|
|
# If the 'name' is 'active operations' and the new is |
|
# 'Background Initialization', we're in the middle of |
|
# a BGI and this is not a warning. If the new is |
|
# 'None', the CGI completed. |
|
if ($variable =~ /Active Operations/i) |
|
{ |
|
$level = "notice"; |
|
if ($new_variable_value =~ /None/i) |
|
{ |
|
# BGI done! |
|
$message_key = "scan_storcli_note_0069"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
else |
|
{ |
|
# BGI in progress still, pull out the |
|
# percentage. |
|
my $percentage = ($new_variable_value =~ /\(\d+%\)/)[0]; |
|
if ($percentage) |
|
{ |
|
# Successfully pulled the new |
|
# percentage complete value. |
|
$new_variable_value = $percentage; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_variable_value => $new_variable_value }}); |
|
} |
|
$message_key = "scan_storcli_note_0068"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
} |
|
|
|
my $variables = { |
|
id_string => $scan_storcli_virtual_drive_id_string, |
|
name => $variable, |
|
old_value => $old_variable_value, |
|
new_value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $level, |
|
clear_alert => $cleared, |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
id_string => $scan_storcli_virtual_drive_id_string, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0022", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => 0, |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => "scan_storcli_warning_0022", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_virtual_drives', |
|
".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and |
|
# delete) this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_virtual_drives'}{source_uuid}{$scan_storcli_virtual_drive_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
id_string => $scan_storcli_virtual_drive_id_string, |
|
name => $variable, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0021", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => 0, |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => "scan_storcli_warning_0021", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now commit the changes. We do this here so that the VD is in place before processing drive |
|
# groups under it. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
# Process drive groups under this virtual drive. They'll likely have vanished, too. |
|
process_drive_groups($anvil, $scan_storcli_virtual_drive_id_string, $scan_storcli_virtual_drive_uuid, $controller_uuid, $host_controller_serial_number); |
|
|
|
# Delete the Virtual Drive from the last scan so that we can find controllers that have been removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}) |
|
{ |
|
delete $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}; |
|
} |
|
} |
|
|
|
# See if any Virtual Drives have vanished. |
|
foreach my $scan_storcli_virtual_drive_uuid (keys %{$anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}}) |
|
{ |
|
# Virtual Drive vanished! |
|
my $scan_storcli_virtual_drive_id_string = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_id_string}; |
|
my $controller_uuid = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_controller_uuid}; |
|
my $creation_date = $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_creation_date}; |
|
my $host_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
controller_uuid => $controller_uuid, |
|
creation_date => $creation_date, |
|
host_controller_serial_number => $host_controller_serial_number, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}; |
|
|
|
# If the old creation date is already 'VANISHED', ignore it. |
|
next if $creation_date eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
id_string => $scan_storcli_virtual_drive_id_string, |
|
controller_serial_number => $host_controller_serial_number, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0023", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => 0, |
|
show_header => 1, |
|
message => "scan_storcli_warning_0023", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_virtual_drives |
|
SET |
|
scan_storcli_virtual_drive_creation_date = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Now commit the changes. We do this here so that the VD is in place before processing drive |
|
# groups under it. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
# Process drive groups under this virtual drive. They'll likely have vanished, too. |
|
process_drive_groups($anvil, $scan_storcli_virtual_drive_id_string, $scan_storcli_virtual_drive_uuid, $controller_uuid, $host_controller_serial_number); |
|
} |
|
|
|
### Now that we've processed virtual drives, see if in stray drive groups are left. |
|
foreach my $scan_storcli_drive_group_uuid (keys %{$anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}}) |
|
{ |
|
# Drive Group vanished! |
|
my $scan_storcli_drive_group_id_string = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_id_string}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan_storcli_drive_group_id_string" => $scan_storcli_drive_group_id_string, |
|
}}); |
|
|
|
# If this drive group is '9999', we won't care if it vanishes because it was a pseudo DG |
|
# anyway. |
|
next if $scan_storcli_drive_group_id_string =~ /-dg9999$/; |
|
|
|
# Still here? Gather the rest of the data. |
|
my $controller_uuid = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { controller_uuid => $controller_uuid }}); |
|
|
|
# If I don't have the controller ID, see if I can parse it from the |
|
if ((not $controller_uuid) && ($scan_storcli_drive_group_id_string =~ /^(.*?)-vd/)) |
|
{ |
|
my $serial_number = $1; |
|
$controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number} ? $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number} : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
serial_number => $serial_number, |
|
controller_uuid => $controller_uuid, |
|
}}); |
|
} |
|
|
|
# If I still don't have a controller UUID, then something serious went wrong. |
|
if (not $controller_uuid) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0015", variables => { drive_group_uuid => $scan_storcli_drive_group_uuid }}); |
|
$anvil->nice_exit({exit_code => 15}); |
|
} |
|
|
|
my $access = $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_access}; |
|
my $host_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
access => $access, |
|
host_controller_serial_number => $host_controller_serial_number, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}; |
|
|
|
# If the old creation date is already 'VANISHED', ignore it. |
|
next if $access eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
id_string => $scan_storcli_drive_group_id_string, |
|
controller_serial_number => $host_controller_serial_number, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0028", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => 0, |
|
show_header => 1, |
|
message => "scan_storcli_warning_0028", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_drive_groups |
|
SET |
|
scan_storcli_drive_group_access = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_drive_group_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Now commit the changes. We do this here so that the VD is in place before processing drive |
|
# groups under it. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted physical drives. |
|
sub process_physical_disks |
|
{ |
|
my ($anvil) = @_; |
|
|
|
foreach my $scan_storcli_virtual_drive_id_string (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}}) |
|
{ |
|
my $virtual_drive = ($scan_storcli_virtual_drive_id_string =~ /-vd(\d+)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
virtual_drive => $virtual_drive, |
|
}}); |
|
|
|
foreach my $drive_group (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drive_group => $drive_group }}); |
|
|
|
foreach my $enclosure_id (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { enclosure_id => $enclosure_id }}); |
|
|
|
foreach my $slot_number (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { slot_number => $slot_number }}); |
|
|
|
# This function is really just to help keep code clean and avoid massive indenting. |
|
process_a_physical_disk($anvil, $scan_storcli_virtual_drive_id_string, $drive_group, $enclosure_id, $slot_number); |
|
} |
|
} |
|
} |
|
} |
|
|
|
# See if any Physical Disks have vanished. |
|
foreach my $scan_storcli_physical_drive_uuid (keys %{$anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}}) |
|
{ |
|
# Physical Disk vanished! |
|
my $old_physical_disk_serial_number = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_serial_number}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_controller_uuid}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_model}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_physical_disk_serial_number => $old_physical_disk_serial_number, |
|
old_controller_uuid => $old_controller_uuid, |
|
old_model => $old_model, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}; |
|
|
|
# If the old alarm state is already 'VANISHED', ignore it. |
|
next if $old_model eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
physical_disk_serial_number => $old_physical_disk_serial_number, |
|
controller_serial_number => $old_controller_serial_number, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_warning_0035", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
show_header => 1, |
|
message => "scan_storcli_warning_0035", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_physical_drives |
|
SET |
|
scan_storcli_physical_drive_model = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_physical_drive_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
# Now commit the changes. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
### NOTE: I don't loop by drive serial number, like in the other process_X() functions, so this one is |
|
### designed a little different. |
|
# This does the work of processing a specific physical disk. |
|
sub process_a_physical_disk |
|
{ |
|
my ($anvil, $scan_storcli_virtual_drive_id_string, $drive_group, $enclosure_id, $slot_number) = @_; |
|
|
|
my ($vd_controller_serial_number, $virtual_drive) = ($scan_storcli_virtual_drive_id_string =~ /^(.*?)-vd(\d+)$/); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
vd_controller_serial_number => $vd_controller_serial_number, |
|
virtual_drive => $virtual_drive, |
|
}}); |
|
|
|
# I need the drive's serial number right off the bat. |
|
# = virtual_drive::0000000051622771-vd0 ::drive_group::0:: enclosure_id::7:: slot_number::1:: variable::serial_number: [S7M1RD440000E722PB9N] |
|
my $scan_storcli_physical_drive_serial_number = $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_physical_drive_serial_number => $scan_storcli_physical_drive_serial_number }}); |
|
if ($scan_storcli_physical_drive_serial_number) |
|
{ |
|
# Got it, delete it now. |
|
delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{serial_number}; |
|
} |
|
else |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0013", variables => { |
|
virtual_drive => $scan_storcli_virtual_drive_id_string, |
|
drive_group => $drive_group, |
|
enclosure_id => $enclosure_id, |
|
slot_number => $slot_number, |
|
}}); |
|
$anvil->nice_exit({exit_code => 13}); |
|
} |
|
|
|
# Make sure I have a controller serial number. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::on_controller" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller}, |
|
}}); |
|
if (not $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller}) |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0012", variables => { serial_number => $scan_storcli_physical_drive_serial_number }}); |
|
$anvil->nice_exit({exit_code => 12}); |
|
} |
|
|
|
my $host_controller_serial_number = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_controller_serial_number => $host_controller_serial_number }}); |
|
|
|
# Now make sure I can translate this to a UUID. |
|
if (not $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0008", variables => { serial_number => $host_controller_serial_number }}); |
|
$anvil->nice_exit({exit_code => 8}); |
|
} |
|
my $controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { controller_uuid => $controller_uuid }}); |
|
|
|
# Not gather the rest of the core table's values. |
|
my $new_size = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size}; |
|
my $new_sector_size = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sector_size}; |
|
my $new_vendor = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{manufacturer_identification}; |
|
my $new_model = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_model}; |
|
my $new_self_encrypting_drive = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{self_encrypting_drive}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_size => $new_size, |
|
new_sector_size => $new_sector_size, |
|
new_vendor => $new_vendor, |
|
new_model => $new_model, |
|
new_self_encrypting_drive => $new_self_encrypting_drive, |
|
}}); |
|
|
|
# Get the temperature ranges, which depends on whether this is an SSD or HDD. |
|
my $drive_temperature_key = "hdd"; |
|
my $drive_media = $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_media}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drive_media => $drive_media }}); |
|
|
|
if (lc($drive_media) eq "ssd") |
|
{ |
|
$drive_temperature_key = "ssd"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drive_temperature_key => $drive_temperature_key }}); |
|
} |
|
|
|
# Setup our thermal thresholds |
|
my $high_critical = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{high_critical}; |
|
my $high_warning = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{high_warning}; |
|
my $low_warning = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{low_warning}; |
|
my $low_critical = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{low_critical}; |
|
my $jump = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{jump}; |
|
my $buffer = $anvil->data->{'scan-storcli'}{thresholds}{drives}{$drive_temperature_key}{buffer}; |
|
my $clear_high_critical = $high_critical - $buffer; |
|
my $clear_high_warning = $high_warning - $buffer; |
|
my $clear_low_critical = $low_critical - $buffer; |
|
my $clear_low_warning = $low_warning - $buffer; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
high_critical => $high_critical, |
|
high_warning => $high_warning, |
|
low_warning => $low_warning, |
|
low_critical => $low_critical, |
|
jump => $jump, |
|
buffer => $buffer, |
|
clear_high_critical => $clear_high_critical, |
|
clear_high_warning => $clear_high_warning, |
|
clear_low_critical => $clear_low_critical, |
|
clear_low_warning => $clear_low_warning, |
|
}}); |
|
|
|
# Fine-tune the alert thresholds |
|
if ($clear_high_critical < $high_warning) |
|
{ |
|
$clear_high_critical = $high_warning + 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_high_critical => $clear_high_critical }}); |
|
} |
|
if ($clear_low_critical > $low_warning) |
|
{ |
|
$clear_low_critical = $low_warning - 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_low_critical => $clear_low_critical }}); |
|
} |
|
|
|
# Is this a new physical disk? |
|
my $is_new = 0; |
|
my $scan_storcli_physical_drive_uuid = ""; |
|
if (exists $anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number}) |
|
{ |
|
# Yup! |
|
$scan_storcli_physical_drive_uuid = $anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_physical_drive_uuid => $scan_storcli_physical_drive_uuid }}); |
|
} |
|
else |
|
{ |
|
$is_new = 1; |
|
$scan_storcli_physical_drive_uuid = $anvil->Get->uuid(); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
is_new => $is_new, |
|
scan_storcli_physical_drive_uuid => $scan_storcli_physical_drive_uuid, |
|
}}); |
|
|
|
$anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number} = $scan_storcli_physical_drive_uuid; |
|
$anvil->data->{'scan-storcli'}{physical_drives}{by_uuid}{$scan_storcli_physical_drive_uuid} = $scan_storcli_physical_drive_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::physical_drives::by_serial::$scan_storcli_physical_drive_serial_number" => $anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number}, |
|
"scan-storcli::physical_drives::by_uuid::$scan_storcli_physical_drive_uuid" => $anvil->data->{'scan-storcli'}{physical_drives}{by_uuid}{$scan_storcli_physical_drive_uuid}, |
|
}}); |
|
} |
|
|
|
# Pull out the rest of the variables now. If the physical disk is new, all variables will be |
|
# INSERTed. If the physical drive exists, each variable will be examined and new ones will be |
|
# INSERTed, existing ones will be checked for changes and UPDATEd as needed. If the physical disk is |
|
# NOT new, then variables from the old data will be deleted as we go and any not found in the current |
|
# data set will be left over. We'll use this to determine variables that have vanished. They will not |
|
# be deleted, but their value will be set to 'VANISHED'. |
|
if ($is_new) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_physical_drive_serial_number => $scan_storcli_physical_drive_serial_number, |
|
scan_storcli_physical_drive_uuid => $scan_storcli_physical_drive_uuid, |
|
host_controller_serial_number => $host_controller_serial_number, |
|
virtual_drive => $virtual_drive, |
|
drive_group => $drive_group, |
|
controller_uuid => $controller_uuid, |
|
new_size => $new_size, |
|
new_sector_size => $new_sector_size, |
|
new_vendor => $new_vendor, |
|
new_model => $new_model, |
|
new_self_encrypting_drive => $new_self_encrypting_drive, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
on_controller => $host_controller_serial_number, |
|
virtual_drive => $virtual_drive, |
|
drive_group => $drive_group, |
|
serial_number => $scan_storcli_physical_drive_serial_number, |
|
size => $new_size, |
|
sector_size => $new_sector_size, |
|
vendor => $new_vendor, |
|
model => $new_model, |
|
self_encrypting_drive => $new_self_encrypting_drive, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0006", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
show_header => 1, |
|
message => "scan_storcli_note_0006", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_physical_drives |
|
( |
|
scan_storcli_physical_drive_uuid, |
|
scan_storcli_physical_drive_host_uuid, |
|
scan_storcli_physical_drive_controller_uuid, |
|
scan_storcli_physical_drive_virtual_drive, |
|
scan_storcli_physical_drive_drive_group, |
|
scan_storcli_physical_drive_enclosure_id, |
|
scan_storcli_physical_drive_slot_number, |
|
scan_storcli_physical_drive_serial_number, |
|
scan_storcli_physical_drive_size, |
|
scan_storcli_physical_drive_sector_size, |
|
scan_storcli_physical_drive_vendor, |
|
scan_storcli_physical_drive_model, |
|
scan_storcli_physical_drive_self_encrypting_drive, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($scan_storcli_physical_drive_uuid).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($virtual_drive).", |
|
".$anvil->Database->quote($drive_group).", |
|
".$anvil->Database->quote($enclosure_id).", |
|
".$anvil->Database->quote($slot_number).", |
|
".$anvil->Database->quote($scan_storcli_physical_drive_serial_number).", |
|
".$anvil->Database->quote($new_size).", |
|
".$anvil->Database->quote($new_sector_size).", |
|
".$anvil->Database->quote($new_vendor).", |
|
".$anvil->Database->quote($new_model).", |
|
".$anvil->Database->quote($new_self_encrypting_drive).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
# If this is a thermal sensor, we need to see if it is OK or not. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_note_0002"; |
|
my $alert_level = "notice"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# This is a temperature, so see if the temperature outside of the |
|
# warning or critical thresholds. This is a new sensor, so nothing |
|
# to compare against. |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($value > $high_critical) |
|
{ |
|
# Crossed the critical threshold. This should |
|
# always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0012"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value > $high_warning) |
|
{ |
|
# Crossed the warning threshold. This should always be unset |
|
# because it is a new variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0013"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_critical) |
|
{ |
|
# Dropped below the critical threshold. This should always be |
|
# unset because it is a new variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0014"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_warning) |
|
{ |
|
# Crossed the warning threshold. This should always be unset |
|
# because it is a new variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0015"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
|
|
# Record this for later processing into the 'temperature' table. |
|
my $sensor_host_key = "pd:".$scan_storcli_physical_drive_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Send an alert telling the user that we've found a new physical drive sensor. |
|
my $variables = { |
|
serial_number => $scan_storcli_physical_drive_serial_number, |
|
name => $variable, |
|
value => $value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
}; |
|
my $log_level = $alert_level eq "notice" ? 3 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
show_header => 0, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_physical_drives', |
|
".$anvil->Database->quote($scan_storcli_physical_drive_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change, but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_controller_uuid}; |
|
my $old_virtual_drive = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_virtual_drive}; |
|
my $old_drive_group = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_drive_group}; |
|
my $old_enclosure_id = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_enclosure_id}; |
|
my $old_slot_number = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_slot_number}; |
|
my $old_physical_drive_serial_number = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_serial_number}; |
|
my $old_size = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_size}; |
|
my $old_sector_size = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_sector_size}; |
|
my $old_vendor = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_vendor}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_model}; |
|
my $old_self_encrypting_drive = $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_self_encrypting_drive}; |
|
$old_controller_uuid = "" if not defined $old_controller_uuid; |
|
$old_physical_drive_serial_number = "" if not defined $old_physical_drive_serial_number; |
|
$old_model = "" if not defined $old_model; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_physical_drive_serial_number => $scan_storcli_physical_drive_serial_number, |
|
old_physical_drive_serial_number => $old_physical_drive_serial_number, |
|
controller_uuid => $controller_uuid, |
|
old_controller_uuid => $old_controller_uuid, |
|
virtual_drive => $virtual_drive, |
|
old_virtual_drive => $old_virtual_drive, |
|
drive_group => $drive_group, |
|
old_drive_group => $old_drive_group, |
|
enclosure_id => $enclosure_id, |
|
old_enclosure_id => $old_enclosure_id, |
|
slot_number => $slot_number, |
|
old_slot_number => $old_slot_number, |
|
new_size => $new_size, |
|
old_size => $old_size, |
|
new_sector_size => $new_sector_size, |
|
old_sector_size => $old_sector_size, |
|
new_vendor => $new_vendor, |
|
old_vendor => $old_vendor, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_self_encrypting_drive => $new_self_encrypting_drive, |
|
old_self_encrypting_drive => $old_self_encrypting_drive, |
|
}}); |
|
|
|
if (($scan_storcli_physical_drive_serial_number ne $old_physical_drive_serial_number) or |
|
($controller_uuid ne $old_controller_uuid) or |
|
($virtual_drive ne $old_virtual_drive) or |
|
($drive_group ne $old_drive_group) or |
|
($enclosure_id ne $old_enclosure_id) or |
|
($slot_number ne $old_slot_number) or |
|
($new_size ne $old_size) or |
|
($new_sector_size ne $old_sector_size) or |
|
($new_vendor ne $old_vendor) or |
|
($new_model ne $old_model) or |
|
($new_self_encrypting_drive ne $old_self_encrypting_drive)) |
|
{ |
|
# I'll need the old controller's serial number. |
|
my $old_host_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_host_controller_serial_number => $old_host_controller_serial_number }}); |
|
|
|
# Send a warning level alert because these really should never change. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0029"; |
|
if ($new_model ne $old_model) |
|
{ |
|
if ($old_model eq "VANISHED") |
|
{ |
|
# Physical drive has returned. |
|
$message_key = "scan_storcli_warning_0030"; |
|
} |
|
} |
|
my $variables = { |
|
new_on_controller => $host_controller_serial_number, |
|
old_on_controller => $old_host_controller_serial_number, |
|
new_virtual_drive => $virtual_drive, |
|
old_virtual_drive => $old_virtual_drive, |
|
new_drive_group => $drive_group, |
|
old_drive_group => $old_drive_group, |
|
new_enclosure_id => $enclosure_id, |
|
old_enclosure_id => $old_enclosure_id, |
|
new_slot_number => $slot_number, |
|
old_slot_number => $old_slot_number, |
|
new_serial_number => $scan_storcli_physical_drive_serial_number, |
|
old_serial_number => $old_physical_drive_serial_number, |
|
new_vendor => $new_vendor, |
|
old_vendor => $old_vendor, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_size => $new_size, |
|
old_size => $old_size, |
|
new_sector_size => $new_sector_size, |
|
old_sector_size => $old_sector_size, |
|
new_self_encrypting_drive => $new_self_encrypting_drive, |
|
old_self_encrypting_drive => $old_self_encrypting_drive, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
show_header => 0, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
$main_table_changed = 1; |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_physical_drives |
|
SET |
|
scan_storcli_physical_drive_controller_uuid = ".$anvil->Database->quote($controller_uuid).", |
|
scan_storcli_physical_drive_virtual_drive = ".$anvil->Database->quote($virtual_drive).", |
|
scan_storcli_physical_drive_drive_group = ".$anvil->Database->quote($drive_group).", |
|
scan_storcli_physical_drive_enclosure_id = ".$anvil->Database->quote($enclosure_id).", |
|
scan_storcli_physical_drive_slot_number = ".$anvil->Database->quote($slot_number).", |
|
scan_storcli_physical_drive_serial_number = ".$anvil->Database->quote($scan_storcli_physical_drive_serial_number).", |
|
scan_storcli_physical_drive_size = ".$anvil->Database->quote($new_size).", |
|
scan_storcli_physical_drive_sector_size = ".$anvil->Database->quote($new_sector_size).", |
|
scan_storcli_physical_drive_vendor = ".$anvil->Database->quote($new_vendor).", |
|
scan_storcli_physical_drive_model = ".$anvil->Database->quote($new_model).", |
|
scan_storcli_physical_drive_self_encrypting_drive = ".$anvil->Database->quote($new_self_encrypting_drive).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_physical_drive_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}}) |
|
{ |
|
my $new_variable_value = delete $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}{$variable}; |
|
$new_variable_value = "" if not defined $new_variable_value; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}; |
|
|
|
# If there is no change, I still want to record the temperature |
|
# (where applicable). So I setup like I will send an alert from the |
|
# start, but will only actually send if something has changed. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0031"; |
|
my $alert_level = "info"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# It's a temperature, so change the default message. |
|
$message_key = "scan_storcli_note_0064"; |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# If the temperature is rising, see if we need to set |
|
# a high warning or critical, or, clear a low warning |
|
# or critical. Check for the reverse if the |
|
# temperature is dropping. |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
### NOTE: We don't (yet) check to see if the |
|
### drive is overheating or freezing |
|
### here. That would require new logic |
|
### and is unlikely to be needed. |
|
# Temperature is back. |
|
$message_key = "scan_storcli_warning_0032"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
elsif ($new_variable_value > $old_variable_value) |
|
{ |
|
# Rising |
|
my $jumped = $new_variable_value - $old_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value > $high_critical) |
|
{ |
|
# Crossed the critical threshold. See |
|
# if this is the first time. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we |
|
# rose above the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0008"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $high_warning) |
|
{ |
|
# Crossed the warning threshold. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0009"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"temperature_state" => $temperature_state, |
|
"temperature_is" => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $clear_low_warning) |
|
{ |
|
# Risen into the clear, make sure |
|
# both warning and critical are |
|
# cleared. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0016"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has dropped back down to |
|
# safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0016"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value > $clear_low_critical) |
|
{ |
|
# Risen above critical, but not in |
|
# the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0017"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"temperature_state" => $temperature_state, |
|
"temperature_is" => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature jumped a large |
|
# amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0018"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
# Falling |
|
my $jumped = $old_variable_value - $new_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value < $low_critical) |
|
{ |
|
# Dropped below the critical threshold. This |
|
# should always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0010"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"temperature_state" => $temperature_state, |
|
"temperature_is" => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $low_warning) |
|
{ |
|
# Crossed the warning threshold. This should |
|
# always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0011"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"temperature_state" => $temperature_state, |
|
"temperature_is" => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $clear_high_warning) |
|
{ |
|
# Dropped into the clear |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0019"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has dropped back down to |
|
# safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0019"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value < $clear_high_critical) |
|
{ |
|
# Dropped below critical, but not in |
|
# the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $scan_storcli_physical_drive_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0020"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature dropped a large |
|
# amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0021"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Record this for later processing into the 'temperature' |
|
# table. |
|
my $sensor_host_key = "pd:".$scan_storcli_physical_drive_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $new_variable_value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Now actually generate an alert and save the changes if something |
|
# changed. |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
$anvil->data->{'scan-storcli'}{alert_sort}++; |
|
|
|
if ($type ne "temperature") |
|
{ |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0032"; |
|
} |
|
|
|
# We want to watch for the 'error' counters. If they |
|
# change, we make this a warning. |
|
if ($variable =~ /error_count/) |
|
{ |
|
# If we're over 6, it's a warning. If its |
|
# under 6, a notice. If it's 0, clear. |
|
if ($new_variable_value > 6) |
|
{ |
|
$alert_level = "warning"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { alert_level => $alert_level }}); |
|
} |
|
elsif ($new_variable_value > 0) |
|
{ |
|
$alert_level = "notice"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { alert_level => $alert_level }}); |
|
} |
|
$message_key = "scan_storcli_warning_0044"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
elsif ($variable =~ /fail/) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_warning_0045"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
my $variables = { |
|
serial_number => $scan_storcli_physical_drive_serial_number, |
|
name => $variable, |
|
old_value => $old_variable_value ? $old_variable_value : "--", |
|
new_value => $new_variable_value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
jump => $jump, |
|
}; |
|
my $log_level = $alert_level eq "notice" ? 3 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => $alert_level, |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
serial_number => $scan_storcli_physical_drive_serial_number, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_warning_0033", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => "scan_storcli_warning_0033", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_physical_drives', |
|
".$anvil->Database->quote($scan_storcli_physical_drive_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and delete) |
|
# this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
next if not defined $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_physical_drives'}{source_uuid}{$scan_storcli_physical_drive_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
serial_number => $scan_storcli_physical_drive_serial_number, |
|
name => $variable, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_warning_0034", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
show_header => $main_table_changed ? 0 : 1, |
|
message => "scan_storcli_warning_0034", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Delete the Physical Drive from the last scan so that we can find disks that have been removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}) |
|
{ |
|
delete $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}; |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted cachevaults (FBUs). |
|
sub process_cachevaults |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Setup our thermal thresholds |
|
my $high_critical = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{high_critical}; |
|
my $high_warning = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{high_warning}; |
|
my $low_warning = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{low_warning}; |
|
my $low_critical = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{low_critical}; |
|
my $jump = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{jump}; |
|
my $buffer = $anvil->data->{'scan-storcli'}{thresholds}{cachevault}{buffer}; |
|
my $clear_high_critical = $high_critical - $buffer; |
|
my $clear_high_warning = $high_warning - $buffer; |
|
my $clear_low_critical = $low_critical - $buffer; |
|
my $clear_low_warning = $low_warning - $buffer; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
high_critical => $high_critical, |
|
high_warning => $high_warning, |
|
low_warning => $low_warning, |
|
low_critical => $low_critical, |
|
jump => $jump, |
|
buffer => $buffer, |
|
clear_high_critical => $clear_high_critical, |
|
clear_high_warning => $clear_high_warning, |
|
clear_low_critical => $clear_low_critical, |
|
clear_low_warning => $clear_low_warning, |
|
}}); |
|
|
|
# Find new, changed and replaced Cachevaults (FBUs). |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
foreach my $cachevault_serial_number (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cachevault_serial_number => $cachevault_serial_number }}); |
|
|
|
# Is this a new Cachevault? |
|
my $cachevault_uuid = ""; |
|
my $is_new = 0; |
|
if (exists $anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$cachevault_serial_number}) |
|
{ |
|
# Yes! |
|
$cachevault_uuid = $anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$cachevault_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cachevault_uuid => $cachevault_uuid }}); |
|
} |
|
else |
|
{ |
|
# No, this is a new Cachevault. Create a new UUID for it. |
|
$cachevault_uuid = $anvil->Get->uuid(); |
|
$is_new = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cachevault_uuid => $cachevault_uuid, |
|
is_new => $is_new, |
|
}}); |
|
|
|
# Add the keys for looking it up by UUID or serial number. |
|
$anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$cachevault_serial_number} = $cachevault_uuid; |
|
$anvil->data->{'scan-storcli'}{cachevaults}{by_uuid}{$cachevault_uuid} = $cachevault_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::cachevaults::by_serial::$cachevault_serial_number" => $anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$cachevault_serial_number}, |
|
"scan-storcli::cachevaults::by_uuid::$cachevault_uuid" => $anvil->data->{'scan-storcli'}{cachevaults}{by_uuid}{$cachevault_uuid}, |
|
}}); |
|
} |
|
|
|
# First up, get the controller serial number and translate that to a controller_uuid. |
|
if (not $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{host_controller_serial_number}) |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0009", variables => { serial_number => $cachevault_serial_number }}); |
|
$anvil->nice_exit({exit_code => 9}); |
|
} |
|
my $host_controller_serial_number = $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{host_controller_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_controller_serial_number => $host_controller_serial_number }}); |
|
|
|
if (not $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0008", variables => { serial_number => $host_controller_serial_number }}); |
|
$anvil->nice_exit({exit_code => 8}); |
|
} |
|
my $controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { controller_uuid => $controller_uuid }}); |
|
|
|
# These are the values for the main table. Anything else will go in the variables table. |
|
my $new_type = ""; |
|
my $new_model = ""; |
|
my $new_state = ""; |
|
my $new_manufacture_date = ""; |
|
my $new_design_capacity = ""; |
|
my $new_replacement_needed = ""; |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
|
|
# Store and delete the value |
|
if ($variable eq "type") |
|
{ |
|
$new_type = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_type => $new_type }}); |
|
next; |
|
} |
|
if ($variable eq "device_name") |
|
{ |
|
$new_model = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_model => $new_model }}); |
|
next; |
|
} |
|
if ($variable eq "state") |
|
{ |
|
$new_state = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_state => $new_state }}); |
|
next; |
|
} |
|
if ($variable eq "date_of_manufacture") |
|
{ |
|
$new_manufacture_date = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_manufacture_date => $new_manufacture_date }}); |
|
next; |
|
} |
|
if ($variable eq "design_capacity") |
|
{ |
|
$new_design_capacity = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_design_capacity => $new_design_capacity }}); |
|
next; |
|
} |
|
if ($variable eq "replacement_required") |
|
{ |
|
$new_replacement_needed = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_replacement_needed => $new_replacement_needed }}); |
|
next; |
|
} |
|
} |
|
|
|
# Pull out the rest of the variables now. If the Cachevault is new, all variables will be |
|
# INSERTed. If the Cachevault exists, each variable will be examined and new ones will be |
|
# INSERTed, existing ones will be checked for changes and UPDATEd as needed. If the |
|
# Cachevault is NOT new, then variables from the old data will be deleted as we go and any |
|
# not found in the current data set will be left over. We'll use this to determine variables |
|
# that have vanished. They will not be deleted, but their value will be set to 'VANISHED'. |
|
if ($is_new) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cachevault_uuid => $cachevault_uuid, |
|
controller_uuid => $controller_uuid, |
|
cachevault_serial_number => $cachevault_serial_number, |
|
new_type => $new_type, |
|
new_model => $new_model, |
|
new_state => $new_state, |
|
new_design_capacity => $new_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
on_controller => $host_controller_serial_number, |
|
serial_number => $cachevault_serial_number, |
|
type => $new_type, |
|
model => $new_model, |
|
'state' => $new_state, |
|
design_capacity => $new_design_capacity, |
|
manufacture_date => $new_manufacture_date, |
|
replacement_needed => $new_replacement_needed, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0007", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0007", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_cachevaults |
|
( |
|
scan_storcli_cachevault_uuid, |
|
scan_storcli_cachevault_host_uuid, |
|
scan_storcli_cachevault_controller_uuid, |
|
scan_storcli_cachevault_serial_number, |
|
scan_storcli_cachevault_type, |
|
scan_storcli_cachevault_model, |
|
scan_storcli_cachevault_state, |
|
scan_storcli_cachevault_design_capacity, |
|
scan_storcli_cachevault_manufacture_date, |
|
scan_storcli_cachevault_replacement_needed, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($cachevault_uuid).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($cachevault_serial_number).", |
|
".$anvil->Database->quote($new_type).", |
|
".$anvil->Database->quote($new_model).", |
|
".$anvil->Database->quote($new_state).", |
|
".$anvil->Database->quote($new_design_capacity).", |
|
".$anvil->Database->quote($new_manufacture_date).", |
|
".$anvil->Database->quote($new_replacement_needed).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_note_0002"; |
|
my $alert_level = "info"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# This is a temperature, so see if the temperature outside of |
|
# the warning or critical thresholds. This is a new sensor, |
|
# so nothing to compare against. |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($value > $high_critical) |
|
{ |
|
# Crossed the critical threshold. This should |
|
# always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0036"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value > $high_warning) |
|
{ |
|
# Crossed the warning threshold. This should always |
|
# be unset because it is a new variable, but check |
|
# anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0037"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_critical) |
|
{ |
|
# Dropped below the critical threshold. This should |
|
# always be unset because it is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0038"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_warning) |
|
{ |
|
# Crossed the warning threshold. This should always be unset |
|
# because it is a new variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0039"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
|
|
# Record this for later processing into the 'temperature' table. |
|
my $sensor_host_key = "cachevault:".$cachevault_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
serial_number => $cachevault_serial_number, |
|
name => $variable, |
|
value => $value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
}; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => 0, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_cachevaults', |
|
".$anvil->Database->quote($cachevault_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change (a changed SN/Cachevault should be |
|
### picked up as a new Cachevault), but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_cachevault_serial_number = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_serial_number}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_controller_uuid}; |
|
my $old_type = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_type}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_model}; |
|
my $old_state = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_state}; |
|
my $old_design_capacity = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_design_capacity}; |
|
my $old_manufacture_date = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_manufacture_date}; |
|
my $old_replacement_needed = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_replacement_needed}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cachevault_serial_number => $cachevault_serial_number, |
|
old_cachevault_serial_number => $old_cachevault_serial_number, |
|
controller_uuid => $controller_uuid, |
|
old_controller_uuid => $old_controller_uuid, |
|
new_type => $new_type, |
|
old_type => $old_type, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_state => $new_state, |
|
old_state => $old_state, |
|
new_design_capacity => $new_design_capacity, |
|
old_design_capacity => $old_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
old_manufacture_date => $old_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
old_replacement_needed => $old_replacement_needed, |
|
}}); |
|
|
|
if (($cachevault_serial_number ne $old_cachevault_serial_number) or |
|
($controller_uuid ne $old_controller_uuid) or |
|
($new_type ne $old_type) or |
|
($new_model ne $old_model) or |
|
($new_state ne $old_state) or |
|
($new_design_capacity ne $old_design_capacity) or |
|
($new_manufacture_date ne $old_manufacture_date) or |
|
($new_replacement_needed ne $old_replacement_needed)) |
|
{ |
|
# I need the serial numbers for the controller UUIDs. |
|
my $new_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_controller_serial_number => $new_controller_serial_number, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Send a warning level alert because the most likely change is 'state' or |
|
# 'replacement_needed'. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0036"; |
|
if ($new_state ne $old_state) |
|
{ |
|
if ($old_state eq "VANISHED") |
|
{ |
|
# Cachevault has returned. |
|
$message_key = "scan_storcli_warning_0037"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
### TODO: Verify this is the expected string on Cachevaults. |
|
if ($new_state =~ /optimal/i) |
|
{ |
|
$cleared = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared => $cleared }}); |
|
} |
|
} |
|
my $variables = { |
|
new_on_controller => $new_controller_serial_number, |
|
old_on_controller => $old_controller_serial_number, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_serial_number => $cachevault_serial_number, |
|
old_serial_number => $old_cachevault_serial_number, |
|
new_type => $new_type, |
|
old_type => $old_type, |
|
new_state => $new_state, |
|
old_state => $old_state, |
|
new_design_capacity => $new_design_capacity, |
|
old_design_capacity => $old_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
old_manufacture_date => $old_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
old_replacement_needed => $old_replacement_needed, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => "warning", |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => 0, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
$main_table_changed = 1; |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_cachevaults |
|
SET |
|
scan_storcli_cachevault_controller_uuid = ".$anvil->Database->quote($controller_uuid).", |
|
scan_storcli_cachevault_serial_number = ".$anvil->Database->quote($cachevault_serial_number).", |
|
scan_storcli_cachevault_type = ".$anvil->Database->quote($new_type).", |
|
scan_storcli_cachevault_model = ".$anvil->Database->quote($new_model).", |
|
scan_storcli_cachevault_state = ".$anvil->Database->quote($new_state).", |
|
scan_storcli_cachevault_manufacture_date = ".$anvil->Database->quote($new_manufacture_date).", |
|
scan_storcli_cachevault_design_capacity = ".$anvil->Database->quote($new_design_capacity).", |
|
scan_storcli_cachevault_replacement_needed = ".$anvil->Database->quote($new_replacement_needed).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_cachevault_uuid = ".$anvil->Database->quote($cachevault_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}}) |
|
{ |
|
my $new_variable_value = delete $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
new_variable_value => $new_variable_value, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}; |
|
|
|
# If there is no change, I still want to record the |
|
# temperature (where applicable). So I setup like I will send |
|
# an alert from the start, but will only actually send if |
|
# something has changed. |
|
my $cleared = 1; |
|
my $message_key = "scan_storcli_warning_0038"; |
|
my $alert_level = "info"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# It's a temperature, so change the default message. |
|
$message_key = "scan_storcli_note_0065"; |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# If the temperature is rising, see if we |
|
# need to set a high warning or critical, or, |
|
# clear a low warning or critical. Check for |
|
# the reverse if the temperature is dropping. |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
### NOTE: We don't (yet) check to see |
|
### if the drive is overheating |
|
### or freezing here. That |
|
### would require new logic and |
|
### is unlikely to be needed. |
|
# Temperature is back. |
|
$cleared = 1; |
|
$message_key = "scan_storcli_warning_0039"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($old_variable_value > $new_variable_value) |
|
{ |
|
# Rising |
|
my $jumped = $new_variable_value - $old_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value > $high_critical) |
|
{ |
|
# Crossed the critical |
|
# threshold. See if this is |
|
# the first time. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0040"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $high_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0041"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $clear_low_warning) |
|
{ |
|
# Risen into the clear, make |
|
# sure both warning and |
|
# critical are cleared. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0042"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0042"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value > $clear_low_critical) |
|
{ |
|
# Risen above critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0043"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature jumped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0044"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
# Falling |
|
my $jumped = $old_variable_value - $new_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value < $low_critical) |
|
{ |
|
# Dropped below the critical |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0045"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $low_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $cachevault_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0046"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $clear_high_warning) |
|
{ |
|
# Dropped into the clear |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0047"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0047"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value < $clear_high_critical) |
|
{ |
|
# Dropped below critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $cachevault_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0048"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature dropped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0049"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Record this for later processing into the |
|
# 'temperature' table. |
|
my $sensor_host_key = "cachevault:".$cachevault_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $new_variable_value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Now actually generate an alert and save the changes if something |
|
# changed. |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
$anvil->data->{'scan-storcli'}{alert_sort}++; |
|
|
|
if ($type ne "temperature") |
|
{ |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0039"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
|
|
# Check for some important issues |
|
#if ($variable =~ /memory_correctable_errors/) |
|
# Nothing seems to be of special interest... See: SELECT a.host_name, b.scan_storcli_cachevault_serial_number AS sn, b.scan_storcli_cachevault_type, scan_storcli_cachevault_model, c.scan_storcli_variable_name AS variable, c.scan_storcli_variable_value AS value, c.scan_storcli_variable_is_temperature AS temp, c.modified_date FROM hosts a, scan_storcli_cachevaults b, scan_storcli_variables c WHERE a.host_uuid = b.scan_storcli_cachevault_host_uuid AND b.scan_storcli_cachevault_uuid = c.scan_storcli_variable_source_uuid AND a.host_name = 'an-a07n01.alteeve.com'; |
|
} |
|
my $variables = { |
|
serial_number => $cachevault_serial_number, |
|
name => $variable, |
|
old_value => $old_variable_value ? $old_variable_value : "--", |
|
new_value => $new_variable_value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
jump => $jump, |
|
}; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => $main_table_changed ? 0 : 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
serial_number => $cachevault_serial_number, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0041", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0041", |
|
variables => $variables, |
|
show_header => $main_table_changed ? 0 : 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_cachevaults', |
|
".$anvil->Database->quote($cachevault_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and |
|
# delete) this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_cachevaults'}{source_uuid}{$cachevault_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
serial_number => $cachevault_serial_number, |
|
name => $variable, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0040", variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => 0, |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0040", |
|
variables => $variables, |
|
show_header => $main_table_changed ? 0 : 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Delete the Cachevault from the last scan so that we can find controllers that have been removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}) |
|
{ |
|
delete $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}; |
|
} |
|
} |
|
|
|
# See if any Cachevaults have vanished. |
|
foreach my $cachevault_uuid (keys %{$anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}}) |
|
{ |
|
# Cachevault vanished! |
|
my $old_cachevault_serial_number = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_serial_number}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_controller_uuid}; |
|
my $old_state = $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}{scan_storcli_cachevault_state}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_cachevault_serial_number => $old_cachevault_serial_number, |
|
old_controller_uuid => $old_controller_uuid, |
|
old_state => $old_state, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$cachevault_uuid}; |
|
|
|
# If the old alarm state is already 'VANISHED', ignore it. |
|
next if $old_state eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
cachevault_serial_number => $old_cachevault_serial_number, |
|
controller_serial_number => $old_controller_serial_number, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0042", variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => 0, |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0042", |
|
variables => $variables, |
|
show_header => 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_cachevaults |
|
SET |
|
scan_storcli_cachevault_state = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_cachevault_uuid = ".$anvil->Database->quote($cachevault_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
# Now commit the changes. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted battery backup units (BBUs). |
|
sub process_bbus |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Find new, changed and replaced BBUs. |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
foreach my $bbu_serial_number (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bbu_serial_number => $bbu_serial_number }}); |
|
|
|
# Is this a new BBU? |
|
my $bbu_uuid = ""; |
|
my $is_new = 0; |
|
if (exists $anvil->data->{'scan-storcli'}{bbus}{by_serial}{$bbu_serial_number}) |
|
{ |
|
# Yes! |
|
$bbu_uuid = $anvil->data->{'scan-storcli'}{bbus}{by_serial}{$bbu_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bbu_uuid => $bbu_uuid }}); |
|
} |
|
else |
|
{ |
|
# No, this is a new BBU. Create a new UUID for it. |
|
$bbu_uuid = $anvil->Get->uuid(); |
|
$is_new = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bbu_uuid => $bbu_uuid, |
|
is_new => $is_new, |
|
}}); |
|
|
|
# Add the keys for looking it up by UUID or serial number. |
|
$anvil->data->{'scan-storcli'}{bbus}{by_serial}{$bbu_serial_number} = $bbu_uuid; |
|
$anvil->data->{'scan-storcli'}{bbus}{by_uuid}{$bbu_uuid} = $bbu_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::bbus::by_serial::$bbu_serial_number" => $anvil->data->{'scan-storcli'}{bbus}{by_serial}{$bbu_serial_number}, |
|
"scan-storcli::bbus::by_uuid::$bbu_uuid" => $anvil->data->{'scan-storcli'}{bbus}{by_uuid}{$bbu_uuid}, |
|
}}); |
|
} |
|
|
|
# The temperature range of the BBU depends on whether it is charging or discharging. |
|
my $bbu_temperature_key = "normal"; |
|
# Get the charge state. |
|
# - None |
|
# - Discharging |
|
# - Charging |
|
my $charging = $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{charging_status}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { charging => $charging }}); |
|
|
|
if ($charging =~ /^discharging$/i) |
|
{ |
|
$bbu_temperature_key = "discharging"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bbu_temperature_key => $bbu_temperature_key }}); |
|
} |
|
|
|
# Setup our thermal thresholds |
|
my $high_critical = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{high_critical}; |
|
my $high_warning = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{high_warning}; |
|
my $low_warning = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{low_warning}; |
|
my $low_critical = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{low_critical}; |
|
my $jump = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{jump}; |
|
my $buffer = $anvil->data->{'scan-storcli'}{thresholds}{bbu}{$bbu_temperature_key}{buffer}; |
|
my $clear_high_critical = $high_critical - $buffer; |
|
my $clear_high_warning = $high_warning - $buffer; |
|
my $clear_low_critical = $low_critical - $buffer; |
|
my $clear_low_warning = $low_warning - $buffer; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
high_critical => $high_critical, |
|
high_warning => $high_warning, |
|
low_warning => $low_warning, |
|
low_critical => $low_critical, |
|
jump => $jump, |
|
buffer => $buffer, |
|
clear_high_critical => $clear_high_critical, |
|
clear_high_warning => $clear_high_warning, |
|
clear_low_critical => $clear_low_critical, |
|
clear_low_warning => $clear_low_warning, |
|
}}); |
|
|
|
# Fine-tune the alert thresholds |
|
if ($clear_high_critical < $high_warning) |
|
{ |
|
$clear_high_critical = $high_warning + 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_high_critical => $clear_high_critical }}); |
|
} |
|
if ($clear_low_critical > $low_warning) |
|
{ |
|
$clear_low_critical = $low_warning - 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_low_critical => $clear_low_critical }}); |
|
} |
|
|
|
# First up, get the controller serial number and translate that to a controller_uuid. |
|
if (not $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{host_controller_serial_number}) |
|
{ |
|
# Error! |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0007", variables => { serial_number => $bbu_serial_number }}); |
|
$anvil->nice_exit({exit_code => 7}); |
|
} |
|
my $host_controller_serial_number = $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{host_controller_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_controller_serial_number => $host_controller_serial_number }}); |
|
|
|
if (not $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0008", variables => { serial_number => $host_controller_serial_number }}); |
|
$anvil->nice_exit({exit_code => 8}); |
|
} |
|
my $controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$host_controller_serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { controller_uuid => $controller_uuid }}); |
|
|
|
# These are the values for the main table. Anything else will go in the variables table. |
|
my $new_type = ""; |
|
my $new_model = ""; |
|
my $new_state = ""; |
|
my $new_manufacture_date = ""; |
|
my $new_design_capacity = ""; |
|
my $new_replacement_needed = ""; |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
|
|
# Store and delete the value |
|
if ($variable eq "type") |
|
{ |
|
$new_type = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_type => $new_type }}); |
|
next; |
|
} |
|
if ($variable eq "manufacture_name") |
|
{ |
|
$new_model = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_model => $new_model }}); |
|
next; |
|
} |
|
if ($variable eq "battery_state") |
|
{ |
|
$new_state = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_model => $new_model }}); |
|
next; |
|
} |
|
if ($variable eq "date_of_manufacture") |
|
{ |
|
$new_manufacture_date = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_manufacture_date => $new_manufacture_date }}); |
|
next; |
|
} |
|
if ($variable eq "design_capacity") |
|
{ |
|
$new_design_capacity = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_design_capacity => $new_design_capacity }}); |
|
next; |
|
} |
|
if ($variable eq "replacement_required") |
|
{ |
|
$new_replacement_needed = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_replacement_needed => $new_replacement_needed }}); |
|
next; |
|
} |
|
} |
|
|
|
# Pull out the rest of the variables now. If the BBU is new, all variables will be INSERTed. |
|
# If the BBU exists, each variable will be examined and new ones will be INSERTed, existing |
|
# ones will be checked for changes and UPDATEd as needed. If the BBU is NOT new, then |
|
# variables from the old data will be deleted as we go and any not found in the current data |
|
# set will be left over. We'll use this to determine variables that have vanished. They will |
|
# not be deleted, but their value will be set to 'VANISHED'. |
|
if ($is_new) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bbu_uuid => $bbu_uuid, |
|
controller_uuid => $controller_uuid, |
|
bbu_serial_number => $bbu_serial_number, |
|
new_type => $new_type, |
|
new_model => $new_model, |
|
new_state => $new_state, |
|
new_design_capacity => $new_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
on_controller => $host_controller_serial_number, |
|
serial_number => $bbu_serial_number, |
|
type => $new_type, |
|
model => $new_model, |
|
'state' => $new_state, |
|
design_capacity => $new_design_capacity, |
|
manufacture_date => $new_manufacture_date, |
|
replacement_needed => $new_replacement_needed, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_note_0003", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0003", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_bbus |
|
( |
|
scan_storcli_bbu_uuid, |
|
scan_storcli_bbu_host_uuid, |
|
scan_storcli_bbu_controller_uuid, |
|
scan_storcli_bbu_serial_number, |
|
scan_storcli_bbu_type, |
|
scan_storcli_bbu_model, |
|
scan_storcli_bbu_state, |
|
scan_storcli_bbu_design_capacity, |
|
scan_storcli_bbu_manufacture_date, |
|
scan_storcli_bbu_replacement_needed, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($bbu_uuid).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($bbu_serial_number).", |
|
".$anvil->Database->quote($new_type).", |
|
".$anvil->Database->quote($new_model).", |
|
".$anvil->Database->quote($new_state).", |
|
".$anvil->Database->quote($new_design_capacity).", |
|
".$anvil->Database->quote($new_manufacture_date).", |
|
".$anvil->Database->quote($new_replacement_needed).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
my $message_key = "scan_storcli_note_0002"; |
|
my $alert_level = "notice"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# This is a temperature, so see if the temperature outside of |
|
# the warning or critical thresholds. This is a new sensor, |
|
# so nothing to compare against. |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($value > $high_critical) |
|
{ |
|
# Crossed the critical threshold. This should |
|
# always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0050"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value > $high_warning) |
|
{ |
|
# Crossed the warning threshold. This should always |
|
# be unset because it is a new variable, but check |
|
# anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0051"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_critical) |
|
{ |
|
# Dropped below the critical threshold. This should |
|
# always be unset because it is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the |
|
# critical threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0052"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_warning) |
|
{ |
|
# Crossed the warning threshold. This should always be unset |
|
# because it is a new variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first time we rose above the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0053"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
|
|
# Record this for later processing into the 'temperature' table. |
|
my $sensor_host_key = "bbu:".$bbu_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
serial_number => $bbu_serial_number, |
|
name => $variable, |
|
value => $value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
}; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => 0, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_bbus', |
|
".$anvil->Database->quote($bbu_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change (a changed SN/BBU should be picked up |
|
### as a new BBU), but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_bbu_serial_number = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_serial_number}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_controller_uuid}; |
|
my $old_type = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_type}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_model}; |
|
my $old_state = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_state}; |
|
my $old_design_capacity = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_design_capacity}; |
|
my $old_manufacture_date = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_manufacture_date}; |
|
my $old_replacement_needed = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_replacement_needed}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
bbu_serial_number => $bbu_serial_number, |
|
old_bbu_serial_number => $old_bbu_serial_number, |
|
controller_uuid => $controller_uuid, |
|
old_controller_uuid => $old_controller_uuid, |
|
new_type => $new_type, |
|
old_type => $old_type, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_state => $new_state, |
|
old_state => $old_state, |
|
new_design_capacity => $new_design_capacity, |
|
old_design_capacity => $old_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
old_manufacture_date => $old_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
old_replacement_needed => $old_replacement_needed, |
|
}}); |
|
|
|
if (($bbu_serial_number ne $old_bbu_serial_number) or |
|
($controller_uuid ne $old_controller_uuid) or |
|
($new_type ne $old_type) or |
|
($new_model ne $old_model) or |
|
($new_state ne $old_state) or |
|
($new_design_capacity ne $old_design_capacity) or |
|
($new_manufacture_date ne $old_manufacture_date) or |
|
($new_replacement_needed ne $old_replacement_needed)) |
|
{ |
|
# I need the serial numbers for the controller UUIDs. |
|
my $new_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_controller_serial_number => $new_controller_serial_number, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Send a warning level alert because the most likely change is 'state' or |
|
# 'replacement_needed'. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0010"; |
|
if ($new_state ne $old_state) |
|
{ |
|
if ($old_state eq "VANISHED") |
|
{ |
|
# BBU has returned. |
|
$message_key = "scan_storcli_warning_0011"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
if ($new_state =~ /optimal/i) |
|
{ |
|
$cleared = 1; |
|
} |
|
} |
|
my $variables = { |
|
new_on_controller => $new_controller_serial_number, |
|
old_on_controller => $old_controller_serial_number, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_serial_number => $bbu_serial_number, |
|
old_serial_number => $old_bbu_serial_number, |
|
new_type => $new_type, |
|
old_type => $old_type, |
|
new_state => $new_state, |
|
old_state => $old_state, |
|
new_design_capacity => $new_design_capacity, |
|
old_design_capacity => $old_design_capacity, |
|
new_manufacture_date => $new_manufacture_date, |
|
old_manufacture_date => $old_manufacture_date, |
|
new_replacement_needed => $new_replacement_needed, |
|
old_replacement_needed => $old_replacement_needed, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
clear_alert => $cleared, |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => 0, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
$main_table_changed = 1; |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_bbus |
|
SET |
|
scan_storcli_bbu_controller_uuid = ".$anvil->Database->quote($controller_uuid).", |
|
scan_storcli_bbu_serial_number = ".$anvil->Database->quote($bbu_serial_number).", |
|
scan_storcli_bbu_type = ".$anvil->Database->quote($new_type).", |
|
scan_storcli_bbu_model = ".$anvil->Database->quote($new_model).", |
|
scan_storcli_bbu_state = ".$anvil->Database->quote($new_state).", |
|
scan_storcli_bbu_manufacture_date = ".$anvil->Database->quote($new_manufacture_date).", |
|
scan_storcli_bbu_design_capacity = ".$anvil->Database->quote($new_design_capacity).", |
|
scan_storcli_bbu_replacement_needed = ".$anvil->Database->quote($new_replacement_needed).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_bbu_uuid = ".$anvil->Database->quote($bbu_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}}) |
|
{ |
|
my $new_variable_value = delete $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}; |
|
|
|
# If there is no change, I still want to record the |
|
# temperature (where applicable). So I setup like I will send |
|
# an alert from the start, but will only actually send if |
|
# something has changed. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0012"; |
|
my $alert_level = "info"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# It's a temperature, so change the default message |
|
# and drop the default alert level. |
|
$message_key = "scan_storcli_note_0066"; |
|
$alert_level = "info"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# If the temperature is rising, see if we |
|
# need to set a high warning or critical, or, |
|
# clear a low warning or critical. Check for |
|
# the reverse if the temperature is dropping. |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
### NOTE: We don't (yet) check to see |
|
### if the drive is overheating |
|
### or freezing here. That |
|
### would require new logic and |
|
### is unlikely to be needed. |
|
# Temperature is back. |
|
$message_key = "scan_storcli_warning_0013"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
elsif ($new_variable_value > $old_variable_value) |
|
{ |
|
# Rising |
|
my $jumped = $new_variable_value - $old_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value > $high_critical) |
|
{ |
|
# Crossed the critical |
|
# threshold. See if this is |
|
# the first time. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0054"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $high_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0055"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"temperature_state" => $temperature_state, |
|
"temperature_is" => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $clear_low_warning) |
|
{ |
|
# Risen into the clear, make |
|
# sure both warning and |
|
# critical are cleared. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0056"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0056"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value > $clear_low_critical) |
|
{ |
|
# Risen above critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0057"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature jumped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0058"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
# Falling |
|
my $jumped = $old_variable_value - $new_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value < $low_critical) |
|
{ |
|
# Dropped below the critical |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0059"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $low_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0060"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $clear_high_warning) |
|
{ |
|
# Dropped into the clear |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0061"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0061"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value < $clear_high_critical) |
|
{ |
|
# Dropped below critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $bbu_serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $bbu_serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0062"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature dropped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0063"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Record this for later processing into the |
|
# 'temperature' table. |
|
my $sensor_host_key = "bbu:$bbu_serial_number"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $new_variable_value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Now actually generate an alert and save the changes if something |
|
# changed. |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
if ($type ne "temperature") |
|
{ |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0013"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
|
|
# Check for some important issues |
|
if ($variable =~ /over_charged/) |
|
{ |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_warning_0049"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
if ($variable =~ /over_temperature/) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_warning_0050"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
if ($variable =~ /pack_is_about_to_fail_and_should_be_replaced/) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_warning_0051"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
message_key => $message_key, |
|
alert_level => $alert_level, |
|
}}); |
|
} |
|
# Other things that might be of interest... See: SELECT a.host_name, b.scan_storcli_bbu_serial_number AS sn, b.scan_storcli_bbu_type, b.scan_storcli_bbu_model, c.scan_storcli_variable_name AS variable, c.scan_storcli_variable_value AS value, c.scan_storcli_variable_is_temperature AS temp, c.modified_date FROM hosts a, scan_storcli_bbus b, scan_storcli_variables c WHERE a.host_uuid = b.scan_storcli_bbu_host_uuid AND b.scan_storcli_bbu_uuid = c.scan_storcli_variable_source_uuid AND a.host_name = 'an-a05n01.alteeve.com'; |
|
} |
|
my $variables = { |
|
serial_number => $bbu_serial_number, |
|
name => $variable, |
|
old_value => $old_variable_value ? $old_variable_value : "--", |
|
new_value => $new_variable_value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
jump => $jump, |
|
}; |
|
my $show_header = $main_table_changed ? 0 : 1; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => $show_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
serial_number => $bbu_serial_number, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
my $show_header = $main_table_changed ? 0 : 1; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_warning_0015", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0015", |
|
variables => $variables, |
|
show_header => $show_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_bbus', |
|
".$anvil->Database->quote($bbu_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and |
|
# delete) this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_bbus'}{source_uuid}{$bbu_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
serial_number => $bbu_serial_number, |
|
name => $variable, |
|
}; |
|
my $show_header = $main_table_changed ? 0 : 1; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_storcli_warning_0014", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0014", |
|
variables => $variables, |
|
show_header => $show_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Delete the BBU from the last scan so that we can find controllers that have been removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}) |
|
{ |
|
delete $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}; |
|
} |
|
} |
|
|
|
# See if any BBUs have vanished. |
|
foreach my $bbu_uuid (keys %{$anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}}) |
|
{ |
|
# BBU vanished! |
|
my $old_bbu_serial_number = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_serial_number}; |
|
my $old_controller_uuid = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_controller_uuid}; |
|
my $old_state = $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}{scan_storcli_bbu_state}; |
|
my $old_controller_serial_number = $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$old_controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_bbu_serial_number => $old_bbu_serial_number, |
|
old_controller_uuid => $old_controller_uuid, |
|
old_state => $old_state, |
|
old_controller_serial_number => $old_controller_serial_number, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$bbu_uuid}; |
|
|
|
# If the old alarm state is already 'VANISHED', ignore it. |
|
next if $old_state eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
bbu_serial_number => $old_bbu_serial_number, |
|
controller_serial_number => $old_controller_serial_number, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0016", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0016", |
|
variables => $variables, |
|
show_header => 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_bbus |
|
SET |
|
scan_storcli_bbu_state = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_bbu_uuid = ".$anvil->Database->quote($bbu_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
# Now commit the changes. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
# Look for added, changed or deleted controllers. |
|
sub process_controllers |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Setup our thermal thresholds |
|
my $high_critical = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{high_critical}; |
|
my $high_warning = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{high_warning}; |
|
my $low_warning = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{low_warning}; |
|
my $low_critical = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{low_critical}; |
|
my $jump = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{jump}; |
|
my $buffer = $anvil->data->{'scan-storcli'}{thresholds}{raid_on_chip}{buffer}; |
|
my $clear_high_critical = $high_critical - $buffer; |
|
my $clear_high_warning = $high_warning - $buffer; |
|
my $clear_low_critical = $low_critical - $buffer; |
|
my $clear_low_warning = $low_warning - $buffer; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
high_critical => $high_critical, |
|
high_warning => $high_warning, |
|
low_warning => $low_warning, |
|
low_critical => $low_critical, |
|
jump => $jump, |
|
buffer => $buffer, |
|
clear_high_critical => $clear_high_critical, |
|
clear_high_warning => $clear_high_warning, |
|
clear_low_critical => $clear_low_critical, |
|
clear_low_warning => $clear_low_warning, |
|
}}); |
|
|
|
# Fine-tune the alert thresholds |
|
if ($clear_high_critical < $high_warning) |
|
{ |
|
$clear_high_critical = $high_warning + 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_high_critical => $clear_high_critical }}); |
|
} |
|
if ($clear_low_critical > $low_warning) |
|
{ |
|
$clear_low_critical = $low_warning - 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { clear_low_critical => $clear_low_critical }}); |
|
} |
|
|
|
# Look for new, changed or deleted controllers. |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
foreach my $serial_number (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
serial_number => $serial_number, |
|
"scan-storcli::controllers::by_serial::$serial_number" => $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number}, |
|
}}); |
|
|
|
# Is this controller in the database yet? |
|
my $controller_uuid = ""; |
|
my $is_new = 0; |
|
if ($anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number}) |
|
{ |
|
# Yes! |
|
$controller_uuid = $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { controller_uuid => $controller_uuid }}); |
|
} |
|
else |
|
{ |
|
# No, this is a new controller. Create a new UUID for it. |
|
$controller_uuid = $anvil->Get->uuid(); |
|
$is_new = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
controller_uuid => $controller_uuid, |
|
is_new => $is_new, |
|
}}); |
|
|
|
# Add the keys for looking it up by UUID or serial number. |
|
$anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number} = $controller_uuid; |
|
$anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::controllers::by_serial::$serial_number" => $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$serial_number}, |
|
"scan-storcli::controllers::by_uuid::$controller_uuid" => $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$controller_uuid}, |
|
}}); |
|
} |
|
|
|
# These are the values for the main table. Anything else will go in the variables table which |
|
# will be processed after the controller. |
|
my $new_model = ""; |
|
my $new_alarm_state = ""; |
|
my $new_cache_size = ""; |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}{$serial_number}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
|
|
if ($variable eq "model") |
|
{ |
|
# Store and delete the value |
|
$new_model = delete $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_model => $new_model }}); |
|
next; |
|
} |
|
elsif ($variable eq "alarm_state") |
|
{ |
|
# Store and delete the value |
|
$new_alarm_state = delete $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_alarm_state => $new_alarm_state }}); |
|
next; |
|
} |
|
elsif ($variable eq "on_board_memory_size") |
|
{ |
|
# Store and delete the value |
|
$new_cache_size = delete $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_cache_size => $new_cache_size }}); |
|
next; |
|
} |
|
} |
|
|
|
# Pull out the rest of the variables now. If the controller is new, all variables will be |
|
# INSERTed. If the controller exists, each variable will be examined and new ones will be |
|
# INSERTed, existing ones will be checked for changes and UPDATEd as needed. If the |
|
# controller is NOT new, then variables from the old data will be deleted as we go and any |
|
# not found in the current data set will be left over. We'll use this to determine variables |
|
# that have vanished. They will not be deleted, but their value will be set to 'VANISHED'. |
|
if ($is_new) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
serial_number => $serial_number, |
|
new_model => $new_model, |
|
new_alarm_state => $new_alarm_state, |
|
new_cache_size => $new_cache_size, |
|
}}); |
|
|
|
### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. |
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
model => $new_model, |
|
serial_number => $serial_number, |
|
say_cache_size => $anvil->Convert->bytes_to_human_readable({'bytes' => $new_cache_size}), |
|
alarm_state => $new_alarm_state, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_note_0001", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0001", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_controllers |
|
( |
|
scan_storcli_controller_host_uuid, |
|
scan_storcli_controller_uuid, |
|
scan_storcli_controller_serial_number, |
|
scan_storcli_controller_model, |
|
scan_storcli_controller_alarm_state, |
|
scan_storcli_controller_cache_size, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($serial_number).", |
|
".$anvil->Database->quote($new_model).", |
|
".$anvil->Database->quote($new_alarm_state).", |
|
".$anvil->Database->quote($new_cache_size).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
|
|
# Process the rest of the variables and temperatures now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}{$serial_number}{$type}}) |
|
{ |
|
my $value = delete $anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
temperature => $temperature, |
|
}}); |
|
|
|
my $message_key = "scan_storcli_note_0002"; |
|
my $alert_level = "notice"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($type eq "temperature") |
|
{ |
|
# This is a temperature, so see if the temperature outside of |
|
# the warning or critical thresholds. This is a new sensor, |
|
# so nothing to compare against. |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
if ($value > $high_critical) |
|
{ |
|
# Crossed the high critical threshold. This should |
|
# always be unset because it is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0022"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value > $high_warning) |
|
{ |
|
# Crossed the high warning threshold. This should |
|
# always be unset because it is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0023"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_critical) |
|
{ |
|
# Dropped below the low critical threshold. This |
|
# should always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0024"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($value < $low_warning) |
|
{ |
|
# Dropped below the low warning threshold. This |
|
# should always be unset because it is a new |
|
# variable, but check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0025"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
|
|
# Record this for later processing into the 'temperature' table. |
|
my $sensor_host_key = "controller:".$serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
serial_number => $serial_number, |
|
name => $variable, |
|
value => $value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
}; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => 0, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_controllers', |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
### NOTE: The serial number should never change (a changed SN/controller should be |
|
### picked up as a new controller), but we check/update just to be safe. |
|
# Look for changes. |
|
my $main_table_changed = 0; |
|
my $old_serial_number = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_serial_number}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_model}; |
|
my $old_alarm_state = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_alarm_state}; |
|
my $old_cache_size = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_cache_size}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
serial_number => $serial_number, |
|
old_serial_number => $old_serial_number, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_alarm_state => $new_alarm_state, |
|
old_alarm_state => $old_alarm_state, |
|
new_cache_size => $new_cache_size, |
|
old_cache_size => $old_cache_size, |
|
}}); |
|
|
|
if (($serial_number ne $old_serial_number) or |
|
($new_model ne $old_model) or |
|
($new_alarm_state ne $old_alarm_state) or |
|
($new_cache_size ne $old_cache_size)) |
|
{ |
|
# Send a warning level alert because the most likely change is 'alarm_state'. |
|
# If, however, the alarm state is now 'off', then we'll clear the alert. |
|
my $cleared = 0; |
|
my $message_key = "scan_storcli_warning_0002"; |
|
if ($new_alarm_state ne $old_alarm_state) |
|
{ |
|
if ($old_alarm_state eq "VANISHED") |
|
{ |
|
# Controller has returned. |
|
$message_key = "scan_storcli_warning_0009"; |
|
} |
|
if ($new_alarm_state =~ /off/i) |
|
{ |
|
$cleared = 1; |
|
} |
|
} |
|
my $variables = { |
|
new_serial_number => $serial_number, |
|
old_serial_number => $old_serial_number, |
|
new_model => $new_model, |
|
old_model => $old_model, |
|
new_alarm_state => $new_alarm_state, |
|
old_alarm_state => $old_alarm_state, |
|
new_cache_size => $new_cache_size, |
|
old_cache_size => $old_cache_size, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => "warning", |
|
message => $message_key, |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE}); |
|
|
|
$main_table_changed = 1; |
|
my $query = " |
|
UPDATE |
|
scan_storcli_controllers |
|
SET |
|
scan_storcli_controller_serial_number = ".$anvil->Database->quote($serial_number).", |
|
scan_storcli_controller_model = ".$anvil->Database->quote($new_model).", |
|
scan_storcli_controller_alarm_state = ".$anvil->Database->quote($new_alarm_state).", |
|
scan_storcli_controller_cache_size = ".$anvil->Database->quote($new_cache_size).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_controller_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
scan_storcli_controller_uuid = ".$anvil->Database->quote($controller_uuid)." |
|
;"; |
|
|
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
### Process the rest of the variables now. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{controller}{serial_number}{$serial_number}{$type}}) |
|
{ |
|
# Being in the 'variable' hash, 'is_temperature' is 'FALSE'. |
|
my $new_variable_value = delete $anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable}; |
|
my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
temperature => $temperature, |
|
}}); |
|
if (exists $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}{scan_storcli_variable_uuid}) |
|
{ |
|
# Look for changes |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
new_variable_value => $new_variable_value, |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}; |
|
|
|
# If there is no change, I still want to record the |
|
# temperature (where applicable). So I setup like I will send |
|
# an alert from the start, but will only actually send if |
|
# something has changed. |
|
my $message_key = "scan_storcli_warning_0003"; |
|
my $alert_level = "info"; |
|
my $temperature_state = "ok"; |
|
my $temperature_is = "nominal"; |
|
my $cleared = 0; |
|
if ($type eq "temperature") |
|
{ |
|
# It's a temperature, so change the default message. |
|
$message_key = "scan_storcli_note_0067"; |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# If the temperature is rising, see if we |
|
# need to set a high warning or critical, or, |
|
# clear a low warning or critical. Check for |
|
# the reverse if the temperature is dropping. |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
### NOTE: We don't (yet) check to see |
|
### if the drive is overheating |
|
### or freezing here. That |
|
### would require new logic and |
|
### is unlikely to be needed. |
|
# Temperature is back. |
|
$message_key = "scan_storcli_warning_0006"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
elsif ($new_variable_value > $old_variable_value) |
|
{ |
|
# Rising |
|
my $jumped = ($new_variable_value - $old_variable_value); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value > $high_critical) |
|
{ |
|
# Crossed the critical |
|
# threshold. See if this is |
|
# the first time. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0026"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $high_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0027"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"alert_level" => $alert_level, |
|
"message_key" => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value > $clear_low_warning) |
|
{ |
|
# Risen into the clear, make |
|
# sure both warning and |
|
# critical are cleared. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0028"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0028"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value > $clear_low_critical) |
|
{ |
|
# Risen above critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0029"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature jumped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0030"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"alert_level" => $alert_level, |
|
"message_key" => $message_key, |
|
}}); |
|
} |
|
} |
|
else |
|
{ |
|
# Falling |
|
my $jumped = $old_variable_value - $new_variable_value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jumped => $jumped }}); |
|
if ($new_variable_value < $low_critical) |
|
{ |
|
# Dropped below the critical |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_low_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_note_0031"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "critical"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $low_warning) |
|
{ |
|
# Crossed the warning |
|
# threshold. This should |
|
# always be unset because it |
|
# is a new variable, but |
|
# check anyway. |
|
my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $serial_number.":".$variable."_low_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); |
|
if ($changed) |
|
{ |
|
# This is the first |
|
# time we rose above |
|
# the critical |
|
# threshold. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0032"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "low"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($new_variable_value < $clear_high_warning) |
|
{ |
|
# Dropped into the clear |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared_critical => $cleared_critical, |
|
cleared_warning => $cleared_warning, |
|
}}); |
|
if ($cleared_critical) |
|
{ |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0033"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($cleared_warning) |
|
{ |
|
# The temperature has |
|
# dropped back down |
|
# to safe levels. |
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0033"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
elsif ($new_variable_value < $clear_high_critical) |
|
{ |
|
# Dropped below critical, but |
|
# not in the clear. |
|
my $cleared_critical = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_high_critical", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_critical => $cleared_critical }}); |
|
if ($cleared_critical) |
|
{ |
|
# Set the warning. |
|
my $cleared_warning = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $serial_number.":".$variable."_high_warning", set_by => $THIS_FILE}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cleared_warning => $cleared_warning }}); |
|
|
|
$cleared = 1; |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0034"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
cleared => $cleared, |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
$temperature_state = "warning"; |
|
$temperature_is = "high"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
temperature_state => $temperature_state, |
|
temperature_is => $temperature_is, |
|
}}); |
|
} |
|
elsif ($jumped > $jump) |
|
{ |
|
# The temperature dropped a |
|
# large amount. |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_note_0035"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Record this for later processing into the |
|
# 'temperature' table. |
|
my $sensor_host_key = "controller:$serial_number"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sensor_host_key => $sensor_host_key }}); |
|
|
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c} = $new_variable_value; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; |
|
$anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_value_c" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_value_c}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_state" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, |
|
"new::temperature::${variable}::${sensor_host_key}::temperature_is" => $anvil->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, |
|
}}); |
|
} |
|
|
|
### TODO: Check to see if the new state of certain key |
|
### variables are worthy of setting a health weight. |
|
### We can't check just on changes. |
|
|
|
# Now actually generate an alert and save the changes if something |
|
# changed. |
|
if (($new_variable_value ne $old_variable_value)) |
|
{ |
|
# Changed! If the old value was 'VANISHED', then a |
|
# sensor or variable returned. Otherwise, for now, we |
|
# treat everything as 'warning' and step down |
|
# explicitely anything not of concern that proves |
|
# noisey later (better safe than sorry). |
|
|
|
# The 'Safe ID' seems to change frequently, so we |
|
# drop this to an 'info' level alert. |
|
if ($variable eq "safe_id") |
|
{ |
|
$alert_level = "info"; |
|
$message_key = "scan_storcli_note_0070"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
|
|
# If it is a temperature, we may want to make some |
|
# changes to the alert level/message. |
|
if ($type ne "temperature") |
|
{ |
|
if ($old_variable_value eq "VANISHED") |
|
{ |
|
$message_key = "scan_storcli_warning_0006"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); |
|
} |
|
|
|
# Check for some important issues |
|
if ($variable =~ /memory_correctable_errors/) |
|
{ |
|
$alert_level = "warning"; |
|
$message_key = "scan_storcli_warning_0046"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($variable =~ /memory_uncorrectable_errors/) |
|
{ |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_warning_0047"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
elsif ($variable =~ /controller_status/) |
|
{ |
|
$alert_level = "critical"; |
|
$message_key = "scan_storcli_warning_0048"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
alert_level => $alert_level, |
|
message_key => $message_key, |
|
}}); |
|
} |
|
# There more of interest... See: SELECT a.host_name, b.scan_storcli_controller_serial_number AS sn, b.scan_storcli_controller_model, c.scan_storcli_variable_name AS variable, c.scan_storcli_variable_value AS value, c.scan_storcli_variable_is_temperature AS temp, c.modified_date FROM hosts a, scan_storcli_controllers b, scan_storcli_variables c WHERE a.host_uuid = b.scan_storcli_controller_host_uuid AND b.scan_storcli_controller_uuid = c.scan_storcli_variable_source_uuid AND a.host_name = 'an-a07n01.alteeve.com'; |
|
} |
|
|
|
# Send an alert telling the user that we've found a new controller. |
|
my $variables = { |
|
serial_number => $serial_number, |
|
name => $variable, |
|
old_value => $old_variable_value ? $old_variable_value : "--", |
|
new_value => $new_variable_value, |
|
high_critical_temperature => $high_critical, |
|
high_warning_temperature => $high_warning, |
|
low_critical_temperature => $low_critical, |
|
low_warning_temperature => $low_warning, |
|
jump => $jump, |
|
}; |
|
my $log_level = (($alert_level eq "warning") or ($alert_level eq "critical")) ? 1 : 2; |
|
my $alert_header = $main_table_changed ? 0 : 1; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => $message_key, variables => $variables}); |
|
$anvil->Alert->register({ |
|
clear_alert => $cleared, |
|
alert_level => $alert_level, |
|
message => $message_key, |
|
variables => $variables, |
|
show_header => $alert_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = ".$anvil->Database->quote($new_variable_value).", |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
else |
|
{ |
|
# New variable, record it. This is a 'warning' level as |
|
# variables aren't expected to spawn into existence. |
|
my $variables = { |
|
serial_number => $serial_number, |
|
name => $variable, |
|
value => $new_variable_value, |
|
}; |
|
my $alert_header = $main_table_changed ? 0 : 1; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0004", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0004", |
|
variables => $variables, |
|
show_header => $alert_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# INSERT |
|
my $query = " |
|
INSERT INTO |
|
scan_storcli_variables |
|
( |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_host_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value, |
|
modified_date |
|
) VALUES ( |
|
".$anvil->Database->quote($anvil->Get->uuid()).", |
|
".$anvil->Database->quote($anvil->Get->host_uuid).", |
|
'scan_storcli_controllers', |
|
".$anvil->Database->quote($controller_uuid).", |
|
".$anvil->Database->quote($temperature).", |
|
".$anvil->Database->quote($variable).", |
|
".$anvil->Database->quote($new_variable_value).", |
|
".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
);"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Now look for any variables left from the previous scan that we didn't match up (and |
|
# delete) this pass. |
|
foreach my $type ("variable", "temperature") |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}}) |
|
{ |
|
# This variable has vanished |
|
my $old_variable_value = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}{scan_storcli_variable_value}; |
|
my $variable_uuid = $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}{scan_storcli_variable_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
old_variable_value => $old_variable_value, |
|
variable_uuid => $variable_uuid, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{'scan_storcli_controllers'}{source_uuid}{$controller_uuid}{$type}{$variable}; |
|
|
|
# If the old value is already 'VANISHED', ignore it. |
|
next if $old_variable_value eq "VANISHED"; |
|
|
|
### NOTE: For now, we're going to use warning level because variables |
|
### shouldn't vanish, but under an-cm, it did happen for |
|
### reasons that we never figured out. So later, we may drop |
|
### the alert level in some cases. |
|
# Still here? Alert and UPDATE. |
|
my $variables = { |
|
serial_number => $serial_number, |
|
name => $variable, |
|
}; |
|
my $alert_header = $main_table_changed ? 0 : 1; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0007", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0007", |
|
variables => $variables, |
|
show_header => $alert_header, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_variables |
|
SET |
|
scan_storcli_variable_value = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_variable_uuid = ".$anvil->Database->quote($variable_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
} |
|
} |
|
|
|
# Delete the controller from the last scan so that we can find controllers that have been |
|
# removed. |
|
if (exists $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}) |
|
{ |
|
delete $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}; |
|
} |
|
} |
|
|
|
# See if any controllers vanished. |
|
foreach my $controller_uuid (keys %{$anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}}) |
|
{ |
|
# Controller vanished! |
|
my $old_serial_number = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_serial_number}; |
|
my $old_model = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_model}; |
|
my $old_alarm_state = $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}{scan_storcli_controller_alarm_state}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
controller_uuid => $controller_uuid, |
|
old_serial_number => $old_serial_number, |
|
old_model => $old_model, |
|
old_alarm_state => $old_alarm_state, |
|
}}); |
|
|
|
# Delete it so that we know it has been processed. |
|
delete $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$controller_uuid}; |
|
|
|
# If the old alarm state is already 'VANISHED', ignore it. |
|
next if $old_alarm_state eq "VANISHED"; |
|
|
|
# Still here? Alert and UPDATE. |
|
### NOTE: For now, we're going to use warning level because controllers should never vanish |
|
### unless one failed. If that is the case, the admin already knows, but this will let |
|
### other notification targets know that the change has happened. |
|
my $variables = { |
|
serial_number => $old_serial_number, |
|
model => $old_model, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0008", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
message => "scan_storcli_warning_0008", |
|
variables => $variables, |
|
show_header => 1, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
my $query = " |
|
UPDATE |
|
scan_storcli_controllers |
|
SET |
|
scan_storcli_controller_alarm_state = 'VANISHED', |
|
modified_date = ".$anvil->Database->quote($anvil->data->{sys}{database}{timestamp})." |
|
WHERE |
|
scan_storcli_controller_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
AND |
|
scan_storcli_controller_uuid = ".$anvil->Database->quote($controller_uuid)." |
|
;"; |
|
# Now record the query in the array |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
push @{$anvil->data->{'scan-storcli'}{queries}}, $query; |
|
} |
|
|
|
# Now commit the changes. |
|
$anvil->Database->write({query => $anvil->data->{'scan-storcli'}{queries}, source => $THIS_FILE, line => __LINE__}); |
|
$anvil->data->{'scan-storcli'}{queries} = []; |
|
|
|
return(0); |
|
} |
|
|
|
# In some weird (and so far unreproducable) case, a controller will get recorded twice. If this happens, the |
|
# system will think it keeps finding and losing controllers. So this check purges duplicates. |
|
sub clear_duplicate_controllers |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Get a list of controllers on this host and count them by their serial numbers. |
|
my $query = " |
|
SELECT |
|
scan_storcli_controller_uuid, |
|
scan_storcli_controller_serial_number, |
|
scan_storcli_controller_alarm_state |
|
FROM |
|
scan_storcli_controllers |
|
WHERE |
|
scan_storcli_controller_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
if ($count > 1) |
|
{ |
|
### NOTE: This works a little differently from originally intended, but it actually works |
|
### better. This should track 'uuid::serial_number' as the UUIDs are unique, the serial |
|
### numbers aren't. As it is now, only the first seen UUID is deleted. In most cases, |
|
### there are only two entries, so this deletes one and leaves the other, so everything |
|
### isn't discovered again new. When we re-do this for M3, swap the logic but skip the |
|
### most recently updated one. |
|
# We'll loop through and track controllers by their serial numbers. If any controller serial |
|
# number is seen 2 or more times, it will be purged and re-added on the next scan. |
|
my $duplicate_controllers = {}; |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_controller_uuid = $row->[0]; |
|
my $scan_storcli_controller_serial_number = $row->[1]; |
|
my $scan_storcli_controller_alarm_state = $row->[2]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_controller_uuid => $scan_storcli_controller_uuid, |
|
scan_storcli_controller_serial_number => $scan_storcli_controller_serial_number, |
|
scan_storcli_controller_alarm_state => $scan_storcli_controller_alarm_state, |
|
}}); |
|
|
|
# Add this to the controllers we know about |
|
if (not exists $duplicate_controllers->{$scan_storcli_controller_serial_number}) |
|
{ |
|
$duplicate_controllers->{$scan_storcli_controller_serial_number}{count} = 1; |
|
$duplicate_controllers->{$scan_storcli_controller_serial_number}{controller_uuid} = $scan_storcli_controller_uuid; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_controllers->${scan_storcli_controller_serial_number}::count" => $duplicate_controllers->{$scan_storcli_controller_serial_number}{count}, |
|
"duplicate_controllers->${scan_storcli_controller_serial_number}::controller_uuid" => $duplicate_controllers->{$scan_storcli_controller_serial_number}{controller_uuid}, |
|
}}); |
|
} |
|
else |
|
{ |
|
$duplicate_controllers->{$scan_storcli_controller_serial_number}{count}++; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"duplicate_controllers->${scan_storcli_controller_serial_number}" => $duplicate_controllers->{$scan_storcli_controller_serial_number}, |
|
}}); |
|
} |
|
} |
|
|
|
foreach my $scan_storcli_controller_serial_number (sort {$a cmp $b} keys %{$duplicate_controllers}) |
|
{ |
|
my $count = $duplicate_controllers->{$scan_storcli_controller_serial_number}{count}; |
|
my $scan_storcli_controller_uuid = $duplicate_controllers->{$scan_storcli_controller_serial_number}{controller_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_controller_serial_number => $scan_storcli_controller_serial_number, |
|
count => $count, |
|
scan_storcli_controller_uuid => $scan_storcli_controller_uuid, |
|
}}); |
|
|
|
if ($count > 1) |
|
{ |
|
# Duplicate. Send an alert and then purge. |
|
my $variables = { |
|
serial_number => $scan_storcli_controller_serial_number, |
|
count => $count, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_warning_0052", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "warning", |
|
show_header => 1, |
|
message => "scan_storcli_warning_0052", |
|
variables => $variables, |
|
sort_position => $anvil->data->{'scan-storcli'}{alert_sort}++, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# We'll commit this batch of queries per controller |
|
my $queries = []; |
|
|
|
# Delete all physical drives |
|
my $query = "SELECT scan_storcli_physical_drive_uuid FROM scan_storcli_physical_drives WHERE scan_storcli_physical_drive_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_physical_drive_uuid = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_physical_drive_uuid => $scan_storcli_physical_drive_uuid }}); |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_physical_drives' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_physical_drives' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_physical_drives WHERE scan_storcli_physical_drive_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_physical_drives WHERE scan_storcli_physical_drive_uuid = ".$anvil->Database->quote($scan_storcli_physical_drive_uuid).";"; |
|
} |
|
|
|
# The scan_storcli_drive_groups are linked to the virtual drives, so we need to |
|
# pull up all the VDs on this controller and use their UUIDs to delete |
|
# down-stream DGs |
|
$query = "SELECT scan_storcli_virtual_drive_uuid FROM scan_storcli_virtual_drives WHERE scan_storcli_virtual_drive_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_virtual_drive_uuid = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_virtual_drive_uuid => $scan_storcli_virtual_drive_uuid }}); |
|
|
|
# Select the DGs under this VD. |
|
my $query = "SELECT scan_storcli_drive_group_uuid FROM scan_storcli_drive_groups WHERE scan_storcli_drive_group_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).";"; |
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_drive_group_uuid = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_drive_group_uuid => $scan_storcli_drive_group_uuid }}); |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_drive_groups' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_drive_groups' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_drive_groups WHERE scan_storcli_drive_group_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_drive_groups WHERE scan_storcli_drive_group_uuid = ".$anvil->Database->quote($scan_storcli_drive_group_uuid).";"; |
|
} |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_virtual_drives' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_virtual_drives' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_virtual_drives WHERE scan_storcli_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_virtual_drives WHERE scan_storcli_virtual_drive_uuid = ".$anvil->Database->quote($scan_storcli_virtual_drive_uuid).";"; |
|
} |
|
|
|
# Delete all cachevaults (FBUs) |
|
$query = "SELECT scan_storcli_cachevault_uuid FROM scan_storcli_cachevaults WHERE scan_storcli_cachevault_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_cachevault_uuid = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_cachevault_uuid => $scan_storcli_cachevault_uuid }}); |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_cachevaults' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_cachevault_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_cachevaults' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_cachevault_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_cachevaults WHERE scan_storcli_cachevault_uuid = ".$anvil->Database->quote($scan_storcli_cachevault_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_cachevaults WHERE scan_storcli_cachevault_uuid = ".$anvil->Database->quote($scan_storcli_cachevault_uuid).";"; |
|
} |
|
|
|
# Delete all BBUs |
|
$query = "SELECT scan_storcli_bbu_uuid FROM scan_storcli_bbus WHERE scan_storcli_bbu_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
$count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_bbu_uuid = $row->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_storcli_bbu_uuid => $scan_storcli_bbu_uuid }}); |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_bbus' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_bbu_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_bbus' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_bbu_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_bbus WHERE scan_storcli_bbu_uuid = ".$anvil->Database->quote($scan_storcli_bbu_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_bbus WHERE scan_storcli_bbu_uuid = ".$anvil->Database->quote($scan_storcli_bbu_uuid).";"; |
|
} |
|
|
|
# Finally, delete the controller. |
|
push @{$queries}, "DELETE FROM history.scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_controllers' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_variables WHERE scan_storcli_variable_source_table = 'scan_storcli_controllers' AND scan_storcli_variable_source_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
|
|
push @{$queries}, "DELETE FROM history.scan_storcli_controllers WHERE scan_storcli_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
push @{$queries}, "DELETE FROM scan_storcli_controllers WHERE scan_storcli_controller_uuid = ".$anvil->Database->quote($scan_storcli_controller_uuid).";"; |
|
|
|
# Commit. Because it's an array, it'll be done as a single transaction |
|
foreach my $query (@{$queries}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
} |
|
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This reads in the last scan's data. |
|
sub read_last_scan |
|
{ |
|
my ($anvil) = @_; |
|
|
|
clear_duplicate_controllers($anvil); |
|
|
|
# Read in the controller(s) |
|
my $query = " |
|
SELECT |
|
scan_storcli_controller_uuid, |
|
scan_storcli_controller_serial_number, |
|
scan_storcli_controller_model, |
|
scan_storcli_controller_alarm_state, |
|
scan_storcli_controller_cache_size |
|
FROM |
|
scan_storcli_controllers |
|
WHERE |
|
scan_storcli_controller_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid).";"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); |
|
my $count = @{$results}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_controller_uuid = $row->[0]; |
|
my $scan_storcli_controller_serial_number = $row->[1]; |
|
my $scan_storcli_controller_model = $row->[2]; |
|
my $scan_storcli_controller_alarm_state = $row->[3]; |
|
my $scan_storcli_controller_cache_size = $row->[4]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_controller_uuid => $scan_storcli_controller_uuid, |
|
scan_storcli_controller_serial_number => $scan_storcli_controller_serial_number, |
|
scan_storcli_controller_model => $scan_storcli_controller_model, |
|
scan_storcli_controller_alarm_state => $scan_storcli_controller_alarm_state, |
|
scan_storcli_controller_cache_size => $scan_storcli_controller_cache_size, |
|
}}); |
|
|
|
# Store the information about this controllers |
|
$anvil->data->{'scan-storcli'}{controllers}{by_serial}{$scan_storcli_controller_serial_number} = $scan_storcli_controller_uuid; |
|
$anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$scan_storcli_controller_uuid} = $scan_storcli_controller_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::controllers::by_serial::${scan_storcli_controller_serial_number}" => $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$scan_storcli_controller_serial_number}, |
|
"scan-storcli::controllers::by_uuid::${scan_storcli_controller_uuid}" => $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$scan_storcli_controller_uuid}, |
|
}}); |
|
|
|
$anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$scan_storcli_controller_uuid} = { |
|
scan_storcli_controller_serial_number => $scan_storcli_controller_serial_number, |
|
scan_storcli_controller_model => $scan_storcli_controller_model, |
|
scan_storcli_controller_alarm_state => $scan_storcli_controller_alarm_state, |
|
scan_storcli_controller_cache_size => $scan_storcli_controller_cache_size, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::controllers::by_serial::$scan_storcli_controller_serial_number" => $anvil->data->{'scan-storcli'}{controllers}{by_serial}{$scan_storcli_controller_serial_number}, |
|
"scan-storcli::controllers::by_uuid::$scan_storcli_controller_uuid" => $anvil->data->{'scan-storcli'}{controllers}{by_uuid}{$scan_storcli_controller_uuid}, |
|
"sql::scan_storcli_controllers::scan_storcli_controller_uuid::${scan_storcli_controller_uuid}::scan_storcli_controller_serial_number" => $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$scan_storcli_controller_uuid}{scan_storcli_controller_serial_number}, |
|
"sql::scan_storcli_controllers::scan_storcli_controller_uuid::${scan_storcli_controller_uuid}::scan_storcli_controller_model" => $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$scan_storcli_controller_uuid}{scan_storcli_controller_model}, |
|
"sql::scan_storcli_controllers::scan_storcli_controller_uuid::${scan_storcli_controller_uuid}::scan_storcli_controller_alarm_state" => $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$scan_storcli_controller_uuid}{scan_storcli_controller_alarm_state}, |
|
"sql::scan_storcli_controllers::scan_storcli_controller_uuid::${scan_storcli_controller_uuid}::scan_storcli_controller_cache_size" => $anvil->data->{sql}{scan_storcli_controllers}{scan_storcli_controller_uuid}{$scan_storcli_controller_uuid}{scan_storcli_controller_cache_size}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# Now load the cachevault data |
|
$query = " |
|
SELECT |
|
scan_storcli_cachevault_uuid, |
|
scan_storcli_cachevault_controller_uuid, |
|
scan_storcli_cachevault_serial_number, |
|
scan_storcli_cachevault_state, |
|
scan_storcli_cachevault_design_capacity, |
|
scan_storcli_cachevault_replacement_needed, |
|
scan_storcli_cachevault_type, |
|
scan_storcli_cachevault_model, |
|
scan_storcli_cachevault_manufacture_date |
|
FROM |
|
scan_storcli_cachevaults |
|
WHERE |
|
scan_storcli_cachevault_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_cachevault_uuid = $row->[0]; |
|
my $scan_storcli_cachevault_controller_uuid = $row->[1]; |
|
my $scan_storcli_cachevault_serial_number = $row->[2]; |
|
my $scan_storcli_cachevault_state = defined $row->[3] ? $row->[3] : ""; |
|
my $scan_storcli_cachevault_design_capacity = defined $row->[4] ? $row->[4] : ""; |
|
my $scan_storcli_cachevault_replacement_needed = defined $row->[5] ? $row->[5] : ""; |
|
my $scan_storcli_cachevault_type = defined $row->[6] ? $row->[6] : ""; |
|
my $scan_storcli_cachevault_model = defined $row->[7] ? $row->[7] : ""; |
|
my $scan_storcli_cachevault_manufacture_date = defined $row->[8] ? $row->[8] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_cachevault_uuid => $scan_storcli_cachevault_uuid, |
|
scan_storcli_cachevault_controller_uuid => $scan_storcli_cachevault_controller_uuid, |
|
scan_storcli_cachevault_serial_number => $scan_storcli_cachevault_serial_number, |
|
scan_storcli_cachevault_state => $scan_storcli_cachevault_state, |
|
scan_storcli_cachevault_design_capacity => $scan_storcli_cachevault_design_capacity, |
|
scan_storcli_cachevault_replacement_needed => $scan_storcli_cachevault_replacement_needed, |
|
scan_storcli_cachevault_type => $scan_storcli_cachevault_type, |
|
scan_storcli_cachevault_model => $scan_storcli_cachevault_model, |
|
scan_storcli_cachevault_manufacture_date => $scan_storcli_cachevault_manufacture_date, |
|
}}); |
|
|
|
# Store the information about this cachevault |
|
$anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$scan_storcli_cachevault_serial_number} = $scan_storcli_cachevault_uuid; |
|
$anvil->data->{'scan-storcli'}{cachevaults}{by_uuid}{$scan_storcli_cachevault_uuid} = $scan_storcli_cachevault_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::cachevaults::by_serial::${scan_storcli_cachevault_serial_number}" => $anvil->data->{'scan-storcli'}{cachevaults}{by_serial}{$scan_storcli_cachevault_serial_number}, |
|
"scan-storcli::cachevaults::by_uuid::${scan_storcli_cachevault_uuid}" => $anvil->data->{'scan-storcli'}{cachevaults}{by_uuid}{$scan_storcli_cachevault_uuid}, |
|
}}); |
|
|
|
$anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid} = { |
|
scan_storcli_cachevault_controller_uuid => $scan_storcli_cachevault_controller_uuid, |
|
scan_storcli_cachevault_serial_number => $scan_storcli_cachevault_serial_number, |
|
scan_storcli_cachevault_state => $scan_storcli_cachevault_state, |
|
scan_storcli_cachevault_design_capacity => $scan_storcli_cachevault_design_capacity, |
|
scan_storcli_cachevault_replacement_needed => $scan_storcli_cachevault_replacement_needed, |
|
scan_storcli_cachevault_type => $scan_storcli_cachevault_type, |
|
scan_storcli_cachevault_model => $scan_storcli_cachevault_model, |
|
scan_storcli_cachevault_manufacture_date => $scan_storcli_cachevault_manufacture_date, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_controller_uuid" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_controller_uuid}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_serial_number" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_serial_number}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_state" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_state}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_design_capacity" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_design_capacity}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_replacement_needed" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_replacement_needed}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_type" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_type}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_model" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_model}, |
|
"sql::scan_storcli_cachevaults::scan_storcli_cachevault_uuid::${scan_storcli_cachevault_uuid}::scan_storcli_cachevault_manufacture_date" => $anvil->data->{sql}{scan_storcli_cachevaults}{scan_storcli_cachevault_uuid}{$scan_storcli_cachevault_uuid}{scan_storcli_cachevault_manufacture_date}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# The BBU data... |
|
$query = " |
|
SELECT |
|
scan_storcli_bbu_uuid, |
|
scan_storcli_bbu_controller_uuid, |
|
scan_storcli_bbu_serial_number, |
|
scan_storcli_bbu_type, |
|
scan_storcli_bbu_model, |
|
scan_storcli_bbu_state, |
|
scan_storcli_bbu_manufacture_date, |
|
scan_storcli_bbu_design_capacity, |
|
scan_storcli_bbu_replacement_needed |
|
FROM |
|
scan_storcli_bbus |
|
WHERE |
|
scan_storcli_bbu_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_bbu_uuid = $row->[0]; |
|
my $scan_storcli_bbu_controller_uuid = $row->[1]; |
|
my $scan_storcli_bbu_serial_number = $row->[2]; |
|
my $scan_storcli_bbu_type = defined $row->[3] ? $row->[3] : ""; |
|
my $scan_storcli_bbu_model = defined $row->[4] ? $row->[4] : ""; |
|
my $scan_storcli_bbu_state = defined $row->[5] ? $row->[5] : ""; |
|
my $scan_storcli_bbu_manufacture_date = defined $row->[6] ? $row->[6] : ""; |
|
my $scan_storcli_bbu_design_capacity = defined $row->[7] ? $row->[7] : ""; |
|
my $scan_storcli_bbu_replacement_needed = defined $row->[8] ? $row->[8] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_bbu_uuid => $scan_storcli_bbu_uuid, |
|
scan_storcli_bbu_controller_uuid => $scan_storcli_bbu_controller_uuid, |
|
scan_storcli_bbu_serial_number => $scan_storcli_bbu_serial_number, |
|
scan_storcli_bbu_type => $scan_storcli_bbu_type, |
|
scan_storcli_bbu_model => $scan_storcli_bbu_model, |
|
scan_storcli_bbu_state => $scan_storcli_bbu_state, |
|
scan_storcli_bbu_manufacture_date => $scan_storcli_bbu_manufacture_date, |
|
scan_storcli_bbu_design_capacity => $scan_storcli_bbu_design_capacity, |
|
scan_storcli_bbu_replacement_needed => $scan_storcli_bbu_replacement_needed, |
|
}}); |
|
|
|
# Store the information about this BBU |
|
$anvil->data->{'scan-storcli'}{bbus}{by_serial}{$scan_storcli_bbu_serial_number} = $scan_storcli_bbu_uuid; |
|
$anvil->data->{'scan-storcli'}{bbus}{by_uuid}{$scan_storcli_bbu_uuid} = $scan_storcli_bbu_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::bbus::by_serial::${scan_storcli_bbu_serial_number}" => $anvil->data->{'scan-storcli'}{bbus}{by_serial}{$scan_storcli_bbu_serial_number}, |
|
"scan-storcli::bbus::by_uuid::${scan_storcli_bbu_uuid}" => $anvil->data->{'scan-storcli'}{bbus}{by_uuid}{$scan_storcli_bbu_uuid}, |
|
}}); |
|
|
|
$anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid} = { |
|
scan_storcli_bbu_controller_uuid => $scan_storcli_bbu_controller_uuid, |
|
scan_storcli_bbu_serial_number => $scan_storcli_bbu_serial_number, |
|
scan_storcli_bbu_type => $scan_storcli_bbu_type, |
|
scan_storcli_bbu_model => $scan_storcli_bbu_model, |
|
scan_storcli_bbu_state => $scan_storcli_bbu_state, |
|
scan_storcli_bbu_manufacture_date => $scan_storcli_bbu_manufacture_date, |
|
scan_storcli_bbu_design_capacity => $scan_storcli_bbu_design_capacity, |
|
scan_storcli_bbu_replacement_needed => $scan_storcli_bbu_replacement_needed, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_controller_uuid" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_controller_uuid}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_serial_number" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_serial_number}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_type" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_type}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_model" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_model}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_state" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_state}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_manufacture_date" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_manufacture_date}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_design_capacity" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_design_capacity}, |
|
"sql::scan_storcli_bbus::scan_storcli_bbu_uuid::${scan_storcli_bbu_uuid}::scan_storcli_bbu_replacement_needed" => $anvil->data->{sql}{scan_storcli_bbus}{scan_storcli_bbu_uuid}{$scan_storcli_bbu_uuid}{scan_storcli_bbu_replacement_needed}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# The virtual drives data... |
|
$query = " |
|
SELECT |
|
scan_storcli_virtual_drive_uuid, |
|
scan_storcli_virtual_drive_controller_uuid, |
|
scan_storcli_virtual_drive_id_string, |
|
scan_storcli_virtual_drive_creation_date, |
|
scan_storcli_virtual_drive_data_protection, |
|
scan_storcli_virtual_drive_disk_cache_policy, |
|
scan_storcli_virtual_drive_emulation_type, |
|
scan_storcli_virtual_drive_encryption, |
|
scan_storcli_virtual_drive_blocks, |
|
scan_storcli_virtual_drive_strip_size, |
|
scan_storcli_virtual_drive_drives_per_span, |
|
scan_storcli_virtual_drive_span_depth, |
|
scan_storcli_virtual_drive_scsi_naa_id |
|
FROM |
|
scan_storcli_virtual_drives |
|
WHERE |
|
scan_storcli_virtual_drive_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_virtual_drive_uuid = $row->[0]; |
|
my $scan_storcli_virtual_drive_controller_uuid = $row->[1]; |
|
my $scan_storcli_virtual_drive_id_string = $row->[2]; |
|
my $scan_storcli_virtual_drive_creation_date = defined $row->[3] ? $row->[3] : ""; |
|
my $scan_storcli_virtual_drive_data_protection = defined $row->[4] ? $row->[4] : ""; |
|
my $scan_storcli_virtual_drive_disk_cache_policy = defined $row->[5] ? $row->[5] : ""; |
|
my $scan_storcli_virtual_drive_emulation_type = defined $row->[6] ? $row->[6] : ""; |
|
my $scan_storcli_virtual_drive_encryption = defined $row->[7] ? $row->[7] : ""; |
|
my $scan_storcli_virtual_drive_blocks = defined $row->[8] ? $row->[8] : ""; |
|
my $scan_storcli_virtual_drive_strip_size = defined $row->[9] ? $row->[9] : ""; |
|
my $scan_storcli_virtual_drive_drives_per_span = defined $row->[10] ? $row->[10] : ""; |
|
my $scan_storcli_virtual_drive_span_depth = defined $row->[11] ? $row->[11] : ""; |
|
my $scan_storcli_virtual_drive_scsi_naa_id = defined $row->[12] ? $row->[12] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_virtual_drive_uuid => $scan_storcli_virtual_drive_uuid, |
|
scan_storcli_virtual_drive_controller_uuid => $scan_storcli_virtual_drive_controller_uuid, |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
scan_storcli_virtual_drive_creation_date => $scan_storcli_virtual_drive_creation_date, |
|
scan_storcli_virtual_drive_data_protection => $scan_storcli_virtual_drive_data_protection, |
|
scan_storcli_virtual_drive_disk_cache_policy => $scan_storcli_virtual_drive_disk_cache_policy, |
|
scan_storcli_virtual_drive_emulation_type => $scan_storcli_virtual_drive_emulation_type, |
|
scan_storcli_virtual_drive_encryption => $scan_storcli_virtual_drive_encryption, |
|
scan_storcli_virtual_drive_blocks => $scan_storcli_virtual_drive_blocks, |
|
scan_storcli_virtual_drive_strip_size => $scan_storcli_virtual_drive_strip_size, |
|
scan_storcli_virtual_drive_drives_per_span => $scan_storcli_virtual_drive_drives_per_span, |
|
scan_storcli_virtual_drive_span_depth => $scan_storcli_virtual_drive_span_depth, |
|
scan_storcli_virtual_drive_scsi_naa_id => $scan_storcli_virtual_drive_scsi_naa_id, |
|
}}); |
|
|
|
# Store the information about this virtual drive. |
|
$anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string} = $scan_storcli_virtual_drive_uuid; |
|
$anvil->data->{'scan-storcli'}{virtual_drives}{by_uuid}{$scan_storcli_virtual_drive_uuid} = $scan_storcli_virtual_drive_id_string; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::virtual_drives::by_id_string::${scan_storcli_virtual_drive_id_string}" => $anvil->data->{'scan-storcli'}{virtual_drives}{by_id_string}{$scan_storcli_virtual_drive_id_string}, |
|
"scan-storcli::virtual_drives::by_uuid::${scan_storcli_virtual_drive_uuid}" => $anvil->data->{'scan-storcli'}{virtual_drives}{by_uuid}{$scan_storcli_virtual_drive_uuid}, |
|
}}); |
|
|
|
# Store the drive group data. (Drive groups have no SN) |
|
$anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid} = { |
|
scan_storcli_virtual_drive_controller_uuid => $scan_storcli_virtual_drive_controller_uuid, |
|
scan_storcli_virtual_drive_id_string => $scan_storcli_virtual_drive_id_string, |
|
scan_storcli_virtual_drive_creation_date => $scan_storcli_virtual_drive_creation_date, |
|
scan_storcli_virtual_drive_data_protection => $scan_storcli_virtual_drive_data_protection, |
|
scan_storcli_virtual_drive_disk_cache_policy => $scan_storcli_virtual_drive_disk_cache_policy, |
|
scan_storcli_virtual_drive_emulation_type => $scan_storcli_virtual_drive_emulation_type, |
|
scan_storcli_virtual_drive_encryption => $scan_storcli_virtual_drive_encryption, |
|
scan_storcli_virtual_drive_blocks => $scan_storcli_virtual_drive_blocks, |
|
scan_storcli_virtual_drive_strip_size => $scan_storcli_virtual_drive_strip_size, |
|
scan_storcli_virtual_drive_drives_per_span => $scan_storcli_virtual_drive_drives_per_span, |
|
scan_storcli_virtual_drive_span_depth => $scan_storcli_virtual_drive_span_depth, |
|
scan_storcli_virtual_drive_scsi_naa_id => $scan_storcli_virtual_drive_scsi_naa_id, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_controller_uuid" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_controller_uuid}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_id_string" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_id_string}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_creation_date" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_creation_date}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_data_protection" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_data_protection}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_disk_cache_policy" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_disk_cache_policy}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_emulation_type" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_emulation_type}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_encryption" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_encryption}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_blocks" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_blocks}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_strip_size" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_strip_size}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_drives_per_span" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_drives_per_span}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_span_depth" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_span_depth}, |
|
"sql::scan_storcli_virtual_drives::scan_storcli_virtual_drive_uuid::${scan_storcli_virtual_drive_uuid}::scan_storcli_virtual_drive_scsi_naa_id" => $anvil->data->{sql}{scan_storcli_virtual_drives}{scan_storcli_virtual_drive_uuid}{$scan_storcli_virtual_drive_uuid}{scan_storcli_virtual_drive_scsi_naa_id}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# The drive group data... |
|
$query = " |
|
SELECT |
|
scan_storcli_drive_group_uuid, |
|
scan_storcli_drive_group_virtual_drive_uuid, |
|
scan_storcli_drive_group_id_string, |
|
scan_storcli_drive_group_access, |
|
scan_storcli_drive_group_array_size, |
|
scan_storcli_drive_group_array_state, |
|
scan_storcli_drive_group_cache, |
|
scan_storcli_drive_group_cachecade, |
|
scan_storcli_drive_group_consistent, |
|
scan_storcli_drive_group_disk_cache, |
|
scan_storcli_drive_group_raid_type, |
|
scan_storcli_drive_group_read_cache, |
|
scan_storcli_drive_group_scheduled_cc, |
|
scan_storcli_drive_group_write_cache |
|
FROM |
|
scan_storcli_drive_groups |
|
WHERE |
|
scan_storcli_drive_group_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_drive_group_uuid = $row->[0]; |
|
my $scan_storcli_drive_group_virtual_drive_uuid = $row->[1]; |
|
my $scan_storcli_drive_group_id_string = $row->[2]; |
|
my $scan_storcli_drive_group_access = defined $row->[3] ? $row->[3] : ""; |
|
my $scan_storcli_drive_group_array_size = defined $row->[4] ? $row->[4] : ""; |
|
my $scan_storcli_drive_group_array_state = defined $row->[5] ? $row->[5] : ""; |
|
my $scan_storcli_drive_group_cache = defined $row->[6] ? $row->[6] : ""; |
|
my $scan_storcli_drive_group_cachecade = defined $row->[7] ? $row->[7] : ""; |
|
my $scan_storcli_drive_group_consistent = defined $row->[8] ? $row->[8] : ""; |
|
my $scan_storcli_drive_group_disk_cache = defined $row->[9] ? $row->[9] : ""; |
|
my $scan_storcli_drive_group_raid_type = defined $row->[10] ? $row->[10] : ""; |
|
my $scan_storcli_drive_group_read_cache = defined $row->[11] ? $row->[11] : ""; |
|
my $scan_storcli_drive_group_scheduled_cc = defined $row->[12] ? $row->[12] : ""; |
|
my $scan_storcli_drive_group_write_cache = defined $row->[13] ? $row->[13] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_drive_group_uuid => $scan_storcli_drive_group_uuid, |
|
scan_storcli_drive_group_virtual_drive_uuid => $scan_storcli_drive_group_virtual_drive_uuid, |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
scan_storcli_drive_group_access => $scan_storcli_drive_group_access, |
|
scan_storcli_drive_group_array_size => $scan_storcli_drive_group_array_size, |
|
scan_storcli_drive_group_array_state => $scan_storcli_drive_group_array_state, |
|
scan_storcli_drive_group_cache => $scan_storcli_drive_group_cache, |
|
scan_storcli_drive_group_cachecade => $scan_storcli_drive_group_cachecade, |
|
scan_storcli_drive_group_consistent => $scan_storcli_drive_group_consistent, |
|
scan_storcli_drive_group_disk_cache => $scan_storcli_drive_group_disk_cache, |
|
scan_storcli_drive_group_raid_type => $scan_storcli_drive_group_raid_type, |
|
scan_storcli_drive_group_read_cache => $scan_storcli_drive_group_read_cache, |
|
scan_storcli_drive_group_scheduled_cc => $scan_storcli_drive_group_scheduled_cc, |
|
scan_storcli_drive_group_write_cache => $scan_storcli_drive_group_write_cache, |
|
}}); |
|
|
|
# Store the information about this virtual drive. |
|
$anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string} = $scan_storcli_drive_group_uuid; |
|
$anvil->data->{'scan-storcli'}{drive_groups}{by_uuid}{$scan_storcli_drive_group_uuid} = $scan_storcli_drive_group_id_string; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::drive_groups::by_id_string::${scan_storcli_drive_group_id_string}" => $anvil->data->{'scan-storcli'}{drive_groups}{by_id_string}{$scan_storcli_drive_group_id_string}, |
|
"scan-storcli::drive_groups::by_uuid::${scan_storcli_drive_group_uuid}" => $anvil->data->{'scan-storcli'}{drive_groups}{by_uuid}{$scan_storcli_drive_group_uuid}, |
|
}}); |
|
|
|
# Store the drive group data. (Drive groups have no SN) |
|
$anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid} = { |
|
scan_storcli_drive_group_virtual_drive_uuid => $scan_storcli_drive_group_virtual_drive_uuid, |
|
scan_storcli_drive_group_id_string => $scan_storcli_drive_group_id_string, |
|
scan_storcli_drive_group_access => $scan_storcli_drive_group_access, |
|
scan_storcli_drive_group_array_size => $scan_storcli_drive_group_array_size, |
|
scan_storcli_drive_group_array_state => $scan_storcli_drive_group_array_state, |
|
scan_storcli_drive_group_cache => $scan_storcli_drive_group_cache, |
|
scan_storcli_drive_group_cachecade => $scan_storcli_drive_group_cachecade, |
|
scan_storcli_drive_group_consistent => $scan_storcli_drive_group_consistent, |
|
scan_storcli_drive_group_disk_cache => $scan_storcli_drive_group_disk_cache, |
|
scan_storcli_drive_group_raid_type => $scan_storcli_drive_group_raid_type, |
|
scan_storcli_drive_group_read_cache => $scan_storcli_drive_group_read_cache, |
|
scan_storcli_drive_group_scheduled_cc => $scan_storcli_drive_group_scheduled_cc, |
|
scan_storcli_drive_group_write_cache => $scan_storcli_drive_group_write_cache, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_virtual_drive_uuid" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_virtual_drive_uuid}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_id_string" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_id_string}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_access" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_access}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_array_size" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_array_size}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_array_state" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_array_state}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_cache" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_cache}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_cachecade" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_cachecade}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_consistent" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_consistent}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_disk_cache" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_disk_cache}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_raid_type" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_raid_type}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_read_cache" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_read_cache}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_scheduled_cc" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_scheduled_cc}, |
|
"sql::scan_storcli_drive_groups::scan_storcli_drive_group_uuid::${scan_storcli_drive_group_uuid}::scan_storcli_drive_group_write_cache" => $anvil->data->{sql}{scan_storcli_drive_groups}{scan_storcli_drive_group_uuid}{$scan_storcli_drive_group_uuid}{scan_storcli_drive_group_write_cache}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# And now, the physical drives. |
|
$query = " |
|
SELECT |
|
scan_storcli_physical_drive_uuid, |
|
scan_storcli_physical_drive_controller_uuid, |
|
scan_storcli_physical_drive_virtual_drive, |
|
scan_storcli_physical_drive_drive_group, |
|
scan_storcli_physical_drive_enclosure_id, |
|
scan_storcli_physical_drive_slot_number, |
|
scan_storcli_physical_drive_serial_number, |
|
scan_storcli_physical_drive_size, |
|
scan_storcli_physical_drive_sector_size, |
|
scan_storcli_physical_drive_vendor, |
|
scan_storcli_physical_drive_model, |
|
scan_storcli_physical_drive_self_encrypting_drive |
|
FROM |
|
scan_storcli_physical_drives |
|
WHERE |
|
scan_storcli_physical_drive_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_physical_drive_uuid = $row->[0]; |
|
my $scan_storcli_physical_drive_controller_uuid = $row->[1]; |
|
my $scan_storcli_physical_drive_virtual_drive = defined $row->[2] ? $row->[2] : ""; |
|
my $scan_storcli_physical_drive_drive_group = defined $row->[3] ? $row->[3] : ""; |
|
my $scan_storcli_physical_drive_enclosure_id = defined $row->[4] ? $row->[4] : ""; |
|
my $scan_storcli_physical_drive_slot_number = defined $row->[5] ? $row->[5] : ""; |
|
my $scan_storcli_physical_drive_serial_number = defined $row->[6] ? $row->[6] : ""; |
|
my $scan_storcli_physical_drive_size = defined $row->[7] ? $row->[7] : ""; |
|
my $scan_storcli_physical_drive_sector_size = defined $row->[8] ? $row->[8] : ""; |
|
my $scan_storcli_physical_drive_vendor = defined $row->[9] ? $row->[9] : ""; |
|
my $scan_storcli_physical_drive_model = defined $row->[10] ? $row->[10] : ""; |
|
my $scan_storcli_physical_drive_self_encrypting_drive = defined $row->[11] ? $row->[11] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_physical_drive_uuid => $scan_storcli_physical_drive_uuid, |
|
scan_storcli_physical_drive_controller_uuid => $scan_storcli_physical_drive_controller_uuid, |
|
scan_storcli_physical_drive_virtual_drive => $scan_storcli_physical_drive_virtual_drive, |
|
scan_storcli_physical_drive_drive_group => $scan_storcli_physical_drive_drive_group, |
|
scan_storcli_physical_drive_enclosure_id => $scan_storcli_physical_drive_enclosure_id, |
|
scan_storcli_physical_drive_slot_number => $scan_storcli_physical_drive_slot_number, |
|
scan_storcli_physical_drive_serial_number => $scan_storcli_physical_drive_serial_number, |
|
scan_storcli_physical_drive_size => $scan_storcli_physical_drive_size, |
|
scan_storcli_physical_drive_sector_size => $scan_storcli_physical_drive_sector_size, |
|
scan_storcli_physical_drive_vendor => $scan_storcli_physical_drive_vendor, |
|
scan_storcli_physical_drive_model => $scan_storcli_physical_drive_model, |
|
scan_storcli_physical_drive_self_encrypting_drive => $scan_storcli_physical_drive_self_encrypting_drive, |
|
}}); |
|
|
|
# Make it so that we can look up the serial number from the drive's UUID and vice versa |
|
$anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number} = $scan_storcli_physical_drive_uuid; |
|
$anvil->data->{'scan-storcli'}{physical_drives}{by_uuid}{$scan_storcli_physical_drive_uuid} = $scan_storcli_physical_drive_serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"scan-storcli::physical_drives::by_serial::${scan_storcli_physical_drive_serial_number}" => $anvil->data->{'scan-storcli'}{physical_drives}{by_serial}{$scan_storcli_physical_drive_serial_number}, |
|
"scan-storcli::physical_drives::by_uuid::${scan_storcli_physical_drive_uuid}" => $anvil->data->{'scan-storcli'}{physical_drives}{by_uuid}{$scan_storcli_physical_drive_uuid}, |
|
}}); |
|
|
|
# Store the information about this physical drive |
|
$anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid} = { |
|
scan_storcli_physical_drive_controller_uuid => $scan_storcli_physical_drive_controller_uuid, |
|
scan_storcli_physical_drive_virtual_drive => $scan_storcli_physical_drive_virtual_drive, |
|
scan_storcli_physical_drive_drive_group => $scan_storcli_physical_drive_drive_group, |
|
scan_storcli_physical_drive_enclosure_id => $scan_storcli_physical_drive_enclosure_id, |
|
scan_storcli_physical_drive_slot_number => $scan_storcli_physical_drive_slot_number, |
|
scan_storcli_physical_drive_serial_number => $scan_storcli_physical_drive_serial_number, |
|
scan_storcli_physical_drive_size => $scan_storcli_physical_drive_size, |
|
scan_storcli_physical_drive_sector_size => $scan_storcli_physical_drive_sector_size, |
|
scan_storcli_physical_drive_vendor => $scan_storcli_physical_drive_vendor, |
|
scan_storcli_physical_drive_model => $scan_storcli_physical_drive_model, |
|
scan_storcli_physical_drive_self_encrypting_drive => $scan_storcli_physical_drive_self_encrypting_drive, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_controller_uuid" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_controller_uuid}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_virtual_drive" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_virtual_drive}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_drive_group" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_drive_group}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_enclosure_id" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_enclosure_id}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_slot_number" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_slot_number}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_serial_number" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_serial_number}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_size" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_size}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_sector_size" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_sector_size}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_vendor" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_vendor}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_model" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_model}, |
|
"sql::scan_storcli_physical_drives::scan_storcli_physical_drive_uuid::${scan_storcli_physical_drive_uuid}::scan_storcli_physical_drive_self_encrypting_drive" => $anvil->data->{sql}{scan_storcli_physical_drives}{scan_storcli_physical_drive_uuid}{$scan_storcli_physical_drive_uuid}{scan_storcli_physical_drive_self_encrypting_drive}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# Lastly, the variables. |
|
$query = " |
|
SELECT |
|
scan_storcli_variable_uuid, |
|
scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name, |
|
scan_storcli_variable_value |
|
FROM |
|
scan_storcli_variables |
|
WHERE |
|
scan_storcli_variable_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." |
|
;"; |
|
$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 => 2, list => { |
|
results => $results, |
|
count => $count, |
|
}}); |
|
foreach my $row (@{$results}) |
|
{ |
|
my $scan_storcli_variable_uuid = $row->[0]; |
|
my $scan_storcli_variable_source_table = $row->[1]; |
|
my $scan_storcli_variable_source_uuid = $row->[2]; |
|
my $scan_storcli_variable_is_temperature = $row->[3]; |
|
my $scan_storcli_variable_name = $row->[4]; |
|
my $scan_storcli_variable_value = defined $row->[5] ? $row->[5] : ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
scan_storcli_variable_uuid => $scan_storcli_variable_uuid, |
|
scan_storcli_variable_source_table => $scan_storcli_variable_source_table, |
|
scan_storcli_variable_source_uuid => $scan_storcli_variable_source_uuid, |
|
scan_storcli_variable_is_temperature => $scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_name => $scan_storcli_variable_name, |
|
scan_storcli_variable_value => $scan_storcli_variable_value, |
|
}}); |
|
|
|
# We store these differently for easier reference. |
|
my $type = $scan_storcli_variable_is_temperature eq "1" ? "temperature" : "variable"; |
|
$anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{$scan_storcli_variable_source_table}{source_uuid}{$scan_storcli_variable_source_uuid}{$type}{$scan_storcli_variable_name} = { |
|
scan_storcli_variable_uuid => $scan_storcli_variable_uuid, |
|
scan_storcli_variable_is_temperature => $scan_storcli_variable_is_temperature, |
|
scan_storcli_variable_value => $scan_storcli_variable_value, |
|
}; |
|
|
|
# Entries are so long that we log the one per variable. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_variables::scan_storcli_variable_uuid::source_table::${scan_storcli_variable_source_table}::source_uuid::${scan_storcli_variable_source_uuid}::${type}::${scan_storcli_variable_name}::scan_storcli_variable_uuid" => $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{$scan_storcli_variable_source_table}{source_uuid}{$scan_storcli_variable_source_uuid}{$type}{$scan_storcli_variable_name}{scan_storcli_variable_uuid}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_variables::scan_storcli_variable_uuid::source_table::${scan_storcli_variable_source_table}::source_uuid::${scan_storcli_variable_source_uuid}::${type}::${scan_storcli_variable_name}::scan_storcli_variable_is_temperature" => $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{$scan_storcli_variable_source_table}{source_uuid}{$scan_storcli_variable_source_uuid}{$type}{$scan_storcli_variable_name}{scan_storcli_variable_is_temperature}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sql::scan_storcli_variables::scan_storcli_variable_uuid::source_table::${scan_storcli_variable_source_table}::source_uuid::${scan_storcli_variable_source_uuid}::${type}::${scan_storcli_variable_name}::scan_storcli_variable_value" => $anvil->data->{sql}{scan_storcli_variables}{scan_storcli_variable_uuid}{source_table}{$scan_storcli_variable_source_table}{source_uuid}{$scan_storcli_variable_source_uuid}{$type}{$scan_storcli_variable_name}{scan_storcli_variable_value}, |
|
}}); |
|
} |
|
undef $results; |
|
|
|
# Return the number |
|
return(0); |
|
} |
|
|
|
# This gathers the various data from the controller(s). |
|
sub gather_data |
|
{ |
|
my ($anvil) = @_; |
|
|
|
### TODO: This assumes the controllers go 0, 1, ... n. If this is wrong, we'll need to call |
|
### 'storcli64 show all' and parse 'System Overview'. |
|
# Loops through reach found controller. |
|
foreach my $controller (1..$anvil->data->{'scan-storcli'}{adapter_count}) |
|
{ |
|
# We drop the number by 1 because the '/cX' starts at '0' where the controller count starts |
|
# at '1'. |
|
my $adapter = ($controller - 1); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
controller => $controller, |
|
adapter => $adapter, |
|
}}); |
|
|
|
# Read in controller data. |
|
my $serial_number = get_controller_info($anvil, $adapter); |
|
|
|
# We use dummy VDs and DGs to store drives not allocated to either yet. The drives will |
|
# reference their parent controller, but the VDs and DGs won't. To deal with this, we need to |
|
# allocate the pseudo DG and VG to something, so we'll use the first controller's SN that we |
|
# see. |
|
if ($controller eq "1") |
|
{ |
|
my $scan_storcli_virtual_drive_id_string = $serial_number."-vd9999"; |
|
$anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{on_controller} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${scan_storcli_virtual_drive_id_string}::variable::on_controller" => $anvil->data->{virtual_drive}{$scan_storcli_virtual_drive_id_string}{variable}{on_controller}, |
|
}}); |
|
} |
|
|
|
# Read in cachevault (FBU) data (if it exists). |
|
get_cachevault_data($anvil, $adapter, $serial_number); |
|
|
|
# Read in BBU data (if it exists). |
|
get_bbu_data($anvil, $adapter, $serial_number); |
|
|
|
# Read in virtual drive information. |
|
get_virtual_drive_data($anvil, $adapter, $serial_number); |
|
|
|
# Read in the physical disk information. |
|
get_physical_disk_data($anvil, $adapter, $serial_number); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This looks for physical disks on the controller. |
|
sub get_physical_disk_data |
|
{ |
|
my ($anvil, $adapter, $serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
adapter => $adapter, |
|
serial_number => $serial_number, |
|
}}); |
|
|
|
my $virtual_drive = $serial_number."-vd9999"; |
|
my $drive_group = 9999; |
|
my $enclosure_id = ""; |
|
my $slot_number = ""; |
|
my $device_id = ""; |
|
my $state = ""; |
|
my $drive_size = ""; |
|
my $interface = ""; |
|
my $drive_media = ""; |
|
my $self_encrypting_drive = ""; |
|
my $protection_info = ""; |
|
my $drive_model = ""; |
|
my $spun_up = ""; |
|
my $in_drive_header = 0; |
|
my $in_port_status = 0; |
|
my $start_break = 0; |
|
my $sector_size = 0; |
|
my $sector_variables = []; |
|
my $shell_call = $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{physical_disk_data}; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
### TODO: Make sure we don't hit a case where we don't find the virtual drive ID string |
|
### before we start recording data. If we do, we'll have to artificially create the ID |
|
### from the controller's serial number (which is pretty safe). |
|
# If I am in the drive header, look for this drive data |
|
# EID :Slt DID State DG Size Intf Med SED PI SeSz Model Sp |
|
# 252 :0 9 Onln 0 136.218 GB SAS HDD N N 512B MK1401GRRB U |
|
if (($in_drive_header) && ($line =~ /^$enclosure_id:$slot_number\s+(\d+)\s+(.*?)\s+(.*?)\s+(.*?B)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?B)\s+(.*?)\s+(.*)$/)) |
|
{ |
|
$device_id = $1; |
|
$state = $2; |
|
$drive_group = $3; |
|
$drive_size = $4; |
|
$interface = $5; |
|
$drive_media = $6; |
|
$self_encrypting_drive = $7; |
|
$protection_info = $8; |
|
$sector_size = $9; |
|
$drive_model = $10; |
|
$spun_up = $11; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
enclosure_id => $enclosure_id, |
|
slot_number => $slot_number, |
|
device_id => $device_id, |
|
'state' => $state, |
|
drive_group => $drive_group, |
|
drive_size => $drive_size, |
|
interface => $interface, |
|
drive_media => $drive_media, |
|
self_encrypting_drive => $self_encrypting_drive, |
|
protection_info => $protection_info, |
|
sector_size => $sector_size, |
|
drive_model => $drive_model, |
|
spun_up => $spun_up, |
|
}}); |
|
|
|
# If it isn't in a drive group, it also won't be in a virtual drive. |
|
if ($drive_group eq "-") |
|
{ |
|
$drive_group = 9999 ; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drive_group => $drive_group }}); |
|
} |
|
elsif ($drive_group =~ /^\d+$/) |
|
{ |
|
# Find the virtual drive this drive is connected to, if any. |
|
foreach my $this_virtual_drive (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}}) |
|
{ |
|
# This avoids auto-vivication of the drive group under the virtual drive |
|
next if not exists $anvil->data->{virtual_drive}{$this_virtual_drive}{drive_group}{$drive_group}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${this_virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_size" => $anvil->data->{virtual_drive}{$this_virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size}, |
|
}}); |
|
if ($anvil->data->{virtual_drive}{$this_virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size}) |
|
{ |
|
# Found it. |
|
$virtual_drive = $this_virtual_drive; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virtual_drive => $virtual_drive }}); |
|
last; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# Not sure that this should ever happen... |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, 'print' => 1 , key => "scan_storcli_warning_0005", variables => { |
|
line => $line, |
|
drive_group => $drive_group, |
|
}}); |
|
} |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virtual_drive => $virtual_drive }}); |
|
|
|
# We need to record this here because drives not in a drive group will be missed |
|
# later in process_vg_pd_list_data(). Drives processed there may overwrite this data, |
|
# which is fine. |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{device_id} = $device_id; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{'state'} = $state; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size} = $drive_size; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{interface} = $interface; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_media} = $drive_media; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{self_encrypting_drive} = $self_encrypting_drive; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{protection_info} = $protection_info; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sector_size} = $sector_size; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_model} = $drive_model; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{spun_up} = $spun_up; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::device_id" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{device_id}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::state" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{'state'}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_size" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::interface" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{interface}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_media" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_media}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::self_encrypting_drive" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{self_encrypting_drive}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::protection_info" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{protection_info}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::sector_size" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sector_size}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_model" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_model}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::spun_up" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{spun_up}, |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::on_controller" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller}, |
|
}}); |
|
next; |
|
} |
|
|
|
# See if I am entering or exiting a section. |
|
if ($line =~ /Drive \/c$adapter\/e(\d+)\/s(\d+):/i) |
|
{ |
|
$enclosure_id = $1; |
|
$slot_number = $2; |
|
#$slot_number = sprintf("%02d", $slot_number); |
|
$in_drive_header = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
enclosure_id => $enclosure_id, |
|
slot_number => $slot_number, |
|
in_drive_header => $in_drive_header, |
|
}}); |
|
next; |
|
} |
|
if ($line =~ /Drive \/c$adapter\/e(\d+)\/s(\d+) State/i) |
|
{ |
|
$enclosure_id = $1; |
|
$slot_number = $2; |
|
#$slot_number = sprintf("%02d", $slot_number); |
|
$in_drive_header = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
enclosure_id => $enclosure_id, |
|
slot_number => $slot_number, |
|
in_drive_header => $in_drive_header, |
|
}}); |
|
next; |
|
} |
|
if ($line =~ /^Port Status /) |
|
{ |
|
$in_port_status = 1; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_port_status => $in_port_status, |
|
start_break => $start_break, |
|
}}); |
|
} |
|
if (($line =~ /^--------/) && ($in_port_status)) |
|
{ |
|
if (not $start_break) |
|
{ |
|
# Split point set, must be the start break |
|
$start_break = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_break => $start_break }}); |
|
next; |
|
} |
|
else |
|
{ |
|
# In 'port status' and start break set, must be end break. |
|
$in_port_status = 0; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_port_status => $in_port_status, |
|
start_break => $start_break, |
|
}}); |
|
|
|
### NOTE: So far as I can tell, there is only ever two SAS ports on hard |
|
### drives. The way the system parses them handles N-number of ports, |
|
### though. For now, we'll squeeze these into the top layer variables |
|
### to save having to have another table to process. |
|
my $sas_port_0_port_status = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{0}{port_status}; |
|
my $sas_port_0_link_speed = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{0}{link_speed}; |
|
my $sas_port_0_sas_address = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{0}{sas_address}; |
|
my $sas_port_1_port_status = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{1}{port_status}; |
|
my $sas_port_1_link_speed = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{1}{link_speed}; |
|
my $sas_port_1_sas_address = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{1}{sas_address}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
sas_port_0_port_status => $sas_port_0_port_status, |
|
sas_port_0_link_speed => $sas_port_0_link_speed, |
|
sas_port_0_sas_address => $sas_port_0_sas_address, |
|
sas_port_1_port_status => $sas_port_1_port_status, |
|
sas_port_1_link_speed => $sas_port_1_link_speed, |
|
sas_port_1_sas_address => $sas_port_1_sas_address, |
|
}}); |
|
|
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_0_port_status} = $sas_port_0_port_status; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_0_link_speed} = $sas_port_0_link_speed; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_0_sas_address} = $sas_port_0_sas_address; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_1_port_status} = $sas_port_1_port_status; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_1_link_speed} = $sas_port_1_link_speed; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sas_port_1_sas_address} = $sas_port_1_sas_address; |
|
next; |
|
} |
|
} |
|
|
|
# We stop processing a given drive when we see 'Inquiry Data'. |
|
if ($line =~ /^Inquiry Data =/) |
|
{ |
|
# Process and variables that need their size calculated from sectors to bytes. |
|
# These are always variables. |
|
foreach my $variable (sort {$a cmp $b} @{$sector_variables}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
next if not $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}; |
|
|
|
my $value = $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
if ($value =~ /^(\d+) bytes, (\d+) sectors/) |
|
{ |
|
my $size = $1; |
|
my $sectors = $2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size => $size, |
|
sectors => $sectors, |
|
sector_size => $sector_size, |
|
}}); |
|
if ($sector_size) |
|
{ |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = ($sectors * $sector_size); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
else |
|
{ |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = $size; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
# Record the drive as being on this controller. |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::on_controller" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{on_controller}, |
|
}}); |
|
|
|
$virtual_drive = $serial_number."-vd9999"; |
|
$drive_group = 9999; |
|
$enclosure_id = ""; |
|
$slot_number = ""; |
|
$in_drive_header = 0; |
|
$in_port_status = 0; |
|
$start_break = 0; |
|
$sector_size = 0; |
|
$sector_variables = []; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virtual_drive => $virtual_drive }}); |
|
} |
|
next if $enclosure_id eq ""; |
|
|
|
# If I am in the port status, parse the port info. |
|
if (($in_port_status) && ($line =~ /^(\d+)\s+(.*?)\s+(\d.*?)Gb\/s\s+(0x.*)$/)) |
|
{ |
|
my $sas_port = $1; |
|
my $port_status = $2; |
|
my $link_speed = $3." #!variable!scan_storcli_unit_0013!#"; |
|
my $sas_address = $4; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
sas_port => $sas_port, |
|
port_status => $port_status, |
|
link_speed => $link_speed, |
|
sas_address => $sas_address, |
|
}}); |
|
|
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{port_status} = $port_status; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{link_speed} = $link_speed; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{sas_address} = $sas_address; |
|
# These are so flipping long that we print them as three separate log entries so that |
|
# they're easier to read in the logs. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::sas_port::${sas_port}::port_status" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{port_status}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::sas_port::${sas_port}::link_speed" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{link_speed}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::sas_port::${sas_port}::sas_address" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{sas_port}{$sas_port}{sas_address}, |
|
}}); |
|
next; |
|
} |
|
|
|
### If I have a 'variable = value' pair split and parse. |
|
# The 'Drive position' isn't set for drives not in an array/drive group. |
|
if ($line =~ /^Drive position = DriveGroup:(\d+), Span:(\d+), Row:(\d+)/i) |
|
{ |
|
my $this_drive_group = $1; |
|
my $span = $2; |
|
my $row = $3; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
this_drive_group => $this_drive_group, |
|
span => $span, |
|
row => $row, |
|
}}); |
|
|
|
# I don't pick up this until well into the scan, but the drive group should match |
|
# what we found earlier. Just to be safe though, if not, throw a warning. |
|
if ($this_drive_group ne $drive_group) |
|
{ |
|
# Report this error |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1 , key => "scan_storcli_warning_0001", variables => { |
|
adapter => $adapter, |
|
serial_number => $serial_number, |
|
virtual_drive => $virtual_drive, |
|
enclosure_id => $enclosure_id, |
|
slot_number => $slot_number, |
|
span => $span, |
|
row => $row, |
|
old_drive_group => $drive_group, |
|
new_drive_group => $this_drive_group, |
|
shell_call => $shell_call, |
|
}}); |
|
$drive_group = $this_drive_group; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drive_group => $drive_group }}); |
|
} |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{span} = $span; |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{row} = $row; |
|
|
|
# These are so flipping long that we print them as three separate log entries so that |
|
# they're easier to read in the logs. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::span" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{span}, |
|
}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::row" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{row}, |
|
}}); |
|
next; |
|
} |
|
|
|
# Split and process all 'variable = value' lines we've not already handled. |
|
if ($line =~ /^(.*?)\s+=\s+(.*)$/) |
|
{ |
|
my $variable = $1; |
|
my $value = $2; |
|
my $type = "variable"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
|
|
# Process some variable names. |
|
if ($variable =~ /^SN$/i) |
|
{ |
|
$variable = "Serial Number"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /^WWN$/i) |
|
{ |
|
$variable = "World Wide Name"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /^PI /i) |
|
{ |
|
$variable =~ s/^PI /Protection Information /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ / Id$/i) |
|
{ |
|
$variable =~ s/ Id$/ Identification/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /^Sector Size$/i) |
|
{ |
|
# Convert to bytes and record. |
|
$value = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $value})." #!string!scan_storcli_unit_0001!#"; |
|
$sector_size = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
value => $value, |
|
sector_size => $sector_size, |
|
}}); |
|
} |
|
if ($variable =~ / EKM/i) |
|
{ |
|
# De-TLA it |
|
$variable =~ s/ EKM/ External Key Management/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /S\.M\.A\.R\.T\./i) |
|
{ |
|
$variable =~ s/S\.M\.A\.R\.T\./SMART/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /S\.M\.A\.R\.T/i) |
|
{ |
|
$variable =~ s/S\.M\.A\.R\.T/SMART/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
|
|
# Process some values. |
|
if ($value =~ /^(\d.*?B) \[(0x.*?) Sectors\]/) |
|
{ |
|
my $size = $1; |
|
my $hex_sectors = $2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size => $size, |
|
hex_sectors => $hex_sectors, |
|
}}); |
|
|
|
my $sectors = Math::BigInt->new($hex_sectors); |
|
my $bytes = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $size}); |
|
$value = $bytes." #!variable!scan_storcli_unit_0001!#, ".$sectors." #!variable!scan_storcli_unit_0012!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size => $size, |
|
'bytes' => $bytes, |
|
hex_sectors => $hex_sectors, |
|
value => $value, |
|
variable => $variable, |
|
}}); |
|
|
|
# Mark this for sector size calculation later. |
|
push @{$sector_variables}, $variable; |
|
} |
|
if (($value =~ /^(\d+\s*[A-Za-z]+B)$/i) or ($value =~ /^(\d+\.\d+\s*[A-Za-z]+B)$/i)) |
|
{ |
|
my $size = $1; |
|
$value = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $size})." #!string!scan_storcli_unit_0001!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size => $size, |
|
value => $value, |
|
}}); |
|
} |
|
if ($value =~ /^(\d.*?)C \(\d.*? F\)/i) |
|
{ |
|
$value = $1; |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
value => $value, |
|
type => $type, |
|
}}); |
|
} |
|
if (($value =~ /^(\d+)C$/i) or ($value =~ /^(\d+\.\d+)C$/i)) |
|
{ |
|
$value = $1; |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
value => $value, |
|
type => $type, |
|
}}); |
|
} |
|
if (($value =~ /^(\d+)F$/i) or ($value =~ /^(\d+\.\d+)F$/i)) |
|
{ |
|
$value = $anvil->Convert->fahrenheit_to_celsius({temperature => $1}); |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
value => $value, |
|
type => $type, |
|
}}); |
|
} |
|
if ($value =~ /^(\d.*?)Gb\/s$/) |
|
{ |
|
$value = $1." #!variable!scan_storcli_unit_0013!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value eq "NA") |
|
{ |
|
$value = "N/A"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
|
|
# Process/standardize the variable. |
|
$variable = process_variable_name($anvil, $variable); |
|
|
|
# Record |
|
$anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${virtual_drive}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::${type}::$variable" => $anvil->data->{virtual_drive}{$virtual_drive}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{$type}{$variable}, |
|
}}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This looks for virtual drives on the controller. |
|
sub get_virtual_drive_data |
|
{ |
|
my ($anvil, $adapter, $serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
adapter => $adapter, |
|
serial_number => $serial_number, |
|
}}); |
|
|
|
my $virtual_drive = ""; |
|
my $id_string = ""; |
|
my $in_overview = 0; |
|
my $in_pd_list = 0; |
|
my $in_vd_data = 0; |
|
my $start_break = 0; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{virtual_drive_data}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /\/c$adapter\/v(\d+):/) |
|
{ |
|
$virtual_drive = $1; |
|
$id_string = $serial_number."-vd".$virtual_drive; |
|
$anvil->data->{virtual_drive}{$id_string}{variable}{on_controller} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
virtual_drive => $virtual_drive, |
|
id_string => $id_string, |
|
"virtual_drive::${id_string}::variable::on_controller" => $anvil->data->{virtual_drive}{$id_string}{variable}{on_controller}, |
|
}}); |
|
|
|
# We set the VD '9999' to the same SN so that we can find unallocated disks later. |
|
my $unallocated_id_string = $serial_number."-vd9999"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { unallocated_id_string => $unallocated_id_string }}); |
|
if (not $anvil->data->{virtual_drive}{$unallocated_id_string}{variable}{on_controller}) |
|
{ |
|
$anvil->data->{virtual_drive}{$unallocated_id_string}{variable}{on_controller} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${unallocated_id_string}::variable::on_controller" => $anvil->data->{virtual_drive}{$unallocated_id_string}{variable}{on_controller}, |
|
}}); |
|
} |
|
} |
|
if ($line =~ /PDs for VD (\d+) :/) |
|
{ |
|
$virtual_drive = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virtual_drive => $virtual_drive }}); |
|
} |
|
if ($line =~ /VD(\d+) Properties/) |
|
{ |
|
$virtual_drive = $1; |
|
$in_vd_data = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
virtual_drive => $virtual_drive, |
|
in_vd_data => $in_vd_data, |
|
}}); |
|
} |
|
|
|
next if $virtual_drive eq ""; |
|
|
|
# See if I am entering or exiting the overview chunk. |
|
if ($line =~ /^DG\/VD/) |
|
{ |
|
$in_overview = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_overview => $in_overview }}); |
|
next; |
|
} |
|
if (($line =~ /^--------/) && ($in_overview)) |
|
{ |
|
if (not $start_break) |
|
{ |
|
# Split point set, must be the start break |
|
$start_break = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_break => $start_break }}); |
|
next; |
|
} |
|
else |
|
{ |
|
# Split point and start break set, must be end break. |
|
$in_overview = 0; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_overview => $in_overview, |
|
start_break => $start_break, |
|
}}); |
|
next; |
|
} |
|
} |
|
if ($in_overview) |
|
{ |
|
process_vg_overview_data($anvil, $line, $serial_number); |
|
} |
|
|
|
# See if I am entering or exiting the physical drive chunk. |
|
if ($line =~ /^EID:Slt/) |
|
{ |
|
$in_pd_list = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_pd_list => $in_pd_list }}); |
|
next; |
|
} |
|
if (($line =~ /^--------/) && ($in_pd_list)) |
|
{ |
|
if (not $start_break) |
|
{ |
|
# Split point set, must be the start break |
|
$start_break = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_break => $start_break }}); |
|
next; |
|
} |
|
else |
|
{ |
|
# Split point and start break set, must be end break. |
|
$in_pd_list = 0; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_pd_list => $in_pd_list, |
|
start_break => $start_break, |
|
}}); |
|
next; |
|
} |
|
} |
|
if ($in_pd_list) |
|
{ |
|
process_vg_pd_list_data($anvil, $line, $virtual_drive, $serial_number, $id_string); |
|
} |
|
|
|
if ($in_vd_data) |
|
{ |
|
if ($line =~ /^(.*?) = (.*)$/) |
|
{ |
|
my $variable = $1; |
|
my $value = $2; |
|
my $type = "variable"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
|
|
# Convert some formatting. |
|
if (($value =~ /^(\d+\s*[A-Za-z]+B)$/i) or ($value =~ /^(\d+\.\d+\s*[A-Za-z]+B)$/i)) |
|
{ |
|
# Convert to bytes |
|
$value = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $value})." #!string!scan_storcli_unit_0001!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
elsif ($value =~ /^(\d\d)-(\d\d)-(\d\d\d\d)$/) |
|
{ |
|
# Convert dd-mm-yyyy to yyyy/mm/dd |
|
$value = $3."/".$2."/".$1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
elsif ($value =~ /^(\d\d):(\d\d):(\d\d) (\wM)$/) |
|
{ |
|
# Convert AM/PM -> 24h |
|
my $hour = $1; |
|
my $minute = $2; |
|
my $second = $3; |
|
my $suffix = $4; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
hour => $hour, |
|
minute => $minute, |
|
second => $second, |
|
suffix => $suffix, |
|
}}); |
|
if ($suffix eq "PM") |
|
{ |
|
$hour += 12; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { hour => $hour }}); |
|
} |
|
$value = "$hour:$minute:$second"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
|
|
# Record |
|
$variable = process_variable_name($anvil, $variable); |
|
$anvil->data->{virtual_drive}{$id_string}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::${type}::$variable" => $anvil->data->{virtual_drive}{$id_string}{$type}{$variable}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This parses a virtual drive's physical disk overview line |
|
sub process_vg_pd_list_data |
|
{ |
|
my ($anvil, $line, $virtual_drive, $serial_number, $id_string) = @_; |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"line" => $line, |
|
}}); |
|
### Sector size is either '512B' or '4 KB' |
|
# EID:Slt DID State DG Size Intf Med SED PI SeSz Model Sp |
|
# 252:0 9 Onln 0 136.218 GB SAS HDD N N 512B MK1401GRRB U |
|
if ($line =~ /^(\d+):(\d+)\s+(\d+)\s+(.*?)\s+(.*?)\s+(.*?B)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?B)\s+(.*?)\s+(.*)$/) |
|
{ |
|
my $enclosure_id = $1; |
|
my $slot_number = $2; |
|
my $device_id = $3; |
|
my $state = $4; |
|
my $drive_group = $5; |
|
my $drive_size = $6; |
|
my $interface = $7; |
|
my $drive_media = $8; |
|
my $self_encrypting_drive = $9; |
|
my $protection_info = $10; |
|
my $sector_size = $11; |
|
my $drive_model = $12; |
|
my $spun_up = $13; |
|
$drive_group = 9999 if $drive_group eq "-"; |
|
$protection_info = $protection_info =~ /n/i ? "No" : "Yes"; |
|
$self_encrypting_drive = $self_encrypting_drive =~ /n/i ? "No" : "Yes"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"enclosure_id" => $enclosure_id, |
|
"slot_number" => $slot_number, |
|
"device_id" => $device_id, |
|
"state" => $state, |
|
"drive_group" => $drive_group, |
|
"drive_size" => $drive_size, |
|
"interface" => $interface, |
|
"drive_media" => $drive_media, |
|
"self_encrypting_drive" => $self_encrypting_drive, |
|
"protection_info" => $protection_info, |
|
"sector_size" => $sector_size, |
|
"drive_model" => $drive_model, |
|
"spun_up" => $spun_up, |
|
}}); |
|
|
|
# Convert the sector and drive sizes into bytes. The controller uses 'xB' but uses base2 values. |
|
$sector_size = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $sector_size})." #!string!scan_storcli_unit_0001!#"; |
|
$drive_size = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $drive_size})." #!string!scan_storcli_unit_0001!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"sector_size" => $sector_size, |
|
"drive_size" => $drive_size, |
|
}}); |
|
|
|
### Long hashes are long... x_x |
|
# Store the data (we'll convert it in a minute. |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{device_id} = $device_id; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{'state'} = $state; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size} = $drive_size; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{interface} = $interface; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_media} = $drive_media; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{self_encrypting_drive} = $self_encrypting_drive; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{protection_info} = $protection_info; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sector_size} = $sector_size; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_model} = $drive_model; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{spun_up} = $spun_up; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::device_id" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{device_id}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::state" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{'state'}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_size" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_size}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::interface" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{interface}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_media" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_media}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::self_encrypting_drive" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{self_encrypting_drive}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::protection_info" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{protection_info}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::sector_size" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{sector_size}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::drive_model" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{drive_model}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::spun_up" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{spun_up}, |
|
}}); |
|
|
|
### WARNING: The strings we set here will be parsed later, so don't change them without also |
|
### changing where they're checked for elsewhere in this agent. |
|
### NOTE: We don't use a function for this because the glossary for the block of data is |
|
### specific for the table above (it would appear). |
|
# Translate the weird short form to useable strings |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}}) |
|
{ |
|
my $value = $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
">> virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
|
|
if ($value =~ /^DHS$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Dedicated Hot Spare"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^UGood$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Unconfigured Good"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^GHS$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Global Hotspare"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^UBad$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Unconfigured Bad"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^Onln$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Online"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^Offln$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Offline"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^U$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Spun Up"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^D$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Spun Down"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^T$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Transition"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^F$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Foreign"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^UGUnsp$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Unsupported"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^UGShld$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Unconfigured shielded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^HSPShld$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Hotspare shielded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^CFShld$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Configured shielded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^Cpybck$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Copyback"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
if ($value =~ /^CBShld$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable} = "Copyback Shielded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::enclosure_id::${enclosure_id}::slot_number::${slot_number}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{enclosure_id}{$enclosure_id}{slot_number}{$slot_number}{variable}{$variable}, |
|
}}); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# Unparsed line |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"? line" => $line, |
|
}}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This parses a virtual drive overview line |
|
sub process_vg_overview_data |
|
{ |
|
my ($anvil, $line, $serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
line => $line, |
|
serial_number => $serial_number, |
|
}}); |
|
|
|
my $drive_group = ""; |
|
my $virtual_drive = ""; |
|
my $raid_type = ""; |
|
my $array_state = ""; |
|
my $access = ""; |
|
my $consistent = ""; |
|
my $cache = ""; |
|
my $cachecade = ""; |
|
my $scheduled_consistency_check = ""; |
|
my $array_size = ""; |
|
my $name = ""; |
|
my $id_string = ""; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"line" => $line, |
|
}}); |
|
# Get the line when there is no name |
|
# 0 / 0 RAID5 Optl RW Yes NRWBD - OFF 953.531 GB |
|
if ($line =~ /^(\d+)\/(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+ \wB)$/i) |
|
{ |
|
$drive_group = $1; |
|
$virtual_drive = $2; |
|
$raid_type = $3; |
|
$array_state = $4; |
|
$access = $5; |
|
$consistent = $6; |
|
$cache = $7; |
|
$cachecade = $8; |
|
$scheduled_consistency_check = $9; |
|
$array_size = $10; |
|
$id_string = $serial_number."-vd".$virtual_drive; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"drive_group" => $drive_group, |
|
"virtual_drive" => $virtual_drive, |
|
"raid_type" => $raid_type, |
|
"array_state" => $array_state, |
|
"access" => $access, |
|
"consistent" => $consistent, |
|
"cache" => $cache, |
|
"cachecade" => $cachecade, |
|
"scheduled_consistency_check" => $scheduled_consistency_check, |
|
"array_size" => $array_size, |
|
"id_string" => $id_string, |
|
}}); |
|
} |
|
# Get the line when there is a name |
|
# 0 / 0 RAID5 Optl RW Yes RWBD - OFF 3.271 TB VD0 |
|
# 1 / 1 RAID5 Optl RW Yes RWBD - OFF 744.187 GB VD1 |
|
# 2 / 2 RAID0 Optl RW Yes RWBD - OFF 1.636 TB VD2 |
|
elsif ($line =~ /^(\d+)\/(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+ \wB)\s+(.*)$/i) |
|
{ |
|
$drive_group = $1; |
|
$virtual_drive = $2; |
|
$raid_type = $3; |
|
$array_state = $4; |
|
$access = $5; |
|
$consistent = $6; |
|
$cache = $7; |
|
$cachecade = $8; |
|
$scheduled_consistency_check = $9; |
|
$array_size = $10; |
|
$name = $11; |
|
$id_string = $serial_number."-vd".$virtual_drive; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"drive_group" => $drive_group, |
|
"virtual_drive" => $virtual_drive, |
|
"raid_type" => $raid_type, |
|
"array_state" => $array_state, |
|
"access" => $access, |
|
"consistent" => $consistent, |
|
"cache" => $cache, |
|
"cachecade" => $cachecade, |
|
"scheduled_consistency_check" => $scheduled_consistency_check, |
|
"array_size" => $array_size, |
|
"name" => $name, |
|
"id_string" => $id_string, |
|
}}); |
|
} |
|
else |
|
{ |
|
# Unmatched line... |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"? line" => $line, |
|
}}); |
|
next; |
|
} |
|
|
|
# Convert the array size into bytes. The controller uses 'xB' but uses base2 values. |
|
$array_size = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $array_size})." #!string!scan_storcli_unit_0001!#"; |
|
|
|
# Store the data. |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{on_controller} = $serial_number; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{raid_type} = $raid_type; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{array_state} = $array_state; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{access} = $access; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{consistent} = $consistent; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{cache} = $cache; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{cachecade} = $cachecade; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{scheduled_consistency_check} = $scheduled_consistency_check; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{array_size} = $array_size; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{name} = $name; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::on_controller" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{on_controller}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::raid_type" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{raid_type}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::array_state" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{array_state}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::access" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{access}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::consistent" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{consistent}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{cache}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::cachecade" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{cachecade}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::scheduled_consistency_check" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{scheduled_consistency_check}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::array_size" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{array_size}, |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::name" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{name}, |
|
}}); |
|
|
|
### WARNING: The strings we set here will be parsed later, so don't change them without also changing |
|
### where they're checked for elsewhere in this agent. |
|
### NOTE: We don't use a function for this because the glossary for the block of data is specific for |
|
### the table above (it would appear). |
|
# Translate the weird short form to useable strings |
|
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
">> virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
|
|
if ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} eq "-") |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "No"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^Cac$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "CacheCade"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^Rec$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Recovery"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^OfLn$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "OffLine"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^Pdgd$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Partially Degraded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^dgrd$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Degraded"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^Optl$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Optimal"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^RO$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Read Only"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^RW$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Read Write"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^HD$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Hidden"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^TRANS$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Transport Ready"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^B$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Blocked"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^Consist$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Consistent"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
elsif ($anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} =~ /^sCC$/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable} = "Scheduled Check Consistency"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"<< virtual_drive::${id_string}::drive_group::${drive_group}::variable::$variable" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}, |
|
}}); |
|
} |
|
|
|
# Because they hate programmers, the cache is a combination of a few of the |
|
# above strings. |
|
if ($variable eq "cache") |
|
{ |
|
my $cache = $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{$variable}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"cache" => $cache, |
|
}}); |
|
|
|
# Prep some blanks |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{read_cache} = ""; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache} = ""; |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{disk_cache} = ""; |
|
|
|
# Read cache |
|
if ($cache =~ /NR/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{read_cache} = "No Read-Ahead"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::read_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{read_cache}, |
|
}}); |
|
} |
|
elsif ($cache =~ /R/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{read_cache} = "Always Read-Ahead"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::read_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{read_cache}, |
|
}}); |
|
} |
|
|
|
# Write cache |
|
if ($cache =~ /AWB/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache} = "Always Write-Back"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::write_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache}, |
|
}}); |
|
} |
|
elsif ($cache =~ /WB/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache} = "Write-Back"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::write_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache}, |
|
}}); |
|
} |
|
elsif ($cache =~ /WT/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache} = "Write-Through"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::write_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{write_cache}, |
|
}}); |
|
} |
|
|
|
# Disk cache |
|
if ($cache =~ /C/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{disk_cache} = "Cached IO"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::disk_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{disk_cache}, |
|
}}); |
|
} |
|
elsif ($cache =~ /D/i) |
|
{ |
|
$anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{disk_cache} = "Direct IO"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"virtual_drive::${id_string}::drive_group::${drive_group}::variable::disk_cache" => $anvil->data->{virtual_drive}{$id_string}{drive_group}{$drive_group}{variable}{disk_cache}, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This looks for a BBU and, if it finds one, parses the output for it. |
|
sub get_bbu_data |
|
{ |
|
my ($anvil, $adapter, $serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
adapter => $adapter, |
|
serial_number => $serial_number, |
|
}}); |
|
|
|
my $bbu_serial_number = ""; |
|
my $bbu_data = []; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{bbu_data}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
last if $line =~ /$adapter Failed /i; |
|
|
|
if ($line =~ /^Serial Number\s+(\S.*)?/i) |
|
{ |
|
$bbu_serial_number = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bbu_serial_number => $bbu_serial_number }}); |
|
next; |
|
} |
|
push @{$bbu_data}, $line; |
|
} |
|
|
|
# If I didn't find a serial number, then I probably don't have an FBU. |
|
return(0) if not $bbu_serial_number; |
|
|
|
# Record the controller the bbu is on. |
|
$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{host_controller_serial_number} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bbu::serial_number::${bbu_serial_number}::host_controller_serial_number" => $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{host_controller_serial_number}, |
|
}}); |
|
|
|
# Still alive? Good, time to parse the most annoying output ever... >_< |
|
my $split_point = 0; |
|
my $start_break = 0; |
|
my $end_break = 0; |
|
foreach my $line (@{$bbu_data}) |
|
{ |
|
next if not $line; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
if ($line =~ /Property(\s+)Value/) |
|
{ |
|
$split_point = length($1) + 8; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { split_point => $split_point }}); |
|
next; |
|
} |
|
|
|
# See if I am entering or exiting a data chunk. |
|
if (($line =~ /^--------/) && ($split_point)) |
|
{ |
|
if (not $start_break) |
|
{ |
|
# Split point set, must be the start break |
|
$start_break = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_break => $start_break }}); |
|
next; |
|
} |
|
else |
|
{ |
|
# Split point and start break set, must be end break. |
|
$split_point = 0; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
split_point => $split_point, |
|
start_break => $start_break, |
|
}}); |
|
next; |
|
} |
|
} |
|
|
|
# If I have a split point, break the string. |
|
if ($split_point) |
|
{ |
|
# Elegant? I think not! |
|
my $variable = ""; |
|
my $value = ""; |
|
my $type = "variable"; |
|
if ($split_point >= length($line)) |
|
{ |
|
# Variable with no value |
|
$variable = $line; |
|
$variable =~ s/\s+$//; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
else |
|
{ |
|
($variable, $value) = ($line =~ /^(.{$split_point})(.*)$/); |
|
$variable =~ s/\s+$//; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
|
|
# Because LSI is either evil or amazingly incompetent, we have the variable |
|
# "Absolute State of charge" listed twice, but once with 'State' and the |
|
# other with 'state' (capital versus small 'S'). We fix it because it is the |
|
# same data and we don't want two records, so the second copy will now just |
|
# overwrite the first one. |
|
if ($variable eq "Absolute State of charge") |
|
{ |
|
$variable = "Absolute state of charge"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
|
|
# They use 'Temperature' twice; once for the temperature and once to show if |
|
# it is OK or not. We'll avoid one clobbering the other by renaming the |
|
# status one. |
|
if (($variable eq "Temperature") && ($value !~ /^\d/)) |
|
{ |
|
$variable = "Temperature Status"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if (($variable eq "Temperature") && ($value =~ /^\d/)) |
|
{ |
|
$variable = "BBU Temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
|
|
# *sigh* - Typo on their part, but also a re-use of the variable name |
|
# "Remaining Time Alarm". The Status one we will rename the variable and the |
|
# later we'll fix the type. |
|
if ((lc($variable) eq "remaining time alarm") && ($value !~ /\d/)) |
|
{ |
|
# No digit in the value, so this is the status. |
|
$variable = "Remaining Time Alarm Status"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
if ($variable =~ /remining /) |
|
{ |
|
$variable =~ s/emining /emaining /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
|
|
if ($variable =~ /\(initial setting\)/i) |
|
{ |
|
$variable =~ s/\(initial setting\)//i; |
|
$variable = "Initial ".$variable." Setting"; |
|
$variable =~ s/\s+//; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
} |
|
|
|
# Is this a temperature or something else we want to pre-process? |
|
if ($value =~ /^(\d+) C$/i) |
|
{ |
|
# Yup |
|
$value = $1; |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d+) F$/i) |
|
{ |
|
# Yup, but translate |
|
$value = $anvil->Convert->fahrenheit_to_celsius({temperature => $1}); |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /\d+d \((\d+) seconds\)$/i) |
|
{ |
|
# This is a static time span (like the time between learn cycles. |
|
$value = $1; |
|
$value .= " #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d\d\d\d)\/(\d\d)\/(\d\d)\s+(\d\d:\d\d:\d\d)\s+\(\d+ seconds\)$/i) |
|
{ |
|
### NOTE: The 'X seconds' seems to not change and be a useless number... |
|
# This is a specific time in the future, properly formatted |
|
$value = $1."/".$2."/".$3.", ".$4; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d\d)\/(\d\d)\/(\d\d\d\d)$/i) |
|
{ |
|
# 'Murica! mm/dd/yyyy -> yyyy/mm/dd |
|
$value = $3."/".$2."/".$1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d+) hour\(s\)$/i) |
|
{ |
|
# 'Murica! mm/dd/yyyy -> yyyy/mm/dd |
|
$value = $1 * 3600; |
|
$value .= " #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
|
|
# Record |
|
$variable = process_variable_name($anvil, $variable); |
|
|
|
# 'Auto-Learn' and 'Auto_Learn' are both used because screw consistency, right? |
|
$variable =~ s/auto-learn/auto_learn/; |
|
|
|
$anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"bbu:serial_number::${bbu_serial_number}::${type}::$variable" => $anvil->data->{bbu}{serial_number}{$bbu_serial_number}{$type}{$variable}, |
|
}}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This looks for a cachevault (flash-backup unit) and, if one is found, parses the output. |
|
sub get_cachevault_data |
|
{ |
|
my ($anvil, $adapter, $serial_number) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
adapter => $adapter, |
|
serial_number => $serial_number, |
|
}}); |
|
|
|
my $cachevault_serial_number = ""; |
|
my $cachevault_data = []; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{cachevault_data}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
last if $line =~ /Cachevault doesn't exist/i; |
|
|
|
if ($line =~ /^Serial Number\s+(\S.*)?/i) |
|
{ |
|
$cachevault_serial_number = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { cachevault_serial_number => $cachevault_serial_number }}); |
|
next; |
|
} |
|
push @{$cachevault_data}, $line; |
|
} |
|
|
|
# If I didn't find a serial number, then I probably don't have an FBU. |
|
return(0) if not $cachevault_serial_number; |
|
|
|
# Record the controller the cachevault is on. |
|
$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{host_controller_serial_number} = $serial_number; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"cachevault::serial_number::${cachevault_serial_number}::host_controller_serial_number" => $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{host_controller_serial_number}, |
|
}}); |
|
|
|
# Still alive? Good, time to parse the most annoying output ever... >_< |
|
my $split_point = 0; |
|
my $start_break = 0; |
|
my $end_break = 0; |
|
foreach my $line (@{$cachevault_data}) |
|
{ |
|
next if not $line; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
if ($line =~ /Property(\s+)Value/) |
|
{ |
|
$split_point = length($1) + 8; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { split_point => $split_point }}); |
|
next; |
|
} |
|
|
|
# See if I am entering or exiting a data chunk. |
|
if (($line =~ /^--------/) && ($split_point)) |
|
{ |
|
if (not $start_break) |
|
{ |
|
# Split point set, must be the start break |
|
$start_break = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { start_break => $start_break }}); |
|
next; |
|
} |
|
else |
|
{ |
|
# Split point and start break set, must be end break. |
|
$split_point = 0; |
|
$start_break = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
split_point => $split_point, |
|
start_break => $start_break, |
|
}}); |
|
next; |
|
} |
|
} |
|
|
|
# If I have a split point, break the string. |
|
if ($split_point) |
|
{ |
|
my $variable = ""; |
|
my $value = ""; |
|
my $type = "variable"; |
|
if ($split_point >= length($line)) |
|
{ |
|
# Variable with no value |
|
$variable = $line; |
|
$variable =~ s/\s+$//; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
else |
|
{ |
|
($variable, $value) = ($line =~ /^(.{$split_point})(.*)$/); |
|
$variable =~ s/\s+$//; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
|
|
# With BBUs, they use 'Temperature' twice; once for status and once for the current |
|
# temperature. They don't currently do this with Cachevaults, but in case they do |
|
# later, we'll rename the temperature variable. |
|
if (($variable eq "Temperature") && ($value =~ /^\d/)) |
|
{ |
|
$variable = "Cachevault Temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }}); |
|
} |
|
|
|
# Is this a temperature or something else we want to pre-process? |
|
if ($value =~ /^(\d+) C$/i) |
|
{ |
|
# Yup |
|
$value = $1; |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d+) F$/i) |
|
{ |
|
# Yup, but translate |
|
$value = $anvil->Convert->fahrenheit_to_celsius({temperature => $1}); |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /\d+d \((\d+) seconds\)$/i) |
|
{ |
|
# This is a static time span (like the time between learn cycles. |
|
$value = $1; |
|
$value .= " #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d\d\d\d)\/(\d\d)\/(\d\d)\s+(\d\d:\d\d:\d\d)\s+\(\d+ seconds\)$/i) |
|
{ |
|
### NOTE: The 'X seconds' seems to not change and be a useless number... |
|
# This is a specific time in the future, properly formatted |
|
# yyyy/mm/dd -> |
|
$value = $1."/".$2."/".$3.", ".$4; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d\d)\/(\d\d)\/(\d\d\d\d)$/i) |
|
{ |
|
# 'Murica! mm/dd/yyyy -> yyyy/mm/dd |
|
$value = $3."/".$2."/".$1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($value =~ /^(\d+) hour\(s\)$/i) |
|
{ |
|
# 'Murica! mm/dd/yyyy -> yyyy/mm/dd |
|
$value = $1 * 3600; |
|
$value .= " #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
|
|
# Record |
|
$variable = process_variable_name($anvil, $variable); |
|
|
|
# 'Auto-Learn' and 'Auto_Learn' are both used because screw consistency, right? |
|
$variable =~ s/auto-learn/auto_learn/; |
|
|
|
$anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"cachevault:serial_number::${cachevault_serial_number}::${type}::$variable" => $anvil->data->{cachevault}{serial_number}{$cachevault_serial_number}{$type}{$variable}, |
|
}}); |
|
} |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This gets the basic information about the controller. |
|
sub get_controller_info |
|
{ |
|
my ($anvil, $adapter) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { adapter => $adapter }}); |
|
|
|
my $in_raid_level_supported = 0; |
|
my $multiline_value = ""; |
|
my $in_header = 1; |
|
my $in_basics = 0; |
|
my $in_supported_ops = 0; |
|
my $in_supported_pd_ops = 0; |
|
my $in_supported_vd_ops = 0; |
|
my $in_hardware_config = 0; |
|
my $in_capabilities = 0; |
|
my $in_policies = 0; |
|
my $in_defaults = 0; |
|
my $serial_number = ""; |
|
my $controller_data = []; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{controller_info}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
next if not $line; |
|
last if $line =~ /^TOPOLOGY:$/i; |
|
|
|
# The time changes constantly, so ignore it. |
|
if ($line =~ /Date\/Time/i) |
|
{ |
|
next; |
|
} |
|
|
|
# RAID Level Supported can be multi-line because $reasons. |
|
if ($line =~ /RAID Level Supported = (.*)$/) |
|
{ |
|
$multiline_value = $1; |
|
$in_raid_level_supported = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
multiline_value => $multiline_value, |
|
in_raid_level_supported => $in_raid_level_supported, |
|
}}); |
|
} |
|
if ($in_raid_level_supported) |
|
{ |
|
if ($line =~ / = /) |
|
{ |
|
# Found the next line, close up RAID Level Supported. |
|
push @{$controller_data}, "RAID Level Supported = ".$multiline_value; |
|
$multiline_value = ""; |
|
$in_raid_level_supported = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
multiline_value => $multiline_value, |
|
in_raid_level_supported => $in_raid_level_supported, |
|
}}); |
|
} |
|
else |
|
{ |
|
$multiline_value .= " $line"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { multiline_value => $multiline_value }}); |
|
next; |
|
} |
|
} |
|
|
|
if ($line =~ /^Serial Number = (.*)?/i) |
|
{ |
|
$serial_number = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { serial_number => $serial_number }}); |
|
next; |
|
} |
|
|
|
### LSI reuses the save variable names in different sections. This tries to catch and rename |
|
### them |
|
# Ignore stuff in the header |
|
if ($line =~ /^Basics/) |
|
{ |
|
$in_header = 0; |
|
$in_basics = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_header => $in_header, |
|
in_basics => $in_basics, |
|
}}); |
|
} |
|
if ($in_basics) |
|
{ |
|
if ($line =~ /^Version/) |
|
{ |
|
$in_basics = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_basics => $in_basics }}); |
|
} |
|
} |
|
elsif ($line =~ /^Controller\s+=/) |
|
{ |
|
# This is the header data, which we don't care about. |
|
next; |
|
} |
|
if ($in_header) |
|
{ |
|
next; |
|
} |
|
|
|
# Mangle supported adapter operation variables. |
|
if ($line =~ /^Supported Adapter Operations/) |
|
{ |
|
$in_supported_ops = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_supported_ops => $in_supported_ops }}); |
|
} |
|
if ($in_supported_ops) |
|
{ |
|
if ($line =~ /^Supported PD Operations/) |
|
{ |
|
$in_supported_ops = 0; |
|
$in_supported_pd_ops = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_supported_ops => $in_supported_ops, |
|
in_supported_pd_ops => $in_supported_pd_ops, |
|
}}); |
|
} |
|
|
|
if ($line =~ /^BBU /) |
|
{ |
|
$line =~ s/^BBU /BBU Supported /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Rebuild Rate /) |
|
{ |
|
$line =~ s/^Rebuild Rate /Configurable Rebuild Rate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^CC Rate /) |
|
{ |
|
$line =~ s/^CC Rate /Configurable Consistency Check Rate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^BGI Rate /) |
|
{ |
|
$line =~ s/^BGI Rate /Configurable background Initialization Rate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Reconstruct Rate /) |
|
{ |
|
$line =~ s/^Reconstruct Rate /Configurable Reconstruct Rate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Patrol Read Rate /) |
|
{ |
|
$line =~ s/^Patrol Read Rate /Configurable Patrol Read Rate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Alarm Control /) |
|
{ |
|
$line =~ s/^Alarm Control /Configurable Alarm Control /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Spanning /) |
|
{ |
|
$line =~ s/^Spanning /Spanning Supported /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /Hot Spare /) |
|
{ |
|
$line =~ s/Hot Spare /Hot Spare Supported /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Foreign Config Import /) |
|
{ |
|
$line =~ s/^Foreign Config Import /Foreign Config Import Supported /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Self Diagnostic /) |
|
{ |
|
$line =~ s/^Self Diagnostic /Self Diagnostic Supported /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Abort CC on Error /) |
|
{ |
|
$line =~ s/^Abort CC on Error /Configurable Abort CC on Error /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Block SSD Write Disk Cache Change /) |
|
{ |
|
$line =~ s/^Block SSD Write Disk Cache Change /Configurable Block SSD Write Disk Cache Change /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# Mangle supported adapter physical disk operation variables. |
|
if ($in_supported_pd_ops) |
|
{ |
|
if ($line =~ /^Supported VD Operations/) |
|
{ |
|
$in_supported_pd_ops = 0; |
|
$in_supported_vd_ops = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_supported_pd_ops => $in_supported_pd_ops, |
|
in_supported_vd_ops => $in_supported_vd_ops, |
|
}}); |
|
} |
|
if ($line =~ /^Deny Locate /) |
|
{ |
|
$line =~ s/^Deny Locate /Deny Physical Disk Locate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Read Policy /) |
|
{ |
|
$line =~ s/^Read Policy /Physical Disk Read Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Write Policy /) |
|
{ |
|
$line =~ s/^Write Policy /Physical Disk Write Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# Mangle supported adapter virtual drive operation variables. |
|
if ($in_supported_vd_ops) |
|
{ |
|
if ($line =~ /^Advanced Software Option/) |
|
{ |
|
$in_supported_vd_ops = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_supported_vd_ops => $in_supported_vd_ops }}); |
|
} |
|
if ($line =~ /^Deny Locate /) |
|
{ |
|
$line =~ s/^Deny Locate /Deny Virtual Disk Locate /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Read Policy /) |
|
{ |
|
$line =~ s/^Read Policy /Virtual Disk Read Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Write Policy /) |
|
{ |
|
$line =~ s/^Write Policy /Virtual Disk Write Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# Mangle hardware config variables. |
|
if ($line =~ /^HwCfg/) |
|
{ |
|
$in_hardware_config = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "in_hardware_config" => $in_hardware_config }}); |
|
} |
|
if ($in_hardware_config) |
|
{ |
|
if ($line =~ /^Policies/) |
|
{ |
|
$in_hardware_config = 0; |
|
$in_policies = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_hardware_config => $in_hardware_config, |
|
in_policies => $in_policies, |
|
}}); |
|
} |
|
if ($line =~ /^BBU /) |
|
{ |
|
$line =~ s/^BBU /BBU Connected /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# Mangle policy variables. |
|
if ($in_policies) |
|
{ |
|
if ($line =~ /^Boot/) |
|
{ |
|
$in_policies = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_policies => $in_policies }}); |
|
} |
|
if ($line =~ /^Disable Online Controller Reset /) |
|
{ |
|
$line =~ s/^Disable Online Controller Reset /Disable Online Controller Reset Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Expose Enclosure Devices /) |
|
{ |
|
$line =~ s/^Expose Enclosure Devices /Expose Enclosure Devices Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Maintain PD Fail History /) |
|
{ |
|
$line =~ s/^Maintain PD Fail History /Maintain PD Fail History Policy /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# Mangle defaults variables |
|
if ($line =~ /^Defaults/) |
|
{ |
|
$in_defaults = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_defaults => $in_defaults }}); |
|
} |
|
if ($in_defaults) |
|
{ |
|
if ($line =~ /^Capabilities/) |
|
{ |
|
$in_defaults = 0; |
|
$in_capabilities = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
in_defaults => $in_defaults, |
|
in_capabilities => $in_capabilities, |
|
}}); |
|
} |
|
if ($line =~ /^Disable Online Controller Reset /) |
|
{ |
|
$line =~ s/^Disable Online Controller Reset /Disable Online Controller Reset Default /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Expose Enclosure Devices /) |
|
{ |
|
$line =~ s/^Expose Enclosure Devices /Expose Enclosure Devices Default /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
if ($line =~ /^Maintain PD Fail History /) |
|
{ |
|
$line =~ s/^Maintain PD Fail History /Maintain PD Fail History Default /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
|
|
# Many of the variables in the 'Defaults' section are also used for their current |
|
# values. So to help differentiate them, we're going to prefix the variables with |
|
# 'Default '. |
|
if (($in_defaults) && ($line =~ / = /)) |
|
{ |
|
$line = "Default ".$line if $line !~ /^Default /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
} |
|
} |
|
|
|
# Mangle capability variables. |
|
if ($in_capabilities) |
|
{ |
|
if ($line =~ /^Scheduled Tasks/) |
|
{ |
|
$in_capabilities = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_capabilities => $in_capabilities }}); |
|
} |
|
if ($line =~ /^Boot Volume Supported /) |
|
{ |
|
$line =~ s/^Boot Volume Supported /Boot Volume Capable /; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
} |
|
} |
|
|
|
# T10-PI (T10 working group, Protection Information) has three levels (Taken from the Seagate |
|
# PDF listed below): |
|
# Type 0 - Describes a drive that is not formatted with PI information bytes. This allows |
|
# for legacy support in non-PI systems. |
|
# Type 1 - Provides support of PI protection using 10- and 16-byte commands. The RDPROTECT |
|
# and WRTPROTECT bits allow for checking control through the CDB. Eight bytes of |
|
# Protection Information are transmitted at sector boundaries across the interface |
|
# if RDPROTECT and WRTPROTECT bits are non-zero values. Type I does not allow the |
|
# use of 32-byte commands. |
|
# Type 2 - Provides checking control and additional expected fields within the 32-byte CDBs. |
|
# Eight bytes of Protection Information are transmitted at sector boundaries across |
|
# the interface if RDPROTECT and WRTPROTECT bits are non-zero values. Type II does |
|
# allow the use of 10- and 16-byte commands with zero values in the RDPROTECT and |
|
# WRTPROTECT fields. The drive will generate a dummy (for example, 0xFFFF) eight |
|
# bytes of Protection Information in the media, but these eight bytes will not be |
|
# transferred to the host during read. |
|
# Type 3 - ? (GUARD tag, reference tag and app tag are combined) |
|
# - http://www.snia.org/sites/default/education/tutorials/2008/fall/storage/RichardVanderbilt_Why_Data_Integrity_rev2.pdf |
|
# Protection is enabled and the 32-byte commands are not valid. The Reference Tag is |
|
# not defined and may be used as an extension of the Application Tag. The drive will |
|
# not check the Reference Tag. |
|
# - https://www.hgst.com/sites/default/files/resources/End-to-end_Data_Protection.pdf |
|
# Type 3 does not define the ref tag. |
|
# - http://lxr.free-electrons.com/source/block/t10-pi.c |
|
# |
|
|
|
# LSI loves to randomly sticking things together... |
|
$line =~ s/BatteryFRU/Battery FRU/; |
|
$line =~ s/ChipRevision/Chip Revision/; |
|
$line =~ s/DisableHII/Disable HII/; |
|
$line =~ s/EnableCrashDump/Enable Crash-Dump/; |
|
$line =~ s/EnableLDBBM/Enable LD_BBM/; |
|
$line =~ s/elementcount/element_count/i; |
|
$line =~ s/perio/per_io/i; |
|
|
|
### NOTE: ROC is RAID on Chip, which is what they call their controller's ASIC |
|
# and they love their weird short forms |
|
$line =~ s/Ctrl/Controller/i; |
|
$line =~ s/Mfg/Manufacture/i; |
|
$line =~ s/Cfg/Config/i; |
|
$line =~ s/Perf /Performance /i; |
|
$line =~ s/ Ext / External /i; |
|
$line =~ s/ VD/ Virtual Disk/i; |
|
$line =~ s/ VDs/ Virtual Disks/i; |
|
$line =~ s/VD /Virtual Disk /i; |
|
$line =~ s/ PD/ Physical Disk/i; |
|
$line =~ s/ PI/ Protection Information/i; |
|
$line =~ s/ LDPI/ Logical Disk Protection Information/i; # https://www.seagate.com/files/staticfiles/docs/pdf/whitepaper/safeguarding-data-from-corruption-technology-paper-tp621us.pdf |
|
$line =~ s/ CC/ Consistency Check/i; |
|
$line =~ s/ BGI/ Background Initialization/i; |
|
$line =~ s/ BGI/ Background/i; |
|
$line =~ s/ LD/ Logical Device/i; |
|
$line =~ s/ FW/ Firmware/i; |
|
$line =~ s/ HII/ Human Interface Infrastructure/i; |
|
$line =~ s/ PFK/ Premium Feature Key/i; |
|
$line =~ s/ WB/ Write-Back/i; |
|
$line =~ s/SSC /Security Subsystem Class /i; # https://en.wikipedia.org/wiki/Opal_Storage_Specification |
|
$line =~ s/ SMP/ Serial Management Protocol/i; # https://en.wikipedia.org/wiki/Serial_Attached_SCSI#Characteristics |
|
$line =~ s/ STP/ Serial ATA Tunneling Protocol/i; # https://en.wikipedia.org/wiki/Serial_Attached_SCSI#Characteristics |
|
$line =~ s/Phys /Physical Layers /i; # 12Gps MegaRAID SAS Software User Guide, March 14, 2016, 4.14.8, https://en.wikipedia.org/wiki/PHY_(chip) |
|
$line =~ s/Phy /Physical Layer /i; # 12Gps MegaRAID SAS Software User Guide, March 14, 2016, 4.14.8, https://en.wikipedia.org/wiki/PHY_(chip) |
|
$line =~ s/ OCE/ Online Capacity Expansion/i; # 12Gps MegaRAID SAS Software User Guide, March 14, 2016, 5.5.14 -> 5 |
|
$line =~ s/ RLM/ RAID Level Migration/i; # 12Gps MegaRAID SAS Software User Guide, March 14, 2016, 5.5.14 -> 5 |
|
$line =~ s/ EKM/ External Key Management/i; |
|
$line =~ s/ BBM/ Bad Block Management/i; |
|
$line =~ s/ QD/ Queue Depth/i; |
|
$line =~ s/NCQ/Native Command Queuing/i; # https://en.wikipedia.org/wiki/Native_Command_Queuing |
|
$line =~ s/ LDBBM/ Logical Disk Bad Block Management/i; |
|
$line =~ s/TPM/Trusted Platform Module/i; # https://en.wikipedia.org/wiki/Trusted_Platform_Module |
|
$line =~ s/\(hrs\)/\(#!variable!scan_storcli_unit_0002!#\)/i; |
|
$line =~ s/ hrs/ #!variable!scan_storcli_unit_0002!#/i; |
|
$line =~ s/ZCR /Zero-Channel RAID /i; |
|
$line =~ s/R1E /RAID 1E /i; |
|
$line =~ s/ R10/ RAID 10/i; |
|
$line =~ s/RAID(\d+)/RAID $1/gi; |
|
$line =~ s/TTY /Terminal /i; |
|
$line =~ s/CME /Continuous Media Error/i; |
|
$line =~ s/SGE /Scatter-Gather Element/i; # https://en.wikipedia.org/wiki/Vectored_I/O |
|
|
|
# Standardize some random strings with the same meaning |
|
$line =~ s/Id /ID /; |
|
$line =~ s/ NA/ N\/A/; |
|
$line =~ s/Bios/BIOS/; |
|
$line =~ s/S\.M\.A\.R\.T\./SMART/i; |
|
$line =~ s/S\.M\.A\.R\.T/SMART/i; |
|
|
|
# And randomly using sentances... |
|
$line =~ s/A rollback operation is in progress/Roll-back operation in progress/i; |
|
$line =~ s/must be rebooted to complete security operation/Reboot Required for Security Operation/i; |
|
$line =~ s/Maximum number of direct attached drives to spin up in 1 min/direct attached drives spun-up per minute/i; |
|
|
|
# And things that break variables when they change |
|
$line =~ s/\(Default\)//; |
|
$line =~ s/Sesmonitoring/SCSI Enclosure Service Monitoring/i; # https://en.wikipedia.org/wiki/SES-2_Enclosure_Management |
|
$line =~ s/SecurityonJBOD/Security on JBOD/i; |
|
$line =~ s/ForceFlash/Force Flash/i; |
|
$line =~ s/DisableImmediateIO/Disable Immediate IO/i; |
|
$line =~ s/LargeIOSupport/Large IO Support/i; |
|
$line =~ s/DrvActivityLEDSetting/Drive Activity LED Setting/i; |
|
$line =~ s/FlushWriteVerify/Flush Write Verify/i; |
|
$line =~ s/CPLDUpdate/Complex Programmable Logic Device Update/i; # https://en.wikipedia.org/wiki/Complex_programmable_logic_device |
|
$line =~ s/ForceTo512e/Force to 512e/i; # 512-byte sector size emulation |
|
$line =~ s/discardCacheDuringLDDelete/Discard Cache During Logical Disk Delete/; |
|
$line =~ s/Breakmirror/Break Mirror/i; # 12Gps MegaRAID SAS Software User Guide, March 14, 2016, 4.14.16 |
|
$line =~ s/Cachebypass/Cache Bypass/i; |
|
$line =~ s/PolaritySplit/Polarity Split/i; |
|
$line =~ s/EnableCrashDump/Enable Crash Dump/i; |
|
$line =~ s/PowerSave/Power Save/i; |
|
|
|
push @{$controller_data}, $line; |
|
} |
|
|
|
# If I didn't find a serial number, something went wrong. |
|
if (not $serial_number) |
|
{ |
|
# Error out. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1 , key => "scan_storcli_error_0006", variables => { adapter => $adapter }}); |
|
$anvil->nice_exit({exit_code => 6}); |
|
} |
|
|
|
# Get the current alarm state. |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{alarm_state}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
|
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^Alarm\s+(.*)$/i) |
|
{ |
|
my $state = $1; |
|
$line = "Alarm State = ".$state; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# Get the rebuild rate |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{rebuild_rate}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^Rebuildrate\s+(\d+)%$/i) |
|
{ |
|
my $rate = $1; |
|
$line = "Rebuild Rate % = ".$rate; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# Get the background initialization rate |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{bgi_rate}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^BGI Rate\s+(\d+)%$/i) |
|
{ |
|
my $rate = $1; |
|
$line = "Background Initialization Rate % = ".$rate; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# Get the consistency check rate |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{cc_rate}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^CC Rate\s+(\d+)%$/i) |
|
{ |
|
my $rate = $1; |
|
$line = "Consistency Check Rate % = ".$rate; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# Get the patrol read rate |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{pr_rate}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^Patrol Read Rate\s+(\d+)%$/i) |
|
{ |
|
my $rate = $1; |
|
$line = "Patrol Read Rate % = ".$rate; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# Get the performance mode |
|
undef $output; |
|
undef $return_code; |
|
($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." /c".$adapter." ".$anvil->data->{'scan-storcli'}{arguments}{performance_mode}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$line = $anvil->Words->clean_spaces({string => $line}); |
|
$line =~ s/\s+:/:/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /^Perf Mode\s+(.*)$/i) |
|
{ |
|
my $mode = $1; |
|
$line = "Performance Mode = ".$mode; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< line" => $line }}); |
|
push @{$controller_data}, $line; |
|
} |
|
} |
|
|
|
# If we're alive, we're ready to proceed. |
|
foreach my $line (@{$controller_data}) |
|
{ |
|
my $type = "variable"; |
|
if ($line =~ /^(.*?)\s+=\s+(.*)$/) |
|
{ |
|
my $variable = $1; |
|
my $value = $2; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
|
|
# If the variable has units, pull them out. |
|
if ($variable =~ /\((\w+B)\)$/i) |
|
{ |
|
my $units = $1; |
|
$variable =~ s/\($units\)//i; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+$//; |
|
my $size = $anvil->Convert->human_readable_to_bytes({size => $value, type => $units, base2 => 1})." #!string!scan_storcli_unit_0001!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
units => $units, |
|
size => $size, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(Degree Celsius\)/i) |
|
{ |
|
# $variable =~ s/\(Degree Celsius\)/ C/i; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+$//; |
|
$variable =~ s/\s+/ /; |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
type => $type, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(Degree Fahrenheit\)/i) |
|
{ |
|
# Covert to °C |
|
$variable =~ s/\(Degree Fahrenheit\)//i; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+$//; |
|
$value = $anvil->Convert->fahrenheit_to_celsius({temperature => $value}); |
|
$type = "temperature"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
type => $type, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(hours\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(hours\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0002!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(hour\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(min\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0003!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(mins\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(mins\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0004!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(min\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(min\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0005!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(secs\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(secs\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
elsif ($variable =~ /\(sec\)/i) |
|
{ |
|
# THis will get translated when generating an alert |
|
$variable =~ s/\(sec\)//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/^\s+//; |
|
$variable =~ s/\s+/ /g; |
|
$value .= " #!variable!scan_storcli_unit_0007!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
variable => $variable, |
|
value => $value, |
|
}}); |
|
} |
|
|
|
# Convert some values. |
|
if ($value =~ /(\d\d)\/(\d\d)\/(\d\d\d\d), (\d\d:\d\d:\d\d)/) |
|
{ |
|
# mm/dd/yyyy -> yyyy/mm/dd |
|
$value = $3."/".$1."/".$2.", ".$4; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /(\d+) hrs/) |
|
{ |
|
$value = $1." #!variable!scan_storcli_unit_0002!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /\(hrs\)/) |
|
{ |
|
$value =~ s/\(hrs\)/\(#!variable!scan_storcli_unit_0002!#\)/; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /^(\d+)s/) |
|
{ |
|
$value = $1." #!variable!scan_storcli_unit_0006!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /^0x\w+$/) |
|
{ |
|
# Hex value, leave it alone |
|
$anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"controller::serial_number::${serial_number}::${type}::${variable}" => $anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable}, |
|
}}); |
|
next; |
|
} |
|
if (($value =~ /^(\d+\s*[A-Za-z]+B)$/i) or ($value =~ /^(\d+\.\d+\s*[A-Za-z]+B)$/i)) |
|
{ |
|
my $size = $1; |
|
$value = $anvil->Convert->human_readable_to_bytes({base2 => 1, size => $size}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size => $size, |
|
value => $value, |
|
}}); |
|
} |
|
if ($value =~ /^00\/00\/00$/i) |
|
{ |
|
# N/A |
|
$value = "#!variable!scan_storcli_unit_0008!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
|
|
if ($value =~ /^AWB$/i) |
|
{ |
|
$value = "#!variable!scan_storcli_unit_0009!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /^WB$/i) |
|
{ |
|
$value = "#!variable!scan_storcli_unit_0010!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /^WT$/i) |
|
{ |
|
$value = "#!variable!scan_storcli_unit_0011!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
if ($value =~ /^(\d+) sectors/i) |
|
{ |
|
$value = $1." #!variable!scan_storcli_unit_0012!#"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { value => $value }}); |
|
} |
|
|
|
# Store it |
|
if (exists $anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable}) |
|
{ |
|
# Conflict! This is a dirty way to keep them separate |
|
$variable .= " 2"; |
|
} |
|
|
|
$variable = process_variable_name($anvil, $variable); |
|
$anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable} = $value; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
"controller::serial_number::${serial_number}::${type}::${variable}" => $anvil->data->{controller}{serial_number}{$serial_number}{$type}{$variable}, |
|
}}); |
|
} |
|
} |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { serial_number => $serial_number }}); |
|
return($serial_number); |
|
} |
|
|
|
# This processes variable names to flatten them and remove spaces and special characters. |
|
sub process_variable_name |
|
{ |
|
my ($anvil, $variable) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ">> variable" => $variable }}); |
|
|
|
$variable = lc($variable); |
|
$variable =~ s/ /_/g; |
|
$variable =~ s/-/_/g; |
|
$variable =~ s/&/and/g; |
|
$variable =~ s/\//_or_/g; |
|
$variable =~ s/_%/_percent/g; |
|
$variable =~ s/{_}+/_/g; |
|
$variable =~ s/^_+//g; |
|
$variable =~ s/_+$//g; |
|
$variable =~ s/(\w)\(/$1_\(/; |
|
$variable =~ s/\((.*?)\)/-_$1/g; |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< variable" => $variable }}); |
|
return($variable); |
|
} |
|
|
|
# This does two things; It checks to see if storcli64 is installed (exits '1' if not, exits '2' if not |
|
# executable) and then checks to see if any controllers are found in the system (exits '3' if not). |
|
sub find_lsi_controllers |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# This will keep track of how many controllers we find. |
|
my $adapter_count = 0; |
|
|
|
# Vendor-specific copies of storcli replace it. So first, check to see if that is the case on this |
|
# node. |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "path::exe::perccli64" => $anvil->data->{path}{exe}{perccli64} }}); |
|
if (-e $anvil->data->{path}{exe}{perccli64}) |
|
{ |
|
# It does, replace the 'storcli64' path. |
|
$anvil->data->{path}{exe}{storcli64} = $anvil->data->{path}{exe}{perccli64}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "path::exe::storcli64" => $anvil->data->{path}{exe}{storcli64} }}); |
|
} |
|
|
|
# Do we have storcli64 installed? |
|
if (not -e $anvil->data->{path}{exe}{storcli64}) |
|
{ |
|
# Nope, Call lspci to see if there's a MegaRAID controller. If there is, the user may need to |
|
# install the RPM. |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{lspci}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
|
|
my $megaraid_installed = 0; |
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /MegaRAID/i) |
|
{ |
|
# This host appears to have a RAID card, but it's not installed. Lets try to |
|
# install it for them. |
|
$megaraid_installed = install_storcli($anvil); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { megaraid_installed => $megaraid_installed }}); |
|
} |
|
} |
|
|
|
# exit. |
|
if (not $megaraid_installed) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "scan_storcli_error_0001", variables => { path => $anvil->data->{path}{exe}{storcli64} }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
} |
|
|
|
# Make sure it is executable |
|
if (not -x $anvil->data->{path}{exe}{storcli64}) |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "scan_storcli_error_0002", variables => { path => $anvil->data->{path}{exe}{storcli64} }}); |
|
$anvil->nice_exit({exit_code => 2}); |
|
} |
|
|
|
# Still alive? Good! Look for controllers now. |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{storcli64}." ".$anvil->data->{'scan-storcli'}{arguments}{adapter_count}}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
|
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
|
|
if ($line =~ /Controller Count = (\d+)/i) |
|
{ |
|
$adapter_count = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { adapter_count => $adapter_count }}); |
|
} |
|
} |
|
|
|
# Have we any adapters? |
|
if ($adapter_count > 0) |
|
{ |
|
$anvil->data->{'scan-storcli'}{adapter_count} = $adapter_count; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 0, level => 2, key => "scan_storcli_log_0001", variables => { |
|
count => $anvil->data->{'scan-storcli'}{adapter_count}, |
|
}}); |
|
} |
|
else |
|
{ |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 2, level => 0, key => "scan_storcli_error_0003", variables => { |
|
path => $anvil->data->{path}{exe}{storcli64}, |
|
}}); |
|
$anvil->nice_exit({exit_code => 3}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub install_storcli |
|
{ |
|
my ($anvil) = @_; |
|
|
|
# Tell the user what we're doing. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "scan_storcli_note_0071"}); |
|
|
|
# Is this a Dell? |
|
my $is_dell = 0; |
|
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{dmidecode}." --string system-manufacturer"}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
|
|
foreach my $line (split/\n/, $output) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
if ($line =~ /Dell/i) |
|
{ |
|
$is_dell = 1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { is_dell => $is_dell }}); |
|
} |
|
} |
|
|
|
my $rpm_name = $is_dell ? "perccli" : "storcli"; |
|
my $shell_call = $anvil->data->{path}{exe}{dnf}." -y install ".$rpm_name; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
|
($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
return_code => $return_code, |
|
}}); |
|
|
|
# Check now to see if the program is installed. If it is, register an alert announcing we installed it. |
|
my $program = $is_dell ? $anvil->data->{path}{exe}{perccli64} : $anvil->data->{path}{exe}{storcli64}; |
|
if (-e $program) |
|
{ |
|
# Installed successfully! |
|
my $variables = { |
|
rpm => $rpm_name, |
|
}; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_storcli_note_0072", variables => $variables}); |
|
$anvil->Alert->register({ |
|
alert_level => "notice", |
|
message => "scan_storcli_note_0072", |
|
show_header => 1, |
|
variables => $variables, |
|
sort_position => 0, |
|
set_by => $THIS_FILE, |
|
}); |
|
|
|
# Before we return, if we installed for Dell, switch out the 'storcli' program path. |
|
if ($is_dell) |
|
{ |
|
$anvil->data->{path}{exe}{storcli64} = $anvil->data->{path}{exe}{perccli64}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "path::exe::storcli64" => $anvil->data->{path}{exe}{storcli64} }}); |
|
} |
|
|
|
return(1); |
|
} |
|
else |
|
{ |
|
# Didn't work. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, key => "scan_storcli_note_0073"}); |
|
} |
|
|
|
return(0); |
|
}
|
|
|