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.
10184 lines
516 KiB
10184 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); |
|
|
|
# Shut down. |
|
$anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); |
|
|
|
|
|
############################################################################################################# |
|
# 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") && (lc($value) ne "absent")) |
|
{ |
|
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->Database->refresh_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->Database->refresh_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->Database->refresh_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->Database->refresh_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->Database->refresh_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->Database->refresh_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->Database->refresh_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->Database->refresh_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, |
|
|