#!/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 HPE type RAID controllers using the 'hpacucli' command line tool. # # https://alteeve.com # # Exit Codes: # 0 - Success # 1 - hpacucli not installed # 2 - hpacucli is installed but it is not executable. # 3 - No HPE type controllers found. # 4 - Controller numeric value is invalid. # 5 - Cache module numeric value is invalid. # 6 - Array numeric value is invalid. # 7 - Logical drive numeric value is invalid. # 8 - Physical drive numeric value is invalid. # 9 - Physical drive has no serial number. # # 255 - The host's UUID isn't in the hosts table yet, ScanCore itself hasn't been run. # # TODO: # - # # 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 AN::Tools; use Data::Dumper; use Math::BigInt; no warnings 'recursion'; # Disable buffering. $| = 1; # Figure out who and where I am. my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $scancore_directory = ($running_directory =~ /^(.*?)\/agents\/$THIS_FILE$/)[0]; # Get the handle to the AN::Tools and preset some variables I will use. my $an = AN::Tools->new({data => { health => { old => {}, new => {}, }, path => { core_strings => "$scancore_directory/ScanCore.xml", sql => "$running_directory/$THIS_FILE.sql", strings => "$running_directory/$THIS_FILE.xml", }, scancore => { archive => { directory => "/var/ScanCore/archives/", division => 60000, trigger => 100000, count => 50000, dump_file_header => " SET statement_timeout = 0; SET lock_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SET check_function_bodies = false; SET client_min_messages = warning; SET row_security = off; SET search_path = history, pg_catalog; ", }, }, # This is used so that the user can set the language in on striker.conf variable. 'scan-hpacucli' => { # 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 => {}, }, physical_drives => { by_serial => {}, by_uuid => {}, }, # Checking the drives for errors is expensive, so it is only done every hour (or # there abouts). Change the interval if you want to check more or less often. diagnostics_interval => 600, disable => 0, ignore_maximum_temperature => 0, language => "en_CA", log_level => 1, log_language => "en_CA", log_file => "/var/log/ScanCore.log", log_db_transactions => 0, thresholds => { # 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 # http://toshiba.semicon-storage.com/us/product/storage-products/enterprise-ssd/px02smb-px02smfxxx.html high_warning => 50, high_critical => 55, low_warning => 5, low_critical => 0, jump => 5, buffer => 2, }, # I've not found official ranges on this yet... These are best-guess values controller_temperature => { high_warning => 100, high_critical => 105, low_warning => 15, low_critical => 10, jump => 10, buffer => 5, }, # I've not found official ranges on this yet... These are best-guess values capacitor => { high_warning => 50, high_critical => 55, low_warning => 15, low_critical => 10, jump => 5, buffer => 3, }, # https://support.hpe.com/hpsc/doc/public/display?docId=c04441382 cache => { high_warning => 50, high_critical => 55, low_warning => 15, low_critical => 10, jump => 5, buffer => 3, }, }, }, sys => { alert_sort => 1, controller => {}, controller_count => 0, alert_sort => 1, # When a lock is requested, this is set to the time the lock was set. # DB->do_db_write() and DB->do_db_read() will check this and if its age is >50% of # scancore::locking::reap_age, it will renew the lock. lock_active => 0, process_diagnostics => 0, sql => [], }, }, }); # Read the config file $an->Storage->read_conf({file => $an->data->{path}{striker_config}}); # Set some defaults $an->default_language ($an->data->{'scan-hpacucli'}{language}); $an->default_log_language($an->data->{'scan-hpacucli'}{log_language}); $an->default_log_file ($an->data->{'scan-hpacucli'}{log_file}); # Set the log level. $an->Log->level($an->data->{'scan-hpacucli'}{log_level}); $an->Log->db_transactions(1) if $an->data->{'scan-hpacucli'}{log_db_transactions}; # Read in the language strings. $an->Storage->read_words({file => $an->data->{path}{strings}}); $an->Storage->read_words({file => $an->data->{path}{core_strings}}); $an->Storage->read_words({file => $an->data->{path}{striker_strings}}); # Get the switches before printing anything in case the user is asking for help. $an->Get->switches(); $an->Log->adjust_log_level({key => $THIS_FILE}); # Help? if (($an->data->{switches}{h}) or ($an->data->{switches}{'?'}) or ($an->data->{switches}{help})) { # Help! print_usage($an); $an->nice_exit({exit_code => 0}); } # Exit if we're disabled. if ($an->data->{'scan-hpacucli'}{disable}) { $an->nice_exit({exit_code => 1}); } # I'll need to loop through the DBs and ensure our schema is loaded for each one. my $connections = $an->DB->connect_to_databases({file => $THIS_FILE}); $an->Log->entry({ log_level => 3, message_key => "notice_message_0013", message_variables => { connections => $connections }, file => $THIS_FILE, line => __LINE__}); # Make sure this host's UUID is in the 'hosts' table. If the user is running this directly without first # running ScanCore, it won't be. if (not $an->DB->verify_host_uuid()) { # ScanCore hasn't run, this host isn't in the 'hosts' table. $an->Alert->error({title_key => "an_0003", message_key => "scancore_error_0020", message_variables => { uuid => $an->data->{sys}{host_uuid} }, code => 255, file => $THIS_FILE, line => __LINE__}); } # If we were called with '--prep-db', we'll prep the database schema regardless of whether clustat is found. if ($an->data->{switches}{'prep-db'}) { if ($connections) { prep_databases($an); } else { # Failed $an->Log->entry({log_level => 1, message_key => "scancore_warning_0031", file => $THIS_FILE, line => __LINE__}); print $an->String->get({key => "scancore_warning_0031"})."\n"; } } print $an->String->get({key => "scan_hpacucli_message_0001"})."\n"; # This does two things; It checks to see if hpacucli 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_hp_controllers($an); # We need to prep the database right away. prep_databases($an); # If we're still alive, start gathering data. gather_data($an); # Archive, if needed. archive_if_needed($an); # Look to see if any databases need to be updated. update_db($an); # Figure out, other than temperatures, what should be added to or removed from health. pre_process_health($an); # Look for changes. find_changes($an); # Process temperatures! This also sets health values for warning and critical temperatures so make sure we # always call this before process_health(). process_temperatures($an); # Finally, process health weights. process_health($an); # Update the database $an->DB->update_time({file => $THIS_FILE}); # Clean up and go away. $an->nice_exit({exit_code => 0}); ############################################################################################################# # Function below # ############################################################################################################# # 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 ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "find_changes" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # 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($an); ### 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($an); # Now that controllers have been proceesed, we can process drives (and their arrays) process_drives($an); # If we processed diagnostics, update if ($an->data->{sys}{process_diagnostics}) { my $query = " UPDATE hpacucli_controllers SET hpacucli_controller_last_diagnostics = ".time.", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); $an->DB->do_db_write({query => $query, source => $THIS_FILE, line => __LINE__}); } 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 ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_health" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # This will hold our updates. $an->data->{sys}{sql} = []; # 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 = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." AND health_agent_name = ".$an->data->{sys}{use_db_fh}->quote($THIS_FILE)." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); my $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); 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]; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "health_uuid", value1 => $health_uuid, name2 => "health_agent_name", value2 => $health_agent_name, name3 => "health_source_name", value3 => $health_source_name, name4 => "health_source_weight", value4 => $health_source_weight, }, file => $THIS_FILE, line => __LINE__}); $an->data->{health}{old}{$health_source_name}{uuid} = $health_uuid; $an->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 %{$an->data->{health}{new}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); if (exists $an->data->{health}{old}{$health_source_name}) { # We've seen this before. Has it changed? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::old::${health_source_name}::value", value1 => $an->data->{health}{old}{$health_source_name}{value}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{health}{new}{$health_source_name} ne $an->data->{health}{old}{$health_source_name}{value}) { # It has changed, update it. my $query = " UPDATE health SET health_source_weight = ".$an->data->{sys}{use_db_fh}->quote($an->data->{health}{new}{$health_source_name}).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE health_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{health}{old}{$health_source_name}{uuid})." ;"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Delete the new old key, regardless of whether it has changed now. delete $an->data->{health}{old}{$health_source_name}; } else { # New entry, INSERT it. my $query = " INSERT INTO health ( health_uuid, health_host_uuid, health_agent_name, health_source_name, health_source_weight, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($THIS_FILE).", ".$an->data->{sys}{use_db_fh}->quote($health_source_name).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{health}{new}{$health_source_name}).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } # Delete any old entries that are left. foreach my $health_source_name (sort {$a cmp $b} keys %{$an->data->{health}{old}}) { # Well set the source name to 'DELETED'. my $query = " UPDATE health SET health_source_name = 'DELETED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE health_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{health}{old}{$health_source_name}{uuid})." ;"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; $query = " DELETE FROM health WHERE health_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{health}{old}{$health_source_name}{uuid})." ;"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Now commit the changes. $an->DB->commit_sql({source => $THIS_FILE, line => __LINE__}); 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 ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_temperatures" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); ### 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_celsius, temperature_state, temperature_is FROM temperature WHERE temperature_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." AND temperature_agent_name = ".$an->data->{sys}{use_db_fh}->quote($THIS_FILE)." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); my $results = $an->DB->do_db_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_celsius = $row->[3]; my $temperature_state = $row->[4]; my $temperature_is = $row->[5]; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "temperature_uuid", value1 => $temperature_uuid, name2 => "temperature_sensor_name", value2 => $temperature_sensor_name, name3 => "temperature_sensor_host", value3 => $temperature_sensor_host, name4 => "temperature_celsius", value4 => $temperature_celsius, name5 => "temperature_state", value5 => $temperature_state, name6 => "temperature_is", value6 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); $an->data->{old}{temperature}{$temperature_sensor_name}{$temperature_sensor_host} = { temperature_uuid => $temperature_uuid, temperature_celsius => $temperature_celsius, temperature_state => $temperature_state, temperature_is => $temperature_is, }; } # Loop through the temperature from this scan. foreach my $variable (sort {$a cmp $b} keys %{$an->data->{new}{temperature}}) { foreach my $serial_number (sort {$a cmp $b} keys %{$an->data->{new}{temperature}{$variable}}) { my $new_temperature_celsius = $an->data->{new}{temperature}{$variable}{$serial_number}{temperature_celsius}; my $new_temperature_state = $an->data->{new}{temperature}{$variable}{$serial_number}{temperature_state}; my $new_temperature_is = $an->data->{new}{temperature}{$variable}{$serial_number}{temperature_is}; $an->Log->entry({log_level => 3, message_key => "an_variables_0005", message_variables => { name1 => "variable", value1 => $variable, name2 => "serial_number", value2 => $serial_number, name3 => "new_temperature_celsius", value3 => $new_temperature_celsius, name4 => "new_temperature_state", value4 => $new_temperature_state, name5 => "new_temperature_is", value5 => $new_temperature_is, }, file => $THIS_FILE, line => __LINE__}); # If the state is 'warning', set a health weight of 1 and set critical to 2. if ($new_temperature_state eq "warning") { my $health_source_name = "temperature:".$serial_number; $an->data->{health}{new}{$health_source_name} = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_temperature_state eq "critical") { my $health_source_name = "temperature:".$serial_number; $an->data->{health}{new}{$health_source_name} = 2; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } # Now see if the variable was seen before and, if so, if it changed. if (ref($an->data->{old}{temperature}{$variable}{$serial_number})) { # Update the existing entry, if needed. my $temperature_uuid = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_uuid}; my $old_temperature_celsius = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_celsius}; my $old_temperature_state = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_state}; my $old_temperature_is = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_is}; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "temperature_uuid", value1 => $temperature_uuid, name2 => "old_temperature_celsius", value2 => $old_temperature_celsius, name3 => "old_temperature_state", value3 => $old_temperature_state, name4 => "old_temperature_is", value4 => $old_temperature_is, }, file => $THIS_FILE, line => __LINE__}); if (($new_temperature_celsius ne $old_temperature_celsius) or ($new_temperature_state ne $old_temperature_state) or ($new_temperature_is ne $old_temperature_is)) { # Something changed, update. my $query = " UPDATE temperature SET temperature_celsius = ".$an->data->{sys}{use_db_fh}->quote($new_temperature_celsius).", temperature_state = ".$an->data->{sys}{use_db_fh}->quote($new_temperature_state).", temperature_is = ".$an->data->{sys}{use_db_fh}->quote($new_temperature_is).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE temperature_uuid = ".$an->data->{sys}{use_db_fh}->quote($temperature_uuid)."; "; push @{$an->data->{sys}{sql}}, $query; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); } else { # No change. $an->Log->entry({log_level => 3, message_key => "scan_hpacucli_log_0002", message_variables => { sensor_name => $variable, sensor_host => $serial_number, }, file => $THIS_FILE, line => __LINE__}); } # We still want this value, so delete it from the hash so it doesn't get # deleted in the next step. delete $an->data->{old}{temperature}{$variable}{$serial_number}; } else { # New entry my $query = " INSERT INTO temperature ( temperature_uuid, temperature_host_uuid, temperature_sensor_host, temperature_sensor_name, temperature_agent_name, temperature_celsius, temperature_state, temperature_is, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($serial_number).", ".$an->data->{sys}{use_db_fh}->quote($variable).", ".$an->data->{sys}{use_db_fh}->quote($THIS_FILE).", ".$an->data->{sys}{use_db_fh}->quote($new_temperature_celsius).", ".$an->data->{sys}{use_db_fh}->quote($new_temperature_state).", ".$an->data->{sys}{use_db_fh}->quote($new_temperature_is).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." ); "; push @{$an->data->{sys}{sql}}, $query; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); } } } # Now, if any undeleted old entries remain, delete them from the database. foreach my $variable (sort {$a cmp $b} keys %{$an->data->{old}{temperature}}) { foreach my $serial_number (sort {$a cmp $b} keys %{$an->data->{old}{temperature}{$variable}}) { my $old_temperature_uuid = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_uuid}; my $old_temperature = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_celsius}; my $old_state = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_state}; my $old_is = $an->data->{old}{temperature}{$variable}{$serial_number}{temperature_is}; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "variable", value1 => $variable, name2 => "serial_number", value2 => $serial_number, name3 => "old_temperature_uuid", value3 => $old_temperature_uuid, name4 => "old_temperature", value4 => $old_temperature, name5 => "old_state", value5 => $old_state, name6 => "old_is", value6 => $old_is, }, file => $THIS_FILE, line => __LINE__}); # Mark the sensor as DELETEd. my $query = " UPDATE temperature SET temperature_state = 'DELETED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE temperature_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_temperature_uuid)."; "; push @{$an->data->{sys}{sql}}, $query; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $query = " DELETE FROM temperature WHERE temperature_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_temperature_uuid)."; "; push @{$an->data->{sys}{sql}}, $query; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); } } # Commit the queries. $an->DB->commit_sql({source => $THIS_FILE, line => __LINE__}); return(0); } # Process drives (and their arrays and logical drives). sub process_drives { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_drives" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Look for new, changed or deleted controllers. $an->data->{sys}{sql} = []; # This is to collected data from every sweep. foreach my $hpacucli_controller_serial_number (sort {$a cmp $b} keys %{$an->data->{controller}}) { # Controller data; next if $hpacucli_controller_serial_number eq "metadata"; my $hpacucli_controller_uuid = $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}; $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, name2 => "hpacucli_controller_uuid", value2 => $hpacucli_controller_uuid, }, file => $THIS_FILE, line => __LINE__}); # Array foreach my $hpacucli_array_name (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}}) { $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_array_name", value1 => $hpacucli_array_name, }, file => $THIS_FILE, line => __LINE__}); # Data, there is no temperature my $new_hpacucli_array_type = "virtual"; my $new_hpacucli_array_status = "virtual"; my $new_hpacucli_array_error_message = ""; if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{array_type}) { $new_hpacucli_array_type = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{array_type}; } if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{status}) { # Array transitions (OK -> Eject -> Plug back in) #scan-hpacucli 3117; - Data; status: [OK] #scan-hpacucli 3117; - Data; status: [Failed Physical Drive] #scan-hpacucli 3148; - Data; status: [OK] $new_hpacucli_array_status = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{status}; } if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message}) { $new_hpacucli_array_error_message = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message}; } $an->Log->entry({log_level => 2, message_key => "an_variables_0004", message_variables => { name1 => "hpacucli_array_name", value1 => $hpacucli_array_name, name2 => "new_hpacucli_array_type", value2 => $new_hpacucli_array_type, name3 => "new_hpacucli_array_status", value3 => $new_hpacucli_array_status, name4 => "new_hpacucli_array_error_message", value4 => $new_hpacucli_array_error_message, }, file => $THIS_FILE, line => __LINE__}); # Does this array exist already? my $hpacucli_array_uuid = $an->data->{'scan-hpacucli'}{virtual_drives}{by_name}{$hpacucli_array_name} ? $an->data->{'scan-hpacucli'}{virtual_drives}{by_name}{$hpacucli_array_name} : ""; if (($hpacucli_array_uuid) && (exists $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid})) { # Look for changes. my $old_hpacucli_array_controller_uuid = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_controller_uuid}; my $old_controller_serial_number = $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$old_hpacucli_array_controller_uuid}; my $old_hpacucli_array_type = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_type}; my $old_hpacucli_array_status = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_status}; my $old_hpacucli_array_error_message = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_error_message}; $an->Log->entry({log_level => 2, message_key => "an_variables_0005", message_variables => { name1 => "old_hpacucli_array_controller_uuid", value1 => $old_hpacucli_array_controller_uuid, name2 => "old_controller_serial_number", value2 => $old_controller_serial_number, name3 => "old_hpacucli_array_type", value3 => $old_hpacucli_array_type, name4 => "old_hpacucli_array_status", value4 => $old_hpacucli_array_status, name5 => "old_hpacucli_array_error_message", value5 => $old_hpacucli_array_error_message, }, file => $THIS_FILE, line => __LINE__}); # Delete the old one so we know we've seen it. delete $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}; # Has anything changed? Note that we don't check the name as that is how we # find if it exists already or not. if (($hpacucli_controller_serial_number ne $old_controller_serial_number) or ($new_hpacucli_array_type ne $old_hpacucli_array_type) or ($new_hpacucli_array_status ne $old_hpacucli_array_status) or ($new_hpacucli_array_error_message ne $old_hpacucli_array_error_message)) { ### Something changed. # If the array is not OK, clear alerts. if ($new_hpacucli_array_status ne $old_hpacucli_array_status) { my $title_key = "an_alert_title_0004"; my $message_key = "scan_hpacucli_note_0023"; # Came back or went OK? if ($old_hpacucli_array_status eq "VANISHED") { $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0032"; } elsif (lc($new_hpacucli_array_status) eq "ok") { $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0024"; } $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { name => $hpacucli_array_name, serial_number => $hpacucli_controller_serial_number, new_status => $new_hpacucli_array_status, old_status => $old_hpacucli_array_status, }, }); } # Did the controller change? if ($hpacucli_controller_serial_number ne $old_controller_serial_number) { # yup. This is a notice as the new controller will have # generated a warning alert. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0025", alert_message_variables => { name => $hpacucli_array_name, new_serial_number => $hpacucli_controller_serial_number, old_serial_number => $old_controller_serial_number, }, }); } # Has the error message changed? if ($new_hpacucli_array_error_message ne $old_hpacucli_array_error_message) { # Default is 'changed' my $title_key = "an_alert_title_0004"; my $message_key = "scan_hpacucli_note_0026"; if (not $new_hpacucli_array_error_message) { # Cleared $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0027"; } elsif (not $old_hpacucli_array_error_message) { # New error $message_key = "scan_hpacucli_note_0028"; } $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { name => $hpacucli_array_name, new_error_message => $new_hpacucli_array_error_message, old_error_message => $old_hpacucli_array_error_message, }, }); } # Did the controller change? if ($new_hpacucli_array_type ne $old_hpacucli_array_type) { # yup. This is a warning because it should never change. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0030", alert_message_variables => { name => $hpacucli_array_name, new_type => $new_hpacucli_array_type, old_type => $old_hpacucli_array_type, }, }); } # UPDATE my $query = " UPDATE hpacucli_arrays SET hpacucli_array_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", hpacucli_array_type = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_type).", hpacucli_array_status = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_status).", hpacucli_array_error_message = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_error_message).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # New. $hpacucli_array_uuid = $an->Get->uuid(); $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number} = $hpacucli_controller_uuid; $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid} = $hpacucli_controller_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::controllers::by_serial::${hpacucli_controller_serial_number}", value1 => $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}, name2 => "scan-hpacucli::controllers::by_uuid::${hpacucli_controller_uuid}", value2 => $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid}, }, file => $THIS_FILE, line => __LINE__}); print $THIS_FILE." ".__LINE__."; - New Array: [$hpacucli_array_name] (UUID: [$hpacucli_array_uuid]); Type: [$new_hpacucli_array_type], status: [$new_hpacucli_array_status], error message: [$new_hpacucli_array_error_message]\n"; # Alert the user if this isn't the virtual array. if ($hpacucli_array_name ne "ZZZZ") { # If the array is OK, it will be a notice. my $alert_level = "notice"; my $title_key = "an_alert_title_0003"; my $message_key = "scan_hpacucli_note_0021"; if (lc($new_hpacucli_array_status) ne "ok") { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0022"; } $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { name => $hpacucli_array_name, type => $new_hpacucli_array_type, status => $new_hpacucli_array_status, error => $new_hpacucli_array_error_message, }, }); } my $query = " INSERT INTO hpacucli_arrays ( hpacucli_array_uuid, hpacucli_array_host_uuid, hpacucli_array_controller_uuid, hpacucli_array_name, hpacucli_array_type, hpacucli_array_status, hpacucli_array_error_message, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_type).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_status).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_array_error_message).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Logical Drive foreach my $hpacucli_logical_drive_name (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}}) { # No thermal data my $hpacucli_logical_drive_uuid = $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name} ? $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name} : ""; my $new_hpacucli_logical_drive_caching = ""; my $new_hpacucli_logical_drive_os_device_name = ""; my $new_hpacucli_logical_drive_type = ""; my $new_hpacucli_logical_drive_raid_level = ""; my $new_hpacucli_logical_drive_size = ""; my $new_hpacucli_logical_drive_strip_size = ""; my $new_hpacucli_logical_drive_stripe_size = ""; my $new_hpacucli_logical_drive_status = ""; # If this is the virtual array, set the sizes to 0. if ($hpacucli_logical_drive_name eq "9999") { $new_hpacucli_logical_drive_size = 0; $new_hpacucli_logical_drive_strip_size = 0; $new_hpacucli_logical_drive_stripe_size = 0; } ### Gather the variables. # Caching if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{caching}) { $new_hpacucli_logical_drive_caching = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{caching}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_caching", value1 => $new_hpacucli_logical_drive_caching, }, file => $THIS_FILE, line => __LINE__}); } # Disk name (in the OS) if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{disk_name}) { $new_hpacucli_logical_drive_os_device_name = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{disk_name}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_os_device_name", value1 => $new_hpacucli_logical_drive_os_device_name, }, file => $THIS_FILE, line => __LINE__}); } # Drive type if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{drive_type}) { $new_hpacucli_logical_drive_type = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{drive_type}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_type", value1 => $new_hpacucli_logical_drive_type, }, file => $THIS_FILE, line => __LINE__}); } # RAID level if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{fault_tolerance}) { $new_hpacucli_logical_drive_raid_level = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{fault_tolerance}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_raid_level", value1 => $new_hpacucli_logical_drive_raid_level, }, file => $THIS_FILE, line => __LINE__}); } # Drive size - Needs to be converted to bytes at initial processing. if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{size}) { $new_hpacucli_logical_drive_size = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{size}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_size", value1 => $new_hpacucli_logical_drive_size." (".$an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_size}).")", }, file => $THIS_FILE, line => __LINE__}); } # Strip size if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{strip_size}) { $new_hpacucli_logical_drive_strip_size = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{strip_size}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_strip_size", value1 => $new_hpacucli_logical_drive_strip_size." (".$an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_strip_size}).")", }, file => $THIS_FILE, line => __LINE__}); } # Stripe size if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{full_stripe_size}) { $new_hpacucli_logical_drive_stripe_size = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{full_stripe_size}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_stripe_size", value1 => $new_hpacucli_logical_drive_stripe_size." (".$an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_stripe_size}).")", }, file => $THIS_FILE, line => __LINE__}); } # Status if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{status}) { $new_hpacucli_logical_drive_status = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{status}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_logical_drive_status", value1 => $new_hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); } $an->Log->entry({log_level => 2, message_key => "an_variables_0008", message_variables => { name1 => "new_hpacucli_logical_drive_caching", value1 => $new_hpacucli_logical_drive_caching, name2 => "new_hpacucli_logical_drive_os_device_name", value2 => $new_hpacucli_logical_drive_os_device_name, name3 => "new_hpacucli_logical_drive_type", value3 => $new_hpacucli_logical_drive_type, name4 => "new_hpacucli_logical_drive_raid_level", value4 => $new_hpacucli_logical_drive_raid_level, name5 => "new_hpacucli_logical_drive_size", value5 => $new_hpacucli_logical_drive_size, name6 => "new_hpacucli_logical_drive_strip_size", value6 => $new_hpacucli_logical_drive_strip_size, name7 => "new_hpacucli_logical_drive_stripe_size", value7 => $new_hpacucli_logical_drive_stripe_size, name8 => "new_hpacucli_logical_drive_status", value8 => $new_hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); if (($hpacucli_logical_drive_uuid) && (exists $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid})) { my $old_hpacucli_logical_drive_array_uuid = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_array_uuid}; my $old_hpacucli_logical_drive_name = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_name}; my $old_hpacucli_logical_drive_caching = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_caching}; my $old_hpacucli_logical_drive_os_device_name = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_os_device_name}; my $old_hpacucli_logical_drive_type = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_type}; my $old_hpacucli_logical_drive_raid_level = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_raid_level}; my $old_hpacucli_logical_drive_size = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_size}; my $old_hpacucli_logical_drive_strip_size = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_strip_size}; my $old_hpacucli_logical_drive_stripe_size = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_stripe_size}; my $old_hpacucli_logical_drive_status = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_status}; $an->Log->entry({log_level => 2, message_key => "an_variables_0011", message_variables => { name1 => "hpacucli_logical_drive_uuid", value1 => $hpacucli_logical_drive_uuid, name2 => "old_hpacucli_logical_drive_array_uuid", value2 => $old_hpacucli_logical_drive_array_uuid, name3 => "old_hpacucli_logical_drive_name", value3 => $old_hpacucli_logical_drive_name, name4 => "old_hpacucli_logical_drive_caching", value4 => $old_hpacucli_logical_drive_caching, name5 => "old_hpacucli_logical_drive_os_device_name", value5 => $old_hpacucli_logical_drive_os_device_name, name6 => "old_hpacucli_logical_drive_type", value6 => $old_hpacucli_logical_drive_type, name7 => "old_hpacucli_logical_drive_raid_level", value7 => $old_hpacucli_logical_drive_raid_level, name8 => "old_hpacucli_logical_drive_size", value8 => $old_hpacucli_logical_drive_size, name9 => "old_hpacucli_logical_drive_strip_size", value9 => $old_hpacucli_logical_drive_strip_size, name10 => "old_hpacucli_logical_drive_stripe_size", value10 => $old_hpacucli_logical_drive_stripe_size, name11 => "old_hpacucli_logical_drive_status", value11 => $old_hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); # Delete this so we know it was processed delete $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}; my $update = 0; my $recovered = ""; if ($new_hpacucli_logical_drive_caching ne $old_hpacucli_logical_drive_caching) { # Did it go enabled or disabled? $update = 1; my $alert_key = "scan_hpacucli_note_0034"; if (lc($new_hpacucli_logical_drive_caching) eq "enabled") { # We're back. $alert_key = "scan_hpacucli_note_0035"; } if (lc($new_hpacucli_logical_drive_caching) eq "disabled") { # Warn the user about a possible performance hit. $alert_key = "scan_hpacucli_note_0036"; } # Send an alert telling the user that we've found a new controller. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => $alert_key, alert_message_variables => { logical_drive => $hpacucli_logical_drive_name, array => $hpacucli_array_name, serial_number => $hpacucli_controller_serial_number, new_value => $new_hpacucli_logical_drive_caching, old_value => $old_hpacucli_logical_drive_caching, }, }); } elsif ($new_hpacucli_logical_drive_status ne $old_hpacucli_logical_drive_status) { # NOTE: Auto-restored a drive that was re-inserted # Example messages; "Interim Recovery Mode" # "Recovering, 0% complete" # LD transitions (OK -> Eject -> Plug back in) $update = 1; my $alert_level = "warning"; my $title_key = "an_alert_title_0004"; my $alert_key = "scan_hpacucli_note_0037"; if ($old_hpacucli_logical_drive_status eq "VANISHED") { # It's back $alert_key = "scan_hpacucli_note_0045"; $title_key = "an_alert_title_0006"; } elsif (lc($new_hpacucli_logical_drive_status) eq "ok") { # Back to healthy. $alert_level = "critical"; $alert_key = "scan_hpacucli_note_0038"; $title_key = "an_alert_title_0007"; # Clear the rebuild alert, if needed my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_logical_drive_uuid, alert_name => "rebuilding_logical_drive:".$hpacucli_logical_drive_name, modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_logical_drive_status =~ /Recovering, (.*?)% complete/i) { # We'll set an alert so that one alert goes out when # the rebuild starts. $recovered = $1; my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_logical_drive_uuid, alert_name => "rebuilding_logical_drive:".$hpacucli_logical_drive_name, modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "recovered", value1 => $recovered, name2 => "set", value2 => $set, }, file => $THIS_FILE, line => __LINE__}); if ($set) { # Let the user know the rebuild has started. $alert_key = "scan_hpacucli_note_0039"; } else { $alert_level = "notice"; $title_key = "an_alert_title_0003"; $alert_key = "scan_hpacucli_note_0040"; } } elsif (lc($new_hpacucli_logical_drive_status) eq "interim recovery mode") { # Drive just failed. $alert_level = "critical"; $alert_key = "scan_hpacucli_note_0041"; $title_key = "an_alert_title_0005"; } # Send the alert $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $alert_key, alert_message_variables => { logical_drive => $hpacucli_logical_drive_name, array => $hpacucli_array_name, serial_number => $hpacucli_controller_serial_number, new_value => $new_hpacucli_logical_drive_status, old_value => $old_hpacucli_logical_drive_status, recovered => $recovered, }, }); } elsif (($new_hpacucli_logical_drive_os_device_name ne $old_hpacucli_logical_drive_os_device_name) or ($new_hpacucli_logical_drive_type ne $old_hpacucli_logical_drive_type) or ($new_hpacucli_logical_drive_raid_level ne $old_hpacucli_logical_drive_raid_level) or ($new_hpacucli_logical_drive_size ne $old_hpacucli_logical_drive_size) or ($new_hpacucli_logical_drive_strip_size ne $old_hpacucli_logical_drive_strip_size) or ($new_hpacucli_logical_drive_stripe_size ne $old_hpacucli_logical_drive_stripe_size)) { # Something else changed. This should normally never happen. $update = 1; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0042", alert_message_variables => { logical_drive => $hpacucli_logical_drive_name, array => $hpacucli_array_name, serial_number => $hpacucli_controller_serial_number, new_os_drive_name => $new_hpacucli_logical_drive_os_device_name, old_os_drive_name => $old_hpacucli_logical_drive_os_device_name, new_type => $new_hpacucli_logical_drive_type, old_type => $old_hpacucli_logical_drive_type, new_raid_level => $new_hpacucli_logical_drive_raid_level, old_raid_level => $old_hpacucli_logical_drive_raid_level, new_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_size}), old_size => $an->Readable->bytes_to_hr({'bytes' => $old_hpacucli_logical_drive_size}), new_strip_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_strip_size}), old_strip_size => $an->Readable->bytes_to_hr({'bytes' => $old_hpacucli_logical_drive_strip_size}), new_stripe_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_stripe_size}), old_stripe_size => $an->Readable->bytes_to_hr({'bytes' => $old_hpacucli_logical_drive_stripe_size}), }, }); } # If something changed, UPDATE. if ($update) { # Quote the numbers. my $quoted_hpacucli_logical_drive_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_size); my $quoted_hpacucli_logical_drive_strip_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_strip_size); my $quoted_hpacucli_logical_drive_stripe_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_stripe_size); $quoted_hpacucli_logical_drive_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_strip_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_stripe_size =~ s/^'(.*?)'$/$1/; # Do the update my $query = " UPDATE hpacucli_logical_drives SET hpacucli_logical_drive_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid).", hpacucli_logical_drive_name = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_name).", hpacucli_logical_drive_caching = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_caching).", hpacucli_logical_drive_os_device_name = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_os_device_name).", hpacucli_logical_drive_type = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_type).", hpacucli_logical_drive_raid_level = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_raid_level).", hpacucli_logical_drive_size = $quoted_hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size = $quoted_hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size = $quoted_hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_status).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_logical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # New, INSERT. $hpacucli_logical_drive_uuid = $an->Get->uuid(); $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name} = $hpacucli_logical_drive_uuid; $an->data->{'scan-hpacucli'}{logical_drives}{by_uuid}{$hpacucli_logical_drive_uuid} = $hpacucli_logical_drive_name; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::logical_drives::by_name::${hpacucli_logical_drive_name}", value1 => $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name}, name2 => "scan-hpacucli::logical_drives::by_uuid::${hpacucli_logical_drive_uuid}", value2 => $an->data->{'scan-hpacucli'}{logical_drives}{by_uuid}{$hpacucli_logical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); # Send an alert telling the user that we've found a new controller. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0033", alert_message_variables => { name => $hpacucli_array_name, logical_drive => $hpacucli_logical_drive_name, new_caching => $new_hpacucli_logical_drive_caching, new_os_device_name => $new_hpacucli_logical_drive_os_device_name, new_type => $new_hpacucli_logical_drive_type, new_raid_level => $new_hpacucli_logical_drive_raid_level, new_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_size}), new_strip_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_strip_size}), new_stripe_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_logical_drive_stripe_size}), new_status => $new_hpacucli_logical_drive_status, }, }); ### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0003", alert_message_variables => {}, }); # Quote some stuff manually my $quoted_hpacucli_logical_drive_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_size); my $quoted_hpacucli_logical_drive_strip_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_strip_size); my $quoted_hpacucli_logical_drive_stripe_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_stripe_size); $quoted_hpacucli_logical_drive_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_strip_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_stripe_size =~ s/^'(.*?)'$/$1/; # Now INERT variables. my $query = " INSERT INTO hpacucli_logical_drives ( hpacucli_logical_drive_uuid, hpacucli_logical_drive_host_uuid, hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name, hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_caching).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_os_device_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_type).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_raid_level).", $quoted_hpacucli_logical_drive_size, $quoted_hpacucli_logical_drive_strip_size, $quoted_hpacucli_logical_drive_stripe_size, ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_logical_drive_status).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Process logical drive variables now. Note that there are no temperatures. foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}}) { # Insert the variables. my $new_hpacucli_variable_value = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{data}{detail}{$hpacucli_variable_name}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_name", value1 => $hpacucli_variable_name, name2 => "new_hpacucli_variable_value", value2 => $new_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # Have we seen this variable before? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::hpacucli_logical_drives::source_uuid::${hpacucli_logical_drive_uuid}::detail::${hpacucli_variable_name}::hpacucli_variable_uuid", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_logical_drives}{source_uuid}{$hpacucli_logical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_logical_drives}{source_uuid}{$hpacucli_logical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}) { # Exists. Has it changed? my $hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_logical_drives}{source_uuid}{$hpacucli_logical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}; my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_logical_drives}{source_uuid}{$hpacucli_logical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_value}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # delete this so that we know it was processed. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_logical_drives}{source_uuid}{$hpacucli_logical_drive_uuid}{detail}{$hpacucli_variable_name}; if ($old_hpacucli_variable_value ne $new_hpacucli_variable_value) { # Now update. Alert the user as a warning, this # should rarely ever change. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0066", alert_message_variables => { logical_drive => $hpacucli_logical_drive_name, array => $hpacucli_array_name, serial_number => $hpacucli_controller_serial_number, variable_name => $hpacucli_variable_name, old_value => $old_hpacucli_variable_value ? $old_hpacucli_variable_value : "--", new_value => $new_hpacucli_variable_value ? $new_hpacucli_variable_value : "--", }, }); # UPDATE my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # New. Alert the user. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_header => 'FALSE', alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0004", alert_message_variables => { name => $hpacucli_variable_name, value => $new_hpacucli_variable_value, }, }); # INSERT my $query = " INSERT INTO hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid()).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", 'hpacucli_logical_drives', ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", FALSE, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } # Physical Disks. foreach my $port (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}}) { foreach my $box (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}}) { foreach my $bay (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}}) { # Throw this into a function to get out of # indent-hell. process_a_drive($an, $hpacucli_controller_serial_number, $hpacucli_logical_drive_uuid, $hpacucli_array_name, $hpacucli_logical_drive_name, $port, $box, $bay); } } } } } # Look for deleted arrays. foreach my $hpacucli_array_uuid (keys %{$an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}}) { my $old_hpacucli_array_name = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_name}; my $old_hpacucli_array_controller_uuid = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_controller_uuid}; my $old_controller_serial_number = $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$old_hpacucli_array_controller_uuid}; my $old_hpacucli_array_status = $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "old_hpacucli_array_name", value1 => $old_hpacucli_array_name, name2 => "old_hpacucli_array_controller_uuid", value2 => $old_hpacucli_array_controller_uuid, name3 => "old_controller_serial_number", value3 => $old_controller_serial_number, name4 => "old_hpacucli_array_status", value4 => $old_hpacucli_array_status, }, file => $THIS_FILE, line => __LINE__}); next if $old_hpacucli_array_name eq "ZZZZ"; next if $old_hpacucli_array_status eq "VANISHED"; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0031", alert_message_variables => { name => $old_hpacucli_array_name, serial_number => $old_controller_serial_number, }, }); my $query = " UPDATE hpacucli_arrays SET hpacucli_array_status = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Look for deleted logical drives. foreach my $hpacucli_logical_drive_uuid (keys %{$an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}}) { # Look for changes my $old_hpacucli_logical_drive_array_uuid = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_array_uuid}; my $old_hpacucli_logical_drive_name = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_name}; my $old_hpacucli_logical_drive_status = $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "hpacucli_logical_drive_uuid", value1 => $hpacucli_logical_drive_uuid, name2 => "old_hpacucli_logical_drive_array_uuid", value2 => $old_hpacucli_logical_drive_array_uuid, name3 => "old_hpacucli_logical_drive_name", value3 => $old_hpacucli_logical_drive_name, name4 => "old_hpacucli_logical_drive_status", value4 => $old_hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); next if $old_hpacucli_logical_drive_name eq "9999"; next if $old_hpacucli_logical_drive_status eq "VANISHED"; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0044", alert_message_variables => { logical_drive => $old_hpacucli_logical_drive_name, }, }); my $query = " UPDATE hpacucli_logical_drives SET hpacucli_logical_drive_status = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_logical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } # Now commit the changes. $an->DB->commit_sql({source => $THIS_FILE, line => __LINE__}); return(0); } # Process a specific drive sub process_a_drive { my ($an, $hpacucli_controller_serial_number, $hpacucli_logical_drive_uuid, $hpacucli_array_name, $hpacucli_logical_drive_name, $port, $box, $bay) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_a_drive" }, message_key => "an_variables_0007", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, name2 => "hpacucli_logical_drive_uuid", value2 => $hpacucli_logical_drive_uuid, name3 => "hpacucli_array_name", value3 => $hpacucli_array_name, name4 => "hpacucli_logical_drive_name", value4 => $hpacucli_logical_drive_name, name5 => "port", value5 => $port, name6 => "box", value6 => $box, name7 => "bay", value7 => $bay, }, file => $THIS_FILE, line => __LINE__}); my $hpacucli_physical_drive_uuid = ""; my $hpacucli_physical_drive_serial_number = ""; my $new_hpacucli_physical_drive_model = ""; my $new_hpacucli_physical_drive_interface = ""; my $new_hpacucli_physical_drive_status = ""; my $new_hpacucli_physical_drive_size = 0; my $new_hpacucli_physical_drive_type = ""; my $new_hpacucli_physical_drive_rpm = 0; my $new_hpacucli_physical_drive_temperature = ""; my $new_hpacucli_physical_drive_last_failure_reason = ""; my $maximum_drive_temperature = 0; # Serial Number if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{serial_number}) { $hpacucli_physical_drive_serial_number = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{serial_number}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_physical_drive_serial_number", value1 => $hpacucli_physical_drive_serial_number, }, file => $THIS_FILE, line => __LINE__}); } # Model if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{model}) { $new_hpacucli_physical_drive_model = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{model}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_model", value1 => $new_hpacucli_physical_drive_model, }, file => $THIS_FILE, line => __LINE__}); } # Interface if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{interface_type}) { $new_hpacucli_physical_drive_interface = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{interface_type}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_interface", value1 => $new_hpacucli_physical_drive_interface, }, file => $THIS_FILE, line => __LINE__}); } # Status if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{status}) { $new_hpacucli_physical_drive_status = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_status", value1 => $new_hpacucli_physical_drive_status, }, file => $THIS_FILE, line => __LINE__}); } # Size if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{size}) { $new_hpacucli_physical_drive_size = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{size}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_size", value1 => $new_hpacucli_physical_drive_size." (".$an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_physical_drive_size}).")", }, file => $THIS_FILE, line => __LINE__}); } # Type if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{drive_type}) { $new_hpacucli_physical_drive_type = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{drive_type}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_type", value1 => $new_hpacucli_physical_drive_type, }, file => $THIS_FILE, line => __LINE__}); } # RPM (0 if SSD) if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{rotational_speed}) { $new_hpacucli_physical_drive_rpm = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{rotational_speed}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_rpm", value1 => $new_hpacucli_physical_drive_rpm, }, file => $THIS_FILE, line => __LINE__}); } # Temperature if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{temperature}{current_temperature}) { $new_hpacucli_physical_drive_temperature = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{temperature}{current_temperature}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_temperature", value1 => $new_hpacucli_physical_drive_temperature, }, file => $THIS_FILE, line => __LINE__}); } # Last failure reason if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{last_failure_reason}) { $new_hpacucli_physical_drive_last_failure_reason = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{last_failure_reason}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_physical_drive_last_failure_reason", value1 => $new_hpacucli_physical_drive_last_failure_reason, }, file => $THIS_FILE, line => __LINE__}); } # Maximum temperature if ($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{temperature}{maximum_temperature}) { $maximum_drive_temperature = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{temperature}{maximum_temperature}; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "maximum_drive_temperature", value1 => $maximum_drive_temperature, }, file => $THIS_FILE, line => __LINE__}); } $an->Log->entry({log_level => 2, message_key => "an_variables_0010", message_variables => { name1 => "hpacucli_physical_drive_serial_number", value1 => $hpacucli_physical_drive_serial_number, name2 => "new_hpacucli_physical_drive_model", value2 => $new_hpacucli_physical_drive_model, name3 => "new_hpacucli_physical_drive_interface", value3 => $new_hpacucli_physical_drive_interface, name4 => "new_hpacucli_physical_drive_status", value4 => $new_hpacucli_physical_drive_status, name5 => "new_hpacucli_physical_drive_size", value5 => $new_hpacucli_physical_drive_size, name6 => "new_hpacucli_physical_drive_type", value6 => $new_hpacucli_physical_drive_type, name7 => "new_hpacucli_physical_drive_rpm", value7 => $new_hpacucli_physical_drive_rpm, name8 => "new_hpacucli_physical_drive_temperature", value8 => $new_hpacucli_physical_drive_temperature, name9 => "new_hpacucli_physical_drive_last_failure_reason", value9 => $new_hpacucli_physical_drive_last_failure_reason, name10 => "maximum_drive_temperature", value10 => $maximum_drive_temperature, }, file => $THIS_FILE, line => __LINE__}); # Delete the Port, Box and Bay values so that they don't get processed as their own variables. delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{port}; delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{box}; delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{bay}; # We need to sanity check the three numeric strings because calling 'quote' directly will wrap the # numeric values in single quotes which violates 'numeric' forms. my $quoted_hpacucli_physical_drive_size = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_size); my $quoted_hpacucli_physical_drive_rpm = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_rpm); my $quoted_hpacucli_physical_drive_temperature = $an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_temperature); $quoted_hpacucli_physical_drive_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_physical_drive_rpm =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_physical_drive_temperature =~ s/^'(.*?)'$/$1/; if ((($quoted_hpacucli_physical_drive_size) && ($quoted_hpacucli_physical_drive_size =~ /\D/)) or (($quoted_hpacucli_physical_drive_rpm) && ($quoted_hpacucli_physical_drive_rpm =~ /\D/)) or (($quoted_hpacucli_physical_drive_temperature) && ($quoted_hpacucli_physical_drive_temperature =~ /\D/))) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0010", message_variables => { size => $quoted_hpacucli_physical_drive_size, rpm => $quoted_hpacucli_physical_drive_rpm, temperature => $quoted_hpacucli_physical_drive_temperature, }, code => 8, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 8}); } $quoted_hpacucli_physical_drive_size = "NULL" if $quoted_hpacucli_physical_drive_size eq ""; $quoted_hpacucli_physical_drive_rpm = "NULL" if $quoted_hpacucli_physical_drive_rpm eq ""; $quoted_hpacucli_physical_drive_temperature = "NULL" if $quoted_hpacucli_physical_drive_temperature eq ""; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "quoted_hpacucli_physical_drive_size", value1 => $quoted_hpacucli_physical_drive_size, name2 => "quoted_hpacucli_physical_drive_rpm", value2 => $quoted_hpacucli_physical_drive_rpm, name3 => "quoted_hpacucli_physical_drive_temperature", value3 => $quoted_hpacucli_physical_drive_temperature, }, file => $THIS_FILE, line => __LINE__}); # Die if we don't have a serial number if (not $hpacucli_physical_drive_serial_number) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0011", message_variables => { serial_number => $hpacucli_controller_serial_number, array_name => $hpacucli_array_name, logical_drive_name => $hpacucli_logical_drive_name, port => $port, box => $box, bay => $bay, }, code => 9, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 9}); } # Have we seen this drive before? if ($an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number}) { # Yup! Look for changes. $hpacucli_physical_drive_uuid = $an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_physical_drive_uuid", value1 => $hpacucli_physical_drive_uuid, }, file => $THIS_FILE, line => __LINE__}); # Gather the old data. my $old_hpacucli_logical_drive_uuid = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_logical_drive_uuid}; my $old_hpacucli_physical_drive_model = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_model}; my $old_hpacucli_physical_drive_interface = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_interface}; my $old_hpacucli_physical_drive_status = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_status}; my $old_hpacucli_physical_drive_size = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_size}; my $old_hpacucli_physical_drive_type = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_type}; my $old_hpacucli_physical_drive_rpm = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_rpm}; my $old_hpacucli_physical_drive_temperature = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_temperature}; my $old_hpacucli_physical_drive_last_failure_reason = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_last_failure_reason}; my $old_hpacucli_physical_drive_port = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_port}; my $old_hpacucli_physical_drive_box = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_box}; my $old_hpacucli_physical_drive_bay = $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_bay}; $an->Log->entry({log_level => 2, message_key => "an_variables_0012", message_variables => { name1 => "old_hpacucli_logical_drive_uuid", value1 => $old_hpacucli_logical_drive_uuid, name2 => "old_hpacucli_physical_drive_model", value2 => $old_hpacucli_physical_drive_model, name3 => "old_hpacucli_physical_drive_interface", value3 => $old_hpacucli_physical_drive_interface, name4 => "old_hpacucli_physical_drive_status", value4 => $old_hpacucli_physical_drive_status, name5 => "old_hpacucli_physical_drive_size", value5 => $old_hpacucli_physical_drive_size, name6 => "old_hpacucli_physical_drive_type", value6 => $old_hpacucli_physical_drive_type, name7 => "old_hpacucli_physical_drive_rpm", value7 => $old_hpacucli_physical_drive_rpm, name8 => "old_hpacucli_physical_drive_temperature", value8 => $old_hpacucli_physical_drive_temperature, name9 => "old_hpacucli_physical_drive_last_failure_reason", value9 => $old_hpacucli_physical_drive_last_failure_reason, name10 => "old_hpacucli_physical_drive_port", value10 => $old_hpacucli_physical_drive_port, name11 => "old_hpacucli_physical_drive_box", value11 => $old_hpacucli_physical_drive_box, name12 => "old_hpacucli_physical_drive_bay", value12 => $old_hpacucli_physical_drive_bay, }, file => $THIS_FILE, line => __LINE__}); # delete this so that we know it was processed. delete $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}; my $update = 0; # Did the drive move between logical drives? if ($hpacucli_logical_drive_uuid ne $old_hpacucli_logical_drive_uuid) { $update = 1; # We'll need to get the host, controller serial number and array name my $query = " SELECT a.host_name, b.hpacucli_controller_serial_number, c.hpacucli_array_name, d.hpacucli_logical_drive_name FROM hosts a, hpacucli_controllers b, hpacucli_arrays c, hpacucli_logical_drives d WHERE a.host_uuid = b.hpacucli_controller_host_uuid AND b.hpacucli_controller_uuid = c.hpacucli_array_controller_uuid AND c.hpacucli_array_uuid = d.hpacucli_logical_drive_array_uuid AND c.hpacucli_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_hpacucli_logical_drive_uuid)." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); my $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "results", value1 => $results, name2 => "count", value2 => $count, }, file => $THIS_FILE, line => __LINE__}); my $old_host_name = $results->[0]->[0] ? $results->[0]->[0] : "--"; my $old_hpacucli_controller_serial_number = $results->[0]->[1] ? $results->[0]->[1] : "--"; my $old_hpacucli_array_name = $results->[0]->[2] ? $results->[0]->[2] : "--"; my $old_hpacucli_logical_drive_name = $results->[0]->[3] ? $results->[0]->[3] : "--"; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "old_host_name", value1 => $old_host_name, name2 => "old_hpacucli_controller_serial_number", value2 => $old_hpacucli_controller_serial_number, name3 => "old_hpacucli_array_name", value3 => $old_hpacucli_array_name, name4 => "old_hpacucli_logical_drive_name", value4 => $old_hpacucli_logical_drive_name, }, file => $THIS_FILE, line => __LINE__}); # Send an alert telling the drive has moved. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0047", alert_message_variables => { drive_serial_number => $hpacucli_physical_drive_serial_number, old_host_name => $old_host_name, new_host_name => $an->hostname, new_controller_serial_number => $hpacucli_controller_serial_number, old_controller_serial_number => $old_hpacucli_controller_serial_number, new_array_name => $hpacucli_array_name, old_array_name => $hpacucli_array_name, new_logical_drive_name => $hpacucli_logical_drive_name, old_logical_drive_name => $old_hpacucli_logical_drive_name }, }); } # Has the status changed? if ($old_hpacucli_physical_drive_status ne $new_hpacucli_physical_drive_status) { $update = 1; # Yup. Start with an alert about it being not OK, and change if it is now OK. my $title_key = "an_alert_title_0004"; my $message_key = "scan_hpacucli_note_0048"; # Did it return? if ($old_hpacucli_physical_drive_status eq "VANISHED") { # The drive is back. $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0050"; } elsif (lc($new_hpacucli_physical_drive_status) eq "ok") { # Drive is OK again. $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0051"; } $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, old_status => $old_hpacucli_physical_drive_status, new_status => $new_hpacucli_physical_drive_status, }, }); } # Did the temperature change? Whether it did or not, we need to record the current # temperature state. ### NOTE: HP tells us the maximum temperature each of its drives can handle. This is ### a low number, so we need to tighten up some thresholds compared to usual ### ranges. # Set defaults my $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{drives}{high_critical}; my $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{drives}{high_warning}; my $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{drives}{low_warning}; my $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{drives}{low_critical}; my $jump = $an->data->{'scan-hpacucli'}{thresholds}{drives}{jump}; my $buffer = $an->data->{'scan-hpacucli'}{thresholds}{drives}{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; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } # Did we get a maximum temperature from the drive? $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "maximum_drive_temperature", value1 => $maximum_drive_temperature, name2 => "scan-hpacucli::ignore_maximum_temperature", value2 => $an->data->{'scan-hpacucli'}{ignore_maximum_temperature}, }, file => $THIS_FILE, line => __LINE__}); if (($maximum_drive_temperature) && (not $an->data->{'scan-hpacucli'}{ignore_maximum_temperature})) { $high_critical = $maximum_drive_temperature; $high_warning = $maximum_drive_temperature - 2; $clear_high_critical = $high_critical - $buffer; $clear_high_warning = $high_warning - $buffer; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "clear_high_critical", value3 => $clear_high_critical, name4 => "clear_high_warning", value4 => $clear_high_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } } # Clear alerts, if needed. The order is important as clearing a warning will replace # clearing a critical when a sensor goes critical -> ok in one scan. Once done, we'll # check if we've crossed into a warning or critical state. If so, those will replace # any cleared messages. my $alert_level = "info"; my $title_key = "an_alert_title_0002"; my $message_key = "scan_hpacucli_note_0053"; my $delta = 0; if ($new_hpacucli_physical_drive_temperature) { if ($new_hpacucli_physical_drive_temperature < $clear_high_critical) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_critical", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "critical"; $title_key = "an_alert_title_0007"; $message_key = "scan_hpacucli_note_0054"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_physical_drive_temperature < $clear_high_warning) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { # The temperature is no longer # warning, and it didn't just go # critical $alert_level = "warning"; $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0055"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_physical_drive_temperature > $clear_low_critical) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_low_critical", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "critical"; $title_key = "an_alert_title_0007"; $message_key = "scan_hpacucli_note_0056"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_physical_drive_temperature > $clear_low_warning) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_low_warning", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "warning"; $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0057"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } # Now see if the temperature has crossed into a warning or critical state. my $temperature_state = "ok"; my $temperature_is = "nominal"; if ($new_hpacucli_physical_drive_temperature > $high_critical) { # Crossed the high critical threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", # This is not the alert level, 'warning' == trouble, 'clear' == ok now. alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0060"; } $temperature_state = "critical"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature > $high_warning) { # Crossed the high warning threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0061"; } $temperature_state = "warning"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature < $low_critical) { # Dropped below the low critical threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_low_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0062"; } $temperature_state = "critical"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature < $low_warning) { # Crossed the low warning threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_low_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0063"; } $temperature_state = "warning"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } else { # Did it change enough to trigger a jump alert? if ($new_hpacucli_physical_drive_temperature > $old_hpacucli_physical_drive_temperature) { # Jumped $delta = $new_hpacucli_physical_drive_temperature - $old_hpacucli_physical_drive_temperature; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "delta", value1 => $delta, }, file => $THIS_FILE, line => __LINE__}); if ($delta >= $jump) { # Big jump. $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0058"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } else { # Dropped $delta = $old_hpacucli_physical_drive_temperature - $new_hpacucli_physical_drive_temperature; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "delta", value1 => $delta, }, file => $THIS_FILE, line => __LINE__}); if ($delta >= $jump) { # Big drop. $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0059"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } } # Record this for later processing into the 'temperature' table. my $sensor_host_key = "physical_drive:$hpacucli_physical_drive_serial_number"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sensor_host_key", value1 => $sensor_host_key, }, file => $THIS_FILE, line => __LINE__}); $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_celsius} = $new_hpacucli_physical_drive_temperature; $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_state} = $temperature_state; $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_is} = $temperature_is; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_celsius", value1 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_celsius}, name2 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_state", value2 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_state}, name3 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_is", value3 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_is}, }, file => $THIS_FILE, line => __LINE__}); } # Now, if the temperature changed, update and send an alert if appropriate. if ($new_hpacucli_physical_drive_temperature ne $old_hpacucli_physical_drive_temperature) { # Yup. Analyze $update = 1; # Send an alert telling the user that we've found a variable for this drive. Note # that we add ' C' to the temperatures so that they get translated to '°F' if desired # by the reader. $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, old_temperature => $old_hpacucli_physical_drive_temperature ? $old_hpacucli_physical_drive_temperature." C" : "--", new_temperature => $new_hpacucli_physical_drive_temperature ? $new_hpacucli_physical_drive_temperature." C" : "--", delta => $delta." C", high_critical_temperature => $high_critical." C", high_warning_temperature => $high_warning." C", low_critical_temperature => $low_critical." C", low_warning_temperature => $low_warning." C", }, }); } # Anything else? if (($old_hpacucli_physical_drive_model ne $new_hpacucli_physical_drive_model) or ($old_hpacucli_physical_drive_interface ne $new_hpacucli_physical_drive_interface) or ($old_hpacucli_physical_drive_size ne $new_hpacucli_physical_drive_size) or ($old_hpacucli_physical_drive_rpm ne $new_hpacucli_physical_drive_rpm) or ($new_hpacucli_physical_drive_last_failure_reason ne $old_hpacucli_physical_drive_last_failure_reason) or ($port ne $old_hpacucli_physical_drive_port) or ($box ne $old_hpacucli_physical_drive_box) or ($bay ne $old_hpacucli_physical_drive_bay)) { # Something else changed. These normally shouldn't change... $update = 1; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0052", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, old_model => $old_hpacucli_physical_drive_model, new_model => $new_hpacucli_physical_drive_model, old_interface => $old_hpacucli_physical_drive_interface, new_interface => $new_hpacucli_physical_drive_interface, old_size => $an->data->{sys}{use_db_fh}->quote($old_hpacucli_physical_drive_size), new_size => $an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_size), old_rpm => $old_hpacucli_physical_drive_rpm, new_rpm => $new_hpacucli_physical_drive_rpm, old_last_failure_reason => $old_hpacucli_physical_drive_last_failure_reason ? $old_hpacucli_physical_drive_last_failure_reason : "--", new_last_failure_reason => $new_hpacucli_physical_drive_last_failure_reason ? $new_hpacucli_physical_drive_last_failure_reason : "--", old_port => $old_hpacucli_physical_drive_port, new_port => $port, old_box => $old_hpacucli_physical_drive_box, new_box => $box, old_bay => $old_hpacucli_physical_drive_bay, new_bay => $bay, }, }); } if ($update) { # UPDATE my $query = " UPDATE hpacucli_physical_drives SET hpacucli_physical_drive_logical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", hpacucli_physical_drive_serial_number = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_serial_number).", hpacucli_physical_drive_model = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_model).", hpacucli_physical_drive_interface = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_interface).", hpacucli_physical_drive_status = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_status).", hpacucli_physical_drive_size = $quoted_hpacucli_physical_drive_size, hpacucli_physical_drive_type = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_type).", hpacucli_physical_drive_rpm = $quoted_hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature = $quoted_hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_last_failure_reason).", hpacucli_physical_drive_port = ".$an->data->{sys}{use_db_fh}->quote($port).", hpacucli_physical_drive_box = ".$an->data->{sys}{use_db_fh}->quote($box).", hpacucli_physical_drive_bay = ".$an->data->{sys}{use_db_fh}->quote($bay).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_physical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # New, INSERT it. $hpacucli_physical_drive_uuid = $an->Get->uuid(); $an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number} = $hpacucli_physical_drive_uuid; $an->data->{'scan-hpacucli'}{physical_drives}{by_uuid}{$hpacucli_physical_drive_uuid} = $hpacucli_physical_drive_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::physical_drives::by_serial::${hpacucli_physical_drive_serial_number}", value1 => $an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number}, name2 => "scan-hpacucli::physical_drives::by_uuid::${hpacucli_physical_drive_uuid}", value2 => $an->data->{'scan-hpacucli'}{physical_drives}{by_uuid}{$hpacucli_physical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); # Send an alert telling the user we found a new drive. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0046", alert_message_variables => { controller_serial_number => $hpacucli_controller_serial_number, array_name => $hpacucli_array_name, logical_drive_name => $hpacucli_logical_drive_name, port => $port, box => $box, bay => $bay, drive_serial_number => $hpacucli_physical_drive_serial_number, model => $new_hpacucli_physical_drive_model, interface => $new_hpacucli_physical_drive_interface, status => $new_hpacucli_physical_drive_status, size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_physical_drive_size}), type => $new_hpacucli_physical_drive_type, rpm => $new_hpacucli_physical_drive_rpm, temperature => $new_hpacucli_physical_drive_temperature ? $new_hpacucli_physical_drive_temperature." C" : "--", last_failure_reason => $new_hpacucli_physical_drive_last_failure_reason ? $new_hpacucli_physical_drive_last_failure_reason : "--", }, }); # Check for problems with this new drive. if (lc($new_hpacucli_physical_drive_status) ne "ok") { # There's a problem, send an alert. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0064", alert_message_variables => { controller_serial_number => $hpacucli_controller_serial_number, }, }); } # Check the temperature, if we read one. if ($new_hpacucli_physical_drive_temperature =~ /^\d+/) { ### NOTE: HP tells us the maximum temperature each of its drives can handle. This is ### a low number, so we need to tighten up some thresholds compared to usual ### ranges. # Set defaults my $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{drives}{high_critical}; my $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{drives}{high_warning}; my $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{drives}{low_warning}; my $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{drives}{low_critical}; my $jump = $an->data->{'scan-hpacucli'}{thresholds}{drives}{jump}; my $buffer = $an->data->{'scan-hpacucli'}{thresholds}{drives}{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; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } # Did we get a maximum temperature from the drive? $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "maximum_drive_temperature", value1 => $maximum_drive_temperature, name2 => "scan-hpacucli::ignore_maximum_temperature", value2 => $an->data->{'scan-hpacucli'}{ignore_maximum_temperature}, }, file => $THIS_FILE, line => __LINE__}); if (($maximum_drive_temperature) && (not $an->data->{'scan-hpacucli'}{ignore_maximum_temperature})) { $high_critical = $maximum_drive_temperature; $high_warning = $maximum_drive_temperature - 2; $clear_high_critical = $high_critical - $buffer; $clear_high_warning = $high_warning - $buffer; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "clear_high_critical", value3 => $clear_high_critical, name4 => "clear_high_warning", value4 => $clear_high_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } } # See if the temperature outside of the warning or critical thresholds. my $temperature_state = "ok"; my $temperature_is = "nominal"; my $alert_level = "warning"; my $title_key = "an_alert_title_0004"; my $message_key = ""; if ($new_hpacucli_physical_drive_temperature > $high_critical) { # Crossed the high critical threshold. This should always be unset because it # is a new variable, but check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", # This is not the alert level, 'warning' == trouble, 'clear' == ok now. alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0060"; } $temperature_state = "critical"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature > $high_warning) { # Crossed the high warning threshold. This should always be unset because it # is a new variable, but check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0061"; } $temperature_state = "warning"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature < $low_critical) { # Dropped below the low critical threshold. This should always be unset # because it is a new variable, but check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0062"; } $temperature_state = "critical"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_physical_drive_temperature < $low_warning) { # Crossed the low warning threshold. This should always be unset because it # is a new variable, but check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "physical_drive_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0063"; } $temperature_state = "warning"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } # Record this for later processing into the 'temperature' table. my $sensor_host_key = "physical_drive:$hpacucli_physical_drive_serial_number"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sensor_host_key", value1 => $sensor_host_key, }, file => $THIS_FILE, line => __LINE__}); $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_celsius} = $new_hpacucli_physical_drive_temperature; $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_state} = $temperature_state; $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_is} = $temperature_is; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_celsius", value1 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_celsius}, name2 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_state", value2 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_state}, name3 => "new::temperature::hpacucli_physical_drive_temperature::${sensor_host_key}::temperature_is", value3 => $an->data->{new}{temperature}{hpacucli_physical_drive_temperature}{$sensor_host_key}{temperature_is}, }, file => $THIS_FILE, line => __LINE__}); if ($message_key) { # Send an alert telling the user that we've found a drive outside nominal # temperature. Note that we add ' C' to the temperatures so that they get # translated to '°F' if desired by the reader. $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_header => 'FALSE', alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { serial_number => $hpacucli_controller_serial_number, temperature => $new_hpacucli_physical_drive_temperature ? $new_hpacucli_physical_drive_temperature." C" : "--", high_critical_temperature => $high_critical." C", high_warning_temperature => $high_warning." C", low_critical_temperature => $low_critical." C", low_warning_temperature => $low_warning." C", }, }); ### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0003", alert_message_variables => {}, }); } } my $query = " INSERT INTO hpacucli_physical_drives ( hpacucli_physical_drive_uuid, hpacucli_physical_drive_host_uuid, hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model, hpacucli_physical_drive_interface, hpacucli_physical_drive_status, hpacucli_physical_drive_size, hpacucli_physical_drive_type, hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port, hpacucli_physical_drive_box, hpacucli_physical_drive_bay, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_model).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_interface).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_status).", $quoted_hpacucli_physical_drive_size, ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_type).", $quoted_hpacucli_physical_drive_rpm, $quoted_hpacucli_physical_drive_temperature, ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_physical_drive_last_failure_reason).", ".$an->data->{sys}{use_db_fh}->quote($port).", ".$an->data->{sys}{use_db_fh}->quote($box).", ".$an->data->{sys}{use_db_fh}->quote($bay).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Process physical drive variables now. Note that there are no temperatures. foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}}) { my $new_hpacucli_variable_value = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{$hpacucli_variable_name}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_name", value1 => $hpacucli_variable_name, name2 => "new_hpacucli_variable_value", value2 => $new_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # Have we seen this variable before? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::hpacucli_physical_drives::source_uuid::${hpacucli_physical_drive_uuid}::detail::${hpacucli_variable_name}::hpacucli_variable_uuid", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}) { # Exists. Has it changed? my $hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}; my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_value}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # delete this so that we know it was processed. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}; if ($old_hpacucli_variable_value ne $new_hpacucli_variable_value) { # Now update. Alert the user as a warning, these should rarely ever change. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0065", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, variable_name => $hpacucli_variable_name, old_value => $old_hpacucli_variable_value ? $old_hpacucli_variable_value : "--", new_value => $new_hpacucli_variable_value ? $new_hpacucli_variable_value : "--", }, }); # UPDATE my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # Clear the hash key that was autovivified in the previous check so that it doesn't # cause a loop when looking for vanished values. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}; # New. Alert the user. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_header => 'FALSE', alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0004", alert_message_variables => { name => $hpacucli_variable_name, value => $new_hpacucli_variable_value, }, }); # INSERT my $query = " INSERT INTO hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid()).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", 'hpacucli_physical_drives', ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid).", FALSE, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } # Look for vanished variables for this drive. foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}}) { my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_value}; my $old_hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drives}{source_uuid}{$hpacucli_physical_drive_uuid}{detail}{$hpacucli_variable_name}{hpacucli_variable_uuid}; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "hpacucli_variable_name", value1 => $hpacucli_variable_name, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, name3 => "old_hpacucli_variable_uuid", value3 => $old_hpacucli_variable_uuid, }, file => $THIS_FILE, line => __LINE__}); # If the old alarm state is already 'VANISHED', ignore it. next if $old_hpacucli_variable_value eq "VANISHED"; # Still here? Alert and UPDATE. ### NOTE: For now, we're going to use warning level because cache_modules ### 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. $an->data->{sys}{alert_sort}++; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0067", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, name => $hpacucli_variable_name, }, }); my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # If this was a diagnostics run, check for error counters if ($an->data->{sys}{process_diagnostics}) { # These are stored in the DB as standard variables, but we use the source is # 'hpacucli_physical_drive_diagnostics' to distinguish them. if (exists $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_hard}) { # We got the data foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}}) { # Store this in the main hash. my $new_hpacucli_variable_value = delete $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$hpacucli_logical_drive_name}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{'diagnostics'}{$hpacucli_variable_name}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_name", value1 => $hpacucli_variable_name, name2 => "new_hpacucli_variable_value", value2 => $new_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); ### TODO # If the variable name has 'error' in it and the value is numeric, see if it # is > 5 and, if so, set the health. # Have we seen this variable before? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::hpacucli_physical_drive_diagnostics::source_uuid::${hpacucli_physical_drive_uuid}::diagnostics::${hpacucli_variable_name}::hpacucli_variable_uuid", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_uuid}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_uuid}) { # Exists. Has it changed? my $hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_uuid}; my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_value}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # Delete this so that we know it was processed. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}; if ($old_hpacucli_variable_value ne $new_hpacucli_variable_value) { # Now update. Alert the user as a warning, these should rarely ever change. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0065", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, variable_name => $hpacucli_variable_name, old_value => $old_hpacucli_variable_value ? $old_hpacucli_variable_value : "--", new_value => $new_hpacucli_variable_value ? $new_hpacucli_variable_value : "--", }, }); # UPDATE my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # Clear the hash key that was autovivified in the previous check so # that it doesn't cause a loop when looking for vanished values. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}; # New. Alert the user. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_header => 'FALSE', alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0004", alert_message_variables => { name => $hpacucli_variable_name, value => $new_hpacucli_variable_value, }, }); # INSERT my $query = " INSERT INTO hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid()).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", 'hpacucli_physical_drive_diagnostics', ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid).", FALSE, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } } # Look for vanished diagnostics variables. foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}}) { my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_value}; my $old_hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_physical_drive_diagnostics}{source_uuid}{$hpacucli_physical_drive_uuid}{'diagnostics'}{$hpacucli_variable_name}{hpacucli_variable_uuid}; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "hpacucli_variable_name", value1 => $hpacucli_variable_name, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, name3 => "old_hpacucli_variable_uuid", value3 => $old_hpacucli_variable_uuid, }, file => $THIS_FILE, line => __LINE__}); # If the old alarm state is already 'VANISHED', ignore it. next if $old_hpacucli_variable_value eq "VANISHED"; # Still here? Alert and UPDATE. ### NOTE: For now, we're going to use warning level because cache_modules ### 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. $an->data->{sys}{alert_sort}++; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0068", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, name => $hpacucli_variable_name, }, }); my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } return(0); } # Look for added, changed or deleted controllers. sub process_controllers { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_controllers" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Look for new, changed or deleted controllers. $an->data->{sys}{sql} = []; foreach my $hpacucli_controller_serial_number (sort {$a cmp $b} keys %{$an->data->{controller}}) { # Controller data; next if $hpacucli_controller_serial_number eq "metadata"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, name2 => "scan-hpacucli::controllers::by_serial::$hpacucli_controller_serial_number", value2 => $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}, }, file => $THIS_FILE, line => __LINE__}); # Have we seen this controller before? my $hpacucli_controller_uuid = ""; my $controller_is_new = 0; if ($an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}) { # Yup! $hpacucli_controller_uuid = $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, }, file => $THIS_FILE, line => __LINE__}); } else { # No, this is a new controller. Create a new UUID for it. $hpacucli_controller_uuid = $an->Get->uuid(); $controller_is_new = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "controller_is_new", value2 => $controller_is_new, }, file => $THIS_FILE, line => __LINE__}); # Add the keys for looking it up by UUID or serial number. $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number} = $hpacucli_controller_uuid; $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid} = $hpacucli_controller_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::controllers::by_serial::$hpacucli_controller_serial_number", value1 => $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}, name2 => "scan-hpacucli::controllers::by_uuid::$hpacucli_controller_uuid", value2 => $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid}, }, file => $THIS_FILE, line => __LINE__}); } # These are the values for the controller and cache tables. Anything else will go in the # variables table which will be processed after the controller. # Controller my $new_hpacucli_controller_model = ""; my $new_hpacucli_controller_status = ""; my $new_hpacucli_controller_last_diagnostics = $an->data->{sys}{process_diagnostics} ? time : ""; my $new_hpacucli_controller_cache_present = "unknown"; my $new_hpacucli_controller_drive_write_cache = ""; my $new_hpacucli_controller_firmware_version = ""; my $new_hpacucli_controller_unsafe_writeback_cache = ""; # Cache my $new_hpacucli_cache_module_size = ""; my $new_hpacucli_cache_module_serial_number = ""; my $new_hpacucli_cache_module_status = ""; my $new_hpacucli_cache_module_type = ""; foreach my $type ("detail", "temperature") { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "type", value1 => $type, }, file => $THIS_FILE, line => __LINE__}); foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}}) { # Pick up the variables for the controller if (($type eq "detail") && ($variable eq "model_name")) { # Store and delete the value $new_hpacucli_controller_model = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_model", value1 => $new_hpacucli_controller_model, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "controller_status")) { # Store and delete the value $new_hpacucli_controller_status = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_controller_status = lc($new_hpacucli_controller_status); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_status", value1 => $new_hpacucli_controller_status, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "cache_board_present")) { # Store and delete the value $new_hpacucli_controller_cache_present = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_controller_cache_present = lc($new_hpacucli_controller_cache_present); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_cache_present", value1 => $new_hpacucli_controller_cache_present, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "drive_write_cache")) { # Store and delete the value $new_hpacucli_controller_drive_write_cache = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_controller_drive_write_cache = lc($new_hpacucli_controller_drive_write_cache); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_drive_write_cache", value1 => $new_hpacucli_controller_drive_write_cache, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "firmware_version")) { # Store and delete the value $new_hpacucli_controller_firmware_version = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_firmware_version", value1 => $new_hpacucli_controller_firmware_version, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "no_battery_write_cache")) { # Store and delete the value $new_hpacucli_controller_unsafe_writeback_cache = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_controller_unsafe_writeback_cache = lc($new_hpacucli_controller_unsafe_writeback_cache); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_controller_unsafe_writeback_cache", value1 => $new_hpacucli_controller_unsafe_writeback_cache, }, file => $THIS_FILE, line => __LINE__}); next; } # Pick up the data for the cache. elsif (($type eq "detail") && ($variable eq "total_cache_size")) { # Store and delete the value $new_hpacucli_cache_module_size = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_cache_module_size", value1 => $new_hpacucli_cache_module_size, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "cache_serial_number")) { # Store and delete the value $new_hpacucli_cache_module_serial_number = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_cache_module_serial_number", value1 => $new_hpacucli_cache_module_serial_number, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "cache_status")) { # Store and delete the value $new_hpacucli_cache_module_status = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_cache_module_status = lc($new_hpacucli_cache_module_status); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_cache_module_status", value1 => $new_hpacucli_cache_module_status, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($type eq "detail") && ($variable eq "cache_backup_power_source")) { # Store and delete the value $new_hpacucli_cache_module_type = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; $new_hpacucli_cache_module_type = lc($new_hpacucli_cache_module_type); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "new_hpacucli_cache_module_type", value1 => $new_hpacucli_cache_module_type, }, file => $THIS_FILE, line => __LINE__}); next; } else { # Just for debug $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::data::${type}::${variable}", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}, }, file => $THIS_FILE, line => __LINE__}); } } } # 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 ($controller_is_new) { $an->Log->entry({log_level => 2, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, name2 => "new_hpacucli_controller_model", value2 => $new_hpacucli_controller_model, name3 => "new_hpacucli_controller_cache_present", value3 => $new_hpacucli_controller_cache_present, name4 => "hnew_pacucli_controller_drive_write_cache", value4 => $new_hpacucli_controller_drive_write_cache, name5 => "new_hpacucli_controller_firmware_version", value5 => $new_hpacucli_controller_firmware_version, name6 => "new_hpacucli_controller_unsafe_writeback_cache", value6 => $new_hpacucli_controller_unsafe_writeback_cache, }, file => $THIS_FILE, line => __LINE__}); # Send an alert telling the user that we've found a new controller. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0001", alert_message_variables => { model => $new_hpacucli_controller_model, serial_number => $hpacucli_controller_serial_number, status => $new_hpacucli_controller_status, drive_write_cache => $new_hpacucli_controller_drive_write_cache, firmware_version => $new_hpacucli_controller_firmware_version, unsafe_writeback_cache => $new_hpacucli_controller_unsafe_writeback_cache, }, }); # INSERT my $query = " INSERT INTO hpacucli_controllers ( hpacucli_controller_uuid, hpacucli_controller_host_uuid, hpacucli_controller_serial_number, hpacucli_controller_model, hpacucli_controller_status, hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_model).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_status).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_last_diagnostics).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_cache_present).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_drive_write_cache).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_firmware_version).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_unsafe_writeback_cache).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } else { ### NOTE: The serial number and model should never change (a changed SN/controller ### should be picked up as a new controller), but we check/update just to be ### safe. # Controller already exists, check for changes. my $old_hpacucli_controller_serial_number = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_serial_number}; my $old_hpacucli_controller_model = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_model}; my $old_hpacucli_controller_status = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_status}; my $old_hpacucli_controller_last_diagnostics = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_last_diagnostics}; my $old_hpacucli_controller_cache_present = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_cache_present}; my $old_hpacucli_controller_drive_write_cache = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_drive_write_cache}; my $old_hpacucli_controller_firmware_version = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_firmware_version}; my $old_hpacucli_controller_unsafe_writeback_cache = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_unsafe_writeback_cache}; $an->Log->entry({log_level => 3, message_key => "an_variables_0009", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, name2 => "old_hpacucli_controller_serial_number", value2 => $old_hpacucli_controller_serial_number, name3 => "old_hpacucli_controller_model", value3 => $old_hpacucli_controller_model, name4 => "old_hpacucli_controller_status", value4 => $old_hpacucli_controller_status, name5 => "old_hpacucli_controller_last_diagnostics", value5 => $old_hpacucli_controller_last_diagnostics, name6 => "old_hpacucli_controller_cache_present", value6 => $old_hpacucli_controller_cache_present, name7 => "old_hpacucli_controller_drive_write_cache", value7 => $old_hpacucli_controller_drive_write_cache, name8 => "old_hpacucli_controller_firmware_version", value8 => $old_hpacucli_controller_firmware_version, name9 => "old_hpacucli_controller_unsafe_writeback_cache", value9 => $old_hpacucli_controller_unsafe_writeback_cache, }, file => $THIS_FILE, line => __LINE__}); # Delete this from the old cache. delete $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}; # NOTE: We don't check if the last diagnostics changed because it will change every # 10 minutes or so. if (($hpacucli_controller_serial_number ne $old_hpacucli_controller_serial_number) or ($new_hpacucli_controller_model ne $old_hpacucli_controller_model) or ($new_hpacucli_controller_status ne $old_hpacucli_controller_status) or ($new_hpacucli_controller_cache_present ne $old_hpacucli_controller_cache_present) or ($new_hpacucli_controller_drive_write_cache ne $old_hpacucli_controller_drive_write_cache) or ($new_hpacucli_controller_firmware_version ne $old_hpacucli_controller_firmware_version) or ($new_hpacucli_controller_unsafe_writeback_cache ne $old_hpacucli_controller_unsafe_writeback_cache)) { # Send a warning level alert because the most likely change is 'status'. If, # however, the status is now 'ok', then we'll clear the alert. my $title_key = "an_alert_title_0004"; my $message_key = "scan_hpacucli_warning_0002"; if ($new_hpacucli_controller_status ne $old_hpacucli_controller_status) { if (($new_hpacucli_controller_status ne $old_hpacucli_controller_status) && ($old_hpacucli_controller_status eq "VANISHED")) { # Controller has returned. $message_key = "scan_hpacucli_warning_0003"; } if (($new_hpacucli_controller_status ne $old_hpacucli_controller_status) && ($new_hpacucli_controller_status =~ /ok/i)) { # Clear the alert, the controller is OK again. $title_key = "an_alert_title_0006"; } } $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { new_serial_number => $hpacucli_controller_serial_number, old_serial_number => $old_hpacucli_controller_serial_number, new_model_name => $new_hpacucli_controller_model, old_model_name => $old_hpacucli_controller_model, new_status => $new_hpacucli_controller_status, old_status => $old_hpacucli_controller_status, new_cache_present => $new_hpacucli_controller_cache_present, old_cache_present => $old_hpacucli_controller_cache_present, new_drive_write_cache => $new_hpacucli_controller_drive_write_cache, old_drive_write_cache => $old_hpacucli_controller_drive_write_cache, new_firmware_version => $new_hpacucli_controller_firmware_version, old_firmware_version => $old_hpacucli_controller_firmware_version, new_unsafe_writeback_cache => $new_hpacucli_controller_unsafe_writeback_cache, old_unsafe_writeback_cache => $old_hpacucli_controller_unsafe_writeback_cache, }, }); my $query = " UPDATE hpacucli_controllers SET hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", hpacucli_controller_serial_number = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_serial_number).", hpacucli_controller_model = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_model).", hpacucli_controller_status = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_status).", hpacucli_controller_cache_present = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_cache_present).", hpacucli_controller_drive_write_cache = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_drive_write_cache).", hpacucli_controller_firmware_version = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_firmware_version).", hpacucli_controller_unsafe_writeback_cache = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_controller_unsafe_writeback_cache).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } # Now, if we had a cache module on this controller, see if we knew about it already. my $hpacucli_cache_module_uuid = ""; my $cache_is_new = 0; if ($new_hpacucli_cache_module_serial_number) { if ($an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$new_hpacucli_cache_module_serial_number}) { # Yup! $hpacucli_cache_module_uuid = $an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$new_hpacucli_cache_module_serial_number}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, }, file => $THIS_FILE, line => __LINE__}); } else { # No, this is a new cache module. Create a new UUID for it. $hpacucli_cache_module_uuid = $an->Get->uuid(); $cache_is_new = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "cache_is_new", value2 => $cache_is_new, }, file => $THIS_FILE, line => __LINE__}); # Add the keys for looking it up by UUID or serial number. $an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$new_hpacucli_cache_module_serial_number} = $hpacucli_cache_module_uuid; $an->data->{'scan-hpacucli'}{cache_modules}{by_uuid}{$hpacucli_cache_module_uuid} = $new_hpacucli_cache_module_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::cache_modules::by_serial::$new_hpacucli_cache_module_serial_number", value1 => $an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$new_hpacucli_cache_module_serial_number}, name2 => "scan-hpacucli::cache_modules::by_uuid::$hpacucli_cache_module_uuid", value2 => $an->data->{'scan-hpacucli'}{cache_modules}{by_uuid}{$hpacucli_cache_module_uuid}, }, file => $THIS_FILE, line => __LINE__}); } if ($cache_is_new) { $an->Log->entry({log_level => 3, message_key => "an_variables_0005", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "new_hpacucli_cache_module_size", value2 => $new_hpacucli_cache_module_size." (".$an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_cache_module_size}).")", name3 => "new_hpacucli_cache_module_serial_number", value3 => $new_hpacucli_cache_module_serial_number, name4 => "new_hpacucli_cache_module_status", value4 => $new_hpacucli_cache_module_status, name5 => "new_hpacucli_cache_module_type", value5 => $new_hpacucli_cache_module_type, }, file => $THIS_FILE, line => __LINE__}); # Send an alert telling the user that we've found a new controller. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0002", alert_message_variables => { serial_number => $new_hpacucli_cache_module_serial_number, cache_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_cache_module_size}), status => $new_hpacucli_cache_module_status, type => $new_hpacucli_cache_module_type, }, }); ### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0003", alert_message_key => "scan_hpacucli_note_0003", alert_message_variables => {}, }); # INSERT my $query = " INSERT INTO hpacucli_cache_modules ( hpacucli_cache_module_uuid, hpacucli_cache_module_host_uuid, hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number, hpacucli_cache_module_status, hpacucli_cache_module_type, hpacucli_cache_module_size, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_status).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_type).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_size).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } else { # Exists already, look for changes. The serial number should never change, # buuuut... my $old_hpacucli_cache_module_controller_uuid = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_controller_uuid}; my $old_hpacucli_cache_module_serial_number = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_serial_number}; my $old_hpacucli_cache_module_status = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_status}; my $old_hpacucli_cache_module_type = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_type}; my $old_hpacucli_cache_module_size = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_size}; $an->Log->entry({log_level => 3, message_key => "an_variables_0005", message_variables => { name1 => "old_hpacucli_cache_module_controller_uuid", value1 => $old_hpacucli_cache_module_controller_uuid, name2 => "old_hpacucli_cache_module_serial_number", value2 => $old_hpacucli_cache_module_serial_number, name3 => "old_hpacucli_cache_module_status", value3 => $old_hpacucli_cache_module_status, name4 => "old_hpacucli_cache_module_type", value4 => $old_hpacucli_cache_module_type, name5 => "old_hpacucli_cache_module_size", value5 => $old_hpacucli_cache_module_size, }, file => $THIS_FILE, line => __LINE__}); # Delete this so we know we saw it. delete $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}; if (($hpacucli_controller_uuid ne $old_hpacucli_cache_module_controller_uuid) or ($new_hpacucli_cache_module_serial_number ne $old_hpacucli_cache_module_serial_number) or ($new_hpacucli_cache_module_status ne $old_hpacucli_cache_module_status) or ($new_hpacucli_cache_module_type ne $old_hpacucli_cache_module_type) or ($new_hpacucli_cache_module_size ne $old_hpacucli_cache_module_size)) { # Something has changed, but what? Any change is likely bad, so we # default to 'warning'. my $title_key = "an_alert_title_0004"; my $message_key = "scan_hpacucli_warning_0004"; # Did the status return to 'ok'? if (($old_hpacucli_cache_module_status ne $new_hpacucli_cache_module_status) && ($old_hpacucli_cache_module_status eq "VANISHED")) { # The cache module is back $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_warning_0005"; } elsif (($old_hpacucli_cache_module_status ne $new_hpacucli_cache_module_status) && ($new_hpacucli_cache_module_status eq "ok")) { # The status is good now, clear the alert $title_key = "an_alert_title_0006"; } # Convert the old controller UUID to a serial number. my $query = "SELECT hpacucli_controller_serial_number FROM hpacucli_controllers WHERE hpacucli_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_hpacucli_cache_module_controller_uuid).";"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); my $old_controller_serial_number = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $old_controller_serial_number = "--" if not defined $old_controller_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "old_controller_serial_number", value1 => $old_controller_serial_number, }, file => $THIS_FILE, line => __LINE__}); # Send the alert $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { old_serial_number => $old_hpacucli_cache_module_serial_number, new_serial_number => $new_hpacucli_cache_module_serial_number, old_controller_serial_number => $old_controller_serial_number, new_controller_serial_number => $hpacucli_controller_serial_number, old_status => $old_hpacucli_cache_module_status, new_status => $old_hpacucli_cache_module_status, old_type => $new_hpacucli_cache_module_type, new_type => $old_hpacucli_cache_module_type, say_old_size => $an->Readable->bytes_to_hr({'bytes' => $old_hpacucli_cache_module_size}), say_new_size => $an->Readable->bytes_to_hr({'bytes' => $new_hpacucli_cache_module_size}), }, }); ### NOTE: The rest of the alerts will be in the format '- Variable: [$value]'. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0003", alert_message_variables => {}, }); # Update the database. $query = " UPDATE hpacucli_cache_modules SET hpacucli_cache_module_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", hpacucli_cache_module_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", hpacucli_cache_module_serial_number = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_serial_number).", hpacucli_cache_module_status = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_status).", hpacucli_cache_module_type = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_type).", hpacucli_cache_module_size = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_cache_module_size).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_cache_module_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } } # We do this after the cache so that the alerts make since when a new controller is found. foreach my $type ("detail", "temperature") { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "type", value1 => $type, }, file => $THIS_FILE, line => __LINE__}); foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}}) { my $new_hpacucli_variable_value = delete $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}; my $temperature = $type eq "temperature" ? "TRUE" : "FALSE"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "variable", value1 => $variable, name2 => "new_hpacucli_variable_value", value2 => $new_hpacucli_variable_value, name3 => "temperature", value3 => $temperature, }, file => $THIS_FILE, line => __LINE__}); # Now, if the variable doesn't exist, INSERT it. If it does exist, see if it # changed and UPDATE it if so. if (exists $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$variable}) { # Look for changes my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$variable}{hpacucli_variable_value}; my $variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$variable}{hpacucli_variable_uuid}; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "new_hpacucli_variable_value", value1 => $new_hpacucli_variable_value, name2 => "old_hpacucli_variable_value", value2 => $old_hpacucli_variable_value, name3 => "variable_uuid", value3 => $variable_uuid, }, file => $THIS_FILE, line => __LINE__}); # Delete it so that we know it has been processed. delete $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$variable}; # Set defaults my $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{high_critical}; my $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{high_warning}; my $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{low_warning}; my $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{low_critical}; my $jump = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{jump}; my $buffer = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{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; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } # Does this variable have defined limits? if (exists $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_critical}) { $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_critical}; $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_warning}; $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{low_warning}; $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{low_critical}; $jump = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{jump}; $buffer = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{buffer}; $clear_high_critical = $high_critical - $buffer; $clear_high_warning = $high_warning - $buffer; $clear_low_critical = $low_critical - $buffer; $clear_low_warning = $low_warning - $buffer; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } } # If it's a temperature, we need to analyze it and store it, # regardless of if it changed this pass. my $temperature_state = "ok"; my $temperature_is = "nominal"; my $message_key = "scan_hpacucli_note_0009"; my $alert_level = "notice"; my $title_key = "an_alert_title_0003"; my $delta = 0; if ($type eq "temperature") { # Change the log level to info as temperatures change often. $alert_level = "info"; $title_key = "an_alert_title_0002"; # Now see if the temperature has crossed into a # warning or critical state. if ($new_hpacucli_variable_value > $high_critical) { # Crossed the high critical threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", # This is not the alert level, 'warning' == trouble, 'clear' == ok now. alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0005"; } $temperature_state = "critical"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value > $high_warning) { # Crossed the high warning threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0006"; } $temperature_state = "warning"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value < $low_critical) { # Dropped below the low critical threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0007"; } $temperature_state = "critical"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value < $low_warning) { # Crossed the low warning threshold. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0008"; } $temperature_state = "warning"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } else { # Did it change enough to trigger a jump # alert? if ($new_hpacucli_variable_value > $old_hpacucli_variable_value) { # Jumped $delta = $new_hpacucli_variable_value - $old_hpacucli_variable_value; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "delta", value1 => $delta, }, file => $THIS_FILE, line => __LINE__}); if ($delta >= $jump) { # Big jump. $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0015"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } else { # Dropped $delta = $old_hpacucli_variable_value - $new_hpacucli_variable_value; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "delta", value1 => $delta, }, file => $THIS_FILE, line => __LINE__}); if ($delta >= $jump) { # Big drop. $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0016"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } } # Record this for later processing into the 'temperature' # table. my $sensor_host_key = "controller:$hpacucli_controller_serial_number"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sensor_host_key", value1 => $sensor_host_key, }, file => $THIS_FILE, line => __LINE__}); $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_celsius} = $new_hpacucli_variable_value; $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "new::temperature::${variable}::${sensor_host_key}::temperature_celsius", value1 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_celsius}, name2 => "new::temperature::${variable}::${sensor_host_key}::temperature_state", value2 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, name3 => "new::temperature::${variable}::${sensor_host_key}::temperature_is", value3 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, }, file => $THIS_FILE, line => __LINE__}); } # Did the variable change? if ($new_hpacucli_variable_value ne $old_hpacucli_variable_value) { # How has it changed? if ($old_hpacucli_variable_value eq "VANISHED") { $message_key = "scan_hpacucli_note_0010"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "message_key", value1 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } elsif ($type eq "temperature") { # Clear alerts, if needed. The order is important as # clearing a warning will replace clearing a critical # when a sensor goes critical -> ok in one scan. Once # done, we'll check if we've crossed into a warning # or critical state. If so, those will replace any # cleared messages. if ($new_hpacucli_variable_value < $clear_high_critical) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_critical", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "critical"; $title_key = "an_alert_title_0007"; $message_key = "scan_hpacucli_note_0011"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_variable_value < $clear_high_warning) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { # The temperature is no longer # warning, and it didn't just go # critical $alert_level = "warning"; $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0012"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_variable_value > $clear_low_critical) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_critical", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "critical"; $title_key = "an_alert_title_0007"; $message_key = "scan_hpacucli_note_0013"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } if ($new_hpacucli_variable_value > $clear_low_warning) { my $cleared = $an->Alert->check_alert_sent({ type => "clear", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_warning", modified_date => $an->data->{sys}{db_timestamp}, }); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "cleared", value1 => $cleared, }, file => $THIS_FILE, line => __LINE__}); if ($cleared) { $alert_level = "warning"; $title_key = "an_alert_title_0006"; $message_key = "scan_hpacucli_note_0014"; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "alert_level", value1 => $alert_level, name2 => "title_key", value2 => $title_key, name3 => "message_key", value3 => $message_key, }, file => $THIS_FILE, line => __LINE__}); } } } # Send an alert telling the user that we've found a variable for this # controller. Note that we add ' C' to the temperatures so that they get # translated to '°F' if desired by the reader. $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { sensor_name => $variable, serial_number => $hpacucli_controller_serial_number, name => $variable, old_value => $type eq "temperature" ? $old_hpacucli_variable_value." C" : $old_hpacucli_variable_value, new_value => $type eq "temperature" ? $new_hpacucli_variable_value." C" : $new_hpacucli_variable_value, high_critical_temperature => $high_critical." C", high_warning_temperature => $high_warning." C", low_critical_temperature => $low_critical." C", low_warning_temperature => $low_warning." C", delta => $delta, }, }); # UPDATE my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } else { # New, record. my $message_key = "scan_hpacucli_note_0004"; my $alert_level = "notice"; my $title_key = "an_alert_title_0003"; # Set defaults my $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{high_critical}; my $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{high_warning}; my $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{low_warning}; my $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{low_critical}; my $jump = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{jump}; my $buffer = $an->data->{'scan-hpacucli'}{thresholds}{'default'}{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; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($type eq "temperature") { # Does this variable have defined limits? if (exists $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_critical}) { $high_critical = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_critical}; $high_warning = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{high_warning}; $low_warning = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{low_warning}; $low_critical = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{low_critical}; $jump = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{jump}; $buffer = $an->data->{'scan-hpacucli'}{thresholds}{$variable}{buffer}; $clear_high_critical = $high_critical - $buffer; $clear_high_warning = $high_warning - $buffer; $clear_low_critical = $low_critical - $buffer; $clear_low_warning = $low_warning - $buffer; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "high_critical", value1 => $high_critical, name2 => "high_warning", value2 => $high_warning, name3 => "low_warning", value3 => $low_warning, name4 => "low_critical", value4 => $low_critical, name5 => "jump", value5 => $jump, name6 => "buffer", value6 => $buffer, name7 => "clear_high_critical", value7 => $clear_high_critical, name8 => "clear_high_warning", value8 => $clear_high_warning, name9 => "clear_low_critical", value9 => $clear_low_critical, name10 => "clear_low_warning", value10 => $clear_low_warning, }, file => $THIS_FILE, line => __LINE__}); # Fine-tune the alert thresholds if ($clear_high_critical < $high_warning) { $clear_high_critical = $high_warning + 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_high_critical", value1 => $clear_high_critical, }, file => $THIS_FILE, line => __LINE__}); } if ($clear_low_critical > $low_warning) { $clear_low_critical = $low_warning - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "clear_low_critical", value1 => $clear_low_critical, }, file => $THIS_FILE, line => __LINE__}); } } # 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 ($new_hpacucli_variable_value > $high_critical) { # Crossed the high critical threshold. This should # always be unset because it is a new variable, but # check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", # This is not the alert level, 'warning' == trouble, 'clear' == ok now. alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0005"; } $temperature_state = "critical"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value > $high_warning) { # Crossed the high warning threshold. This should # always be unset because it is a new variable, but # check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_high_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0006"; } $temperature_state = "warning"; $temperature_is = "high"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value < $low_critical) { # Dropped below the low critical threshold. This # should always be unset because it is a new # variable, but check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_critical", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "critical"; $title_key = "an_alert_title_0005"; $message_key = "scan_hpacucli_note_0007"; } $temperature_state = "critical"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } elsif ($new_hpacucli_variable_value < $low_warning) { # Crossed the low warning threshold. This should # always be unset because it is a new variable, but # check anyway. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_controller_serial_number, alert_name => $variable."_low_warning", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { $alert_level = "warning"; $title_key = "an_alert_title_0004"; $message_key = "scan_hpacucli_note_0008"; } $temperature_state = "warning"; $temperature_is = "low"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "temperature_state", value1 => $temperature_state, name2 => "temperature_is", value2 => $temperature_is, }, file => $THIS_FILE, line => __LINE__}); } # Record this for later processing into the 'temperature' # table. my $sensor_host_key = "controller:$hpacucli_controller_serial_number"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sensor_host_key", value1 => $sensor_host_key, }, file => $THIS_FILE, line => __LINE__}); $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_celsius} = $new_hpacucli_variable_value; $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state} = $temperature_state; $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is} = $temperature_is; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "new::temperature::${variable}::${sensor_host_key}::temperature_celsius", value1 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_celsius}, name2 => "new::temperature::${variable}::${sensor_host_key}::temperature_state", value2 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_state}, name3 => "new::temperature::${variable}::${sensor_host_key}::temperature_is", value3 => $an->data->{new}{temperature}{$variable}{$sensor_host_key}{temperature_is}, }, file => $THIS_FILE, line => __LINE__}); } # Send an alert telling the user that we've found a variable for this # controller. Note that we add ' C' to the temperatures so that they get # translated to '°F' if desired by the reader. $an->Alert->register_alert({ alert_level => $alert_level, alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}++, alert_header => 'FALSE', alert_title_key => $title_key, alert_message_key => $message_key, alert_message_variables => { sensor_name => $variable, serial_number => $hpacucli_controller_serial_number, name => $variable, value => $type eq "temperature" ? $new_hpacucli_variable_value." C" : $new_hpacucli_variable_value, high_critical_temperature => $high_critical." C", high_warning_temperature => $high_warning." C", low_critical_temperature => $low_critical." C", low_warning_temperature => $low_warning." C", }, }); # INSERT my $query = " INSERT INTO hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->Get->uuid()).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", 'hpacucli_controllers', ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($temperature).", ".$an->data->{sys}{use_db_fh}->quote($variable).", ".$an->data->{sys}{use_db_fh}->quote($new_hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } } } # Look for removed controllers foreach my $hpacucli_controller_uuid (keys %{$an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}}) { # Controller vanished! my $old_hpacucli_controller_serial_number = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_serial_number}; my $old_hpacucli_controller_model = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_model}; my $old_hpacucli_controller_status = $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "old_hpacucli_controller_serial_number", value2 => $old_hpacucli_controller_serial_number, name3 => "old_hpacucli_controller_model", value3 => $old_hpacucli_controller_model, name4 => "old_hpacucli_controller_status", value4 => $old_hpacucli_controller_status, }, file => $THIS_FILE, line => __LINE__}); # Delete it so that we know it has been processed. delete $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}; # If the old alarm state is already 'VANISHED', ignore it. next if $old_hpacucli_controller_status 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. $an->data->{sys}{alert_sort}++; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}, alert_header => "TRUE", alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0017", alert_message_variables => { model => $old_hpacucli_controller_model, serial_number => $old_hpacucli_controller_serial_number, }, }); my $query = " UPDATE hpacucli_controllers SET hpacucli_controller_status = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Look for removed cache modules foreach my $hpacucli_cache_module_uuid (keys %{$an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}}) { # Controller vanished! my $old_hpacucli_cache_module_serial_number = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_serial_number}; my $old_hpacucli_cache_module_status = $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "old_hpacucli_cache_module_serial_number", value2 => $old_hpacucli_cache_module_serial_number, name3 => "old_hpacucli_cache_module_status", value3 => $old_hpacucli_cache_module_status, }, file => $THIS_FILE, line => __LINE__}); # Delete it so that we know it has been processed. delete $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}; # If the old alarm state is already 'VANISHED', ignore it. next if $old_hpacucli_cache_module_status eq "VANISHED"; # Still here? Alert and UPDATE. ### NOTE: For now, we're going to use warning level because cache_modules 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. $an->data->{sys}{alert_sort}++; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}, alert_header => "TRUE", alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_note_0018", alert_message_variables => { serial_number => $old_hpacucli_cache_module_serial_number, }, }); my $query = " UPDATE hpacucli_cache_modules SET hpacucli_cache_module_status = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_cache_module_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } # Look for removed controller variables. foreach my $hpacucli_controller_uuid (keys %{$an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}}) { # Get the serial numbre for this contrller my $hpacucli_controller_serial_number = $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "hpacucli_controller_serial_number", value2 => $hpacucli_controller_serial_number, }, file => $THIS_FILE, line => __LINE__}); foreach my $type ("detail", "temperature") { foreach my $hpacucli_variable_name (sort {$a cmp $b} keys %{$an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}}) { my $old_hpacucli_variable_value = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$hpacucli_variable_name}{hpacucli_variable_value}; my $old_hpacucli_variable_uuid = $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{hpacucli_controllers}{source_uuid}{$hpacucli_controller_uuid}{$type}{$hpacucli_variable_name}{hpacucli_variable_uuid}; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "type", value1 => $type, name2 => "hpacucli_variable_name", value2 => $hpacucli_variable_name, name3 => "old_hpacucli_variable_value", value3 => $old_hpacucli_variable_value, name4 => "old_hpacucli_variable_uuid", value4 => $old_hpacucli_variable_uuid, }, file => $THIS_FILE, line => __LINE__}); # If the old alarm state is already 'VANISHED', ignore it. next if $old_hpacucli_variable_value eq "VANISHED"; # Still here? Alert and UPDATE. ### NOTE: For now, we're going to use warning level because cache_modules ### 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 $message_key = $type eq "temperature" ? "scan_hpacucli_note_0019" : "scan_hpacucli_note_0020"; $an->data->{sys}{alert_sort}++; $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_sort => $an->data->{sys}{alert_sort}, alert_title_key => "an_alert_title_0004", alert_message_key => $message_key, alert_message_variables => { serial_number => $hpacucli_controller_serial_number, name => $hpacucli_variable_name, }, }); my $query = " UPDATE hpacucli_variables SET hpacucli_variable_value = 'VANISHED', modified_date = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{db_timestamp})." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($old_hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{sys}{sql}}, $query; } } } # Now commit the changes. $an->DB->commit_sql({source => $THIS_FILE, line => __LINE__}); return(0); } # This reads in the last scan's data. sub read_last_scan { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "read_last_scan" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Read in the controller(s) my $query = " SELECT hpacucli_controller_uuid, hpacucli_controller_serial_number, hpacucli_controller_model, hpacucli_controller_status, hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache FROM hpacucli_controllers WHERE hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).";"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); my $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_controller_uuid = $row->[0]; my $hpacucli_controller_serial_number = $row->[1]; my $hpacucli_controller_model = $row->[2]; my $hpacucli_controller_status = $row->[3]; my $hpacucli_controller_last_diagnostics = defined $row->[4]; my $hpacucli_controller_cache_present = $row->[5]; my $hpacucli_controller_drive_write_cache = $row->[6]; my $hpacucli_controller_firmware_version = defined $row->[7] ? $row->[7] : ""; my $hpacucli_controller_unsafe_writeback_cache = defined $row->[8] ? $row->[8] : ""; $an->Log->entry({log_level => 3, message_key => "an_variables_0009", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "hpacucli_controller_serial_number", value2 => $hpacucli_controller_serial_number, name3 => "hpacucli_controller_model", value3 => $hpacucli_controller_model, name4 => "hpacucli_controller_status", value4 => $hpacucli_controller_status, name5 => "hpacucli_controller_last_diagnostics", value5 => $hpacucli_controller_last_diagnostics, name6 => "hpacucli_controller_cache_present", value6 => $hpacucli_controller_cache_present, name7 => "hpacucli_controller_drive_write_cache", value7 => $hpacucli_controller_drive_write_cache, name8 => "hpacucli_controller_firmware_version", value8 => $hpacucli_controller_firmware_version, name9 => "hpacucli_controller_unsafe_writeback_cache", value9 => $hpacucli_controller_unsafe_writeback_cache, }, file => $THIS_FILE, line => __LINE__}); # Store the information about this controllers $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number} = $hpacucli_controller_uuid; $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid} = $hpacucli_controller_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::controllers::by_serial::${hpacucli_controller_serial_number}", value1 => $an->data->{'scan-hpacucli'}{controllers}{by_serial}{$hpacucli_controller_serial_number}, name2 => "scan-hpacucli::controllers::by_uuid::${hpacucli_controller_uuid}", value2 => $an->data->{'scan-hpacucli'}{controllers}{by_uuid}{$hpacucli_controller_uuid}, }, file => $THIS_FILE, line => __LINE__}); $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid} = { hpacucli_controller_serial_number => $hpacucli_controller_serial_number, hpacucli_controller_model => $hpacucli_controller_model, hpacucli_controller_status => $hpacucli_controller_status, hpacucli_controller_last_diagnostics => $hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present => $hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache => $hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version => $hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache => $hpacucli_controller_unsafe_writeback_cache, }; $an->Log->entry({log_level => 3, message_key => "an_variables_0009", message_variables => { name1 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_serial_number", value1 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_serial_number}, name2 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_model", value2 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_model}, name3 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_status", value3 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_status}, name4 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_last_diagnostics", value4 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_last_diagnostics}, name5 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_cache_present", value5 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_cache_present}, name6 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_drive_write_cache", value6 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_drive_write_cache}, name7 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_firmware_version", value7 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_firmware_version}, name8 => "sql::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::hpacucli_controller_unsafe_writeback_cache", value8 => $an->data->{sql}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_unsafe_writeback_cache}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # Now load the cache data $query = " SELECT hpacucli_cache_module_uuid, hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number, hpacucli_cache_module_status, hpacucli_cache_module_type, hpacucli_cache_module_size FROM hpacucli_cache_modules WHERE hpacucli_cache_module_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_cache_module_uuid = $row->[0]; my $hpacucli_cache_module_controller_uuid = $row->[1]; my $hpacucli_cache_module_serial_number = $row->[2]; my $hpacucli_cache_module_status = $row->[3]; my $hpacucli_cache_module_type = $row->[4]; my $hpacucli_cache_module_size = $row->[5]; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "hpacucli_cache_module_controller_uuid", value2 => $hpacucli_cache_module_controller_uuid, name3 => "hpacucli_cache_module_serial_number", value3 => $hpacucli_cache_module_serial_number, name4 => "hpacucli_cache_module_status", value4 => $hpacucli_cache_module_status, name5 => "hpacucli_cache_module_type", value5 => $hpacucli_cache_module_type, name6 => "hpacucli_cache_module_size", value6 => $hpacucli_cache_module_size, }, file => $THIS_FILE, line => __LINE__}); # Store the information about this cache_module $an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$hpacucli_cache_module_serial_number} = $hpacucli_cache_module_uuid; $an->data->{'scan-hpacucli'}{cache_modules}{by_uuid}{$hpacucli_cache_module_uuid} = $hpacucli_cache_module_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::cache_modules::by_serial::${hpacucli_cache_module_serial_number}", value1 => $an->data->{'scan-hpacucli'}{cache_modules}{by_serial}{$hpacucli_cache_module_serial_number}, name2 => "scan-hpacucli::cache_modules::by_uuid::${hpacucli_cache_module_uuid}", value2 => $an->data->{'scan-hpacucli'}{cache_modules}{by_uuid}{$hpacucli_cache_module_uuid}, }, file => $THIS_FILE, line => __LINE__}); $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid} = { hpacucli_cache_module_controller_uuid => $hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number => $hpacucli_cache_module_serial_number, hpacucli_cache_module_status => $hpacucli_cache_module_status, hpacucli_cache_module_type => $hpacucli_cache_module_type, hpacucli_cache_module_size => $hpacucli_cache_module_size, }; $an->Log->entry({log_level => 3, message_key => "an_variables_0005", message_variables => { name1 => "sql::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::hpacucli_cache_module_controller_uuid", value1 => $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_controller_uuid}, name2 => "sql::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::hpacucli_cache_module_serial_number", value2 => $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_serial_number}, name3 => "sql::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::hpacucli_cache_module_status", value3 => $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_status}, name4 => "sql::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::hpacucli_cache_module_type", value4 => $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_type}, name5 => "sql::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::hpacucli_cache_module_size", value5 => $an->data->{sql}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_size}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # The array data... $query = " SELECT hpacucli_array_uuid, hpacucli_array_controller_uuid, hpacucli_array_name, hpacucli_array_type, hpacucli_array_status, hpacucli_array_error_message FROM hpacucli_arrays WHERE hpacucli_array_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_array_uuid = $row->[0]; my $hpacucli_array_controller_uuid = $row->[1]; my $hpacucli_array_name = $row->[2]; my $hpacucli_array_type = $row->[3]; my $hpacucli_array_status = $row->[4]; my $hpacucli_array_error_message = defined $row->[5] ? $row->[5] : ""; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_array_uuid", value1 => $hpacucli_array_uuid, name2 => "hpacucli_array_controller_uuid", value2 => $hpacucli_array_controller_uuid, name3 => "hpacucli_array_name", value3 => $hpacucli_array_name, name4 => "hpacucli_array_type", value4 => $hpacucli_array_type, name5 => "hpacucli_array_status", value5 => $hpacucli_array_status, name6 => "hpacucli_array_error_message", value6 => $hpacucli_array_error_message, }, file => $THIS_FILE, line => __LINE__}); # Store the information about this virtual drive. $an->data->{'scan-hpacucli'}{virtual_drives}{by_name}{$hpacucli_array_name} = $hpacucli_array_uuid; $an->data->{'scan-hpacucli'}{virtual_drives}{by_uuid}{$hpacucli_array_uuid} = $hpacucli_array_name; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::virtual_drives::by_name::${hpacucli_array_name}", value1 => $an->data->{'scan-hpacucli'}{virtual_drives}{by_name}{$hpacucli_array_name}, name2 => "scan-hpacucli::virtual_drives::by_uuid::${hpacucli_array_uuid}", value2 => $an->data->{'scan-hpacucli'}{virtual_drives}{by_uuid}{$hpacucli_array_uuid}, }, file => $THIS_FILE, line => __LINE__}); # Store the drive group data. (Drive groups have no SN) $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid} = { hpacucli_array_controller_uuid => $hpacucli_array_controller_uuid, hpacucli_array_name => $hpacucli_array_name, hpacucli_array_type => $hpacucli_array_type, hpacucli_array_status => $hpacucli_array_status, hpacucli_array_error_message => $hpacucli_array_error_message, }; $an->Log->entry({log_level => 3, message_key => "an_variables_0005", message_variables => { name1 => "sql::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::hpacucli_array_controller_uuid", value1 => $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_controller_uuid}, name2 => "sql::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::hpacucli_array_name", value2 => $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_name}, name3 => "sql::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::hpacucli_array_type", value3 => $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_type}, name4 => "sql::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::hpacucli_array_status", value4 => $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_status}, name5 => "sql::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::hpacucli_array_error_message", value5 => $an->data->{sql}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_error_message}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # The drive group data... $query = " SELECT hpacucli_logical_drive_uuid, hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name, hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status FROM hpacucli_logical_drives WHERE hpacucli_logical_drive_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_logical_drive_uuid = $row->[0]; my $hpacucli_logical_drive_array_uuid = $row->[1]; my $hpacucli_logical_drive_name = $row->[2]; my $hpacucli_logical_drive_caching = $row->[3]; my $hpacucli_logical_drive_os_device_name = $row->[4]; my $hpacucli_logical_drive_type = $row->[5]; my $hpacucli_logical_drive_raid_level = $row->[6]; my $hpacucli_logical_drive_size = $row->[7]; my $hpacucli_logical_drive_strip_size = $row->[8]; my $hpacucli_logical_drive_stripe_size = $row->[9]; my $hpacucli_logical_drive_status = $row->[10]; $an->Log->entry({log_level => 3, message_key => "an_variables_0011", message_variables => { name1 => "hpacucli_logical_drive_uuid", value1 => $hpacucli_logical_drive_uuid, name2 => "hpacucli_logical_drive_array_uuid", value2 => $hpacucli_logical_drive_array_uuid, name3 => "hpacucli_logical_drive_name", value3 => $hpacucli_logical_drive_name, name4 => "hpacucli_logical_drive_caching", value4 => $hpacucli_logical_drive_caching, name5 => "hpacucli_logical_drive_os_device_name", value5 => $hpacucli_logical_drive_os_device_name, name6 => "hpacucli_logical_drive_type", value6 => $hpacucli_logical_drive_type, name7 => "hpacucli_logical_drive_raid_level", value7 => $hpacucli_logical_drive_raid_level, name8 => "hpacucli_logical_drive_size", value8 => $hpacucli_logical_drive_size, name9 => "hpacucli_logical_drive_strip_size", value9 => $hpacucli_logical_drive_strip_size, name10 => "hpacucli_logical_drive_stripe_size", value10 => $hpacucli_logical_drive_stripe_size, name11 => "hpacucli_logical_drive_status", value11 => $hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); # Store the information about this virtual drive. $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name} = $hpacucli_logical_drive_uuid; $an->data->{'scan-hpacucli'}{logical_drives}{by_uuid}{$hpacucli_logical_drive_uuid} = $hpacucli_logical_drive_name; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::logical_drives::by_name::${hpacucli_logical_drive_name}", value1 => $an->data->{'scan-hpacucli'}{logical_drives}{by_name}{$hpacucli_logical_drive_name}, name2 => "scan-hpacucli::logical_drives::by_uuid::${hpacucli_logical_drive_uuid}", value2 => $an->data->{'scan-hpacucli'}{logical_drives}{by_uuid}{$hpacucli_logical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); # Store the logical drive data. (LDs have no SN) $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid} = { hpacucli_logical_drive_array_uuid => $hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name => $hpacucli_logical_drive_name, hpacucli_logical_drive_caching => $hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name => $hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type => $hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level => $hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size => $hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size => $hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size => $hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status => $hpacucli_logical_drive_status, }; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_array_uuid", value1 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_array_uuid}, name2 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_name", value2 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_name}, name3 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_caching", value3 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_caching}, name4 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_os_device_name", value4 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_os_device_name}, name5 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_type", value5 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_type}, name6 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_raid_level", value6 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_raid_level}, name7 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_size", value7 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_size}, name8 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_strip_size", value8 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_strip_size}, name9 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_stripe_size", value9 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_stripe_size}, name10 => "sql::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::hpacucli_logical_drive_status", value10 => $an->data->{sql}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_status}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # And now, the physical drives. $query = " SELECT hpacucli_physical_drive_uuid, hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model, hpacucli_physical_drive_interface, hpacucli_physical_drive_status, hpacucli_physical_drive_size, hpacucli_physical_drive_type, hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port, hpacucli_physical_drive_box, hpacucli_physical_drive_bay FROM hpacucli_physical_drives WHERE hpacucli_physical_drive_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_physical_drive_uuid = $row->[0]; my $hpacucli_physical_drive_logical_drive_uuid = $row->[1]; my $hpacucli_physical_drive_serial_number = $row->[2]; my $hpacucli_physical_drive_model = $row->[3]; my $hpacucli_physical_drive_interface = $row->[4]; my $hpacucli_physical_drive_status = $row->[5]; my $hpacucli_physical_drive_size = $row->[6]; my $hpacucli_physical_drive_type = $row->[7]; my $hpacucli_physical_drive_rpm = $row->[8]; my $hpacucli_physical_drive_temperature = defined $row->[9] ? $row->[9] : ""; my $hpacucli_physical_drive_last_failure_reason = $row->[10]; my $hpacucli_physical_drive_port = $row->[11]; my $hpacucli_physical_drive_box = $row->[12]; my $hpacucli_physical_drive_bay = $row->[13]; $an->Log->entry({log_level => 3, message_key => "an_variables_0014", message_variables => { name1 => "hpacucli_physical_drive_uuid", value1 => $hpacucli_physical_drive_uuid, name2 => "hpacucli_physical_drive_logical_drive_uuid", value2 => $hpacucli_physical_drive_logical_drive_uuid, name3 => "hpacucli_physical_drive_serial_number", value3 => $hpacucli_physical_drive_serial_number, name4 => "hpacucli_physical_drive_model", value4 => $hpacucli_physical_drive_model, name5 => "hpacucli_physical_drive_interface", value5 => $hpacucli_physical_drive_interface, name6 => "hpacucli_physical_drive_status", value6 => $hpacucli_physical_drive_status, name7 => "hpacucli_physical_drive_size", value7 => $hpacucli_physical_drive_size, name8 => "hpacucli_physical_drive_type", value8 => $hpacucli_physical_drive_type, name9 => "hpacucli_physical_drive_rpm", value9 => $hpacucli_physical_drive_rpm, name10 => "hpacucli_physical_drive_temperature", value10 => $hpacucli_physical_drive_temperature, name11 => "hpacucli_physical_drive_last_failure_reason", value11 => $hpacucli_physical_drive_last_failure_reason, name12 => "hpacucli_physical_drive_port", value12 => $hpacucli_physical_drive_port, name13 => "hpacucli_physical_drive_box", value13 => $hpacucli_physical_drive_box, name14 => "hpacucli_physical_drive_bay", value14 => $hpacucli_physical_drive_bay, }, file => $THIS_FILE, line => __LINE__}); # Make it so that we can look up the serial number from the drive's UUID and vice versa $an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number} = $hpacucli_physical_drive_uuid; $an->data->{'scan-hpacucli'}{physical_drives}{by_uuid}{$hpacucli_physical_drive_uuid} = $hpacucli_physical_drive_serial_number; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "scan-hpacucli::physical_drives::by_serial::${hpacucli_physical_drive_serial_number}", value1 => $an->data->{'scan-hpacucli'}{physical_drives}{by_serial}{$hpacucli_physical_drive_serial_number}, name2 => "scan-hpacucli::physical_drives::by_uuid::${hpacucli_physical_drive_uuid}", value2 => $an->data->{'scan-hpacucli'}{physical_drives}{by_uuid}{$hpacucli_physical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); # Store the information about this physical drive $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid} = { hpacucli_physical_drive_logical_drive_uuid => $hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number => $hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model => $hpacucli_physical_drive_model, hpacucli_physical_drive_interface => $hpacucli_physical_drive_interface, hpacucli_physical_drive_status => $hpacucli_physical_drive_status, hpacucli_physical_drive_size => $hpacucli_physical_drive_size, hpacucli_physical_drive_type => $hpacucli_physical_drive_type, hpacucli_physical_drive_rpm => $hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature => $hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason => $hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port => $hpacucli_physical_drive_port, hpacucli_physical_drive_box => $hpacucli_physical_drive_box, hpacucli_physical_drive_bay => $hpacucli_physical_drive_bay, }; $an->Log->entry({log_level => 3, message_key => "an_variables_0013", message_variables => { name1 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_logical_drive_uuid", value1 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_logical_drive_uuid}, name2 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_serial_number", value2 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_serial_number}, name3 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_model", value3 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_model}, name4 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_interface", value4 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_interface}, name5 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_status", value5 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_status}, name6 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_size", value6 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_size}, name7 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_type", value7 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_type}, name8 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_rpm", value8 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_rpm}, name9 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_temperature", value9 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_temperature}, name10 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_last_failure_reason", value10 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_last_failure_reason}, name11 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_port", value11 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_port}, name12 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_box", value12 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_box}, name13 => "sql::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::hpacucli_physical_drive_bay", value13 => $an->data->{sql}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_bay}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # Lastly, the variables. $query = " SELECT hpacucli_variable_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value FROM hpacucli_variables WHERE hpacucli_variable_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); $results = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results, }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_variable_uuid = $row->[0]; my $hpacucli_variable_source_table = $row->[1]; my $hpacucli_variable_source_uuid = $row->[2]; my $hpacucli_variable_is_temperature = $row->[3]; my $hpacucli_variable_name = $row->[4]; my $hpacucli_variable_value = defined $row->[5] ? $row->[5] : ""; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "hpacucli_variable_source_table", value2 => $hpacucli_variable_source_table, name3 => "hpacucli_variable_source_uuid", value3 => $hpacucli_variable_source_uuid, name4 => "hpacucli_variable_is_temperature", value4 => $hpacucli_variable_is_temperature, name5 => "hpacucli_variable_name", value5 => $hpacucli_variable_name, name6 => "hpacucli_variable_value", value6 => $hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); # We store these differently for easier reference. Diagnostic data is stored in the special # 'hpacucli_physical_drive_diagnostics' source. my $type = "detail"; if ($hpacucli_variable_source_table eq "hpacucli_physical_drive_diagnostics") { $type = "diagnostics"; } if ($hpacucli_variable_is_temperature eq "1") { $type = "temperature"; } $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{$hpacucli_variable_source_table}{source_uuid}{$hpacucli_variable_source_uuid}{$type}{$hpacucli_variable_name} = { hpacucli_variable_uuid => $hpacucli_variable_uuid, hpacucli_variable_is_temperature => $hpacucli_variable_is_temperature, hpacucli_variable_value => $hpacucli_variable_value, }; # Entries are so long that we log the one per variable. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::${hpacucli_variable_source_table}::source_uuid::${hpacucli_variable_source_uuid}::${type}::${hpacucli_variable_name}::hpacucli_variable_uuid", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{$hpacucli_variable_source_table}{source_uuid}{$hpacucli_variable_source_uuid}{$type}{$hpacucli_variable_name}{hpacucli_variable_uuid}, }, file => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::${hpacucli_variable_source_table}::source_uuid::${hpacucli_variable_source_uuid}::${type}::${hpacucli_variable_name}::hpacucli_variable_is_temperature", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{$hpacucli_variable_source_table}{source_uuid}{$hpacucli_variable_source_uuid}{$type}{$hpacucli_variable_name}{hpacucli_variable_is_temperature}, }, file => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sql::hpacucli_variables::hpacucli_variable_uuid::source_table::${hpacucli_variable_source_table}::source_uuid::${hpacucli_variable_source_uuid}::${type}::${hpacucli_variable_name}::hpacucli_variable_value", value1 => $an->data->{sql}{hpacucli_variables}{hpacucli_variable_uuid}{source_table}{$hpacucli_variable_source_table}{source_uuid}{$hpacucli_variable_source_uuid}{$type}{$hpacucli_variable_name}{hpacucli_variable_value}, }, file => $THIS_FILE, line => __LINE__}); } undef $results; # Return the number return(0); } # This looks for anything other than temperature sensors that will feed into the health of the node. sub pre_process_health { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "pre_process_health" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # This is to collected data from every sweep. foreach my $hpacucli_controller_serial_number (sort {$a cmp $b} keys %{$an->data->{controller}}) { # We don't care about metadata next if $hpacucli_controller_serial_number eq "metadata"; # Controller data foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}}) { if (($variable eq "battery_or_capacitor_status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{$variable}) ne "ok")) { # BBU/FBU problem, score of 2 my $health_source_name = "controller:".$hpacucli_controller_serial_number.":data:".$variable; $an->data->{health}{new}{$health_source_name} = 2; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } elsif (($variable eq "cache_status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{$variable}) ne "ok")) { # Cache isn't OK, score of 2 my $health_source_name = "controller:".$hpacucli_controller_serial_number.":data:".$variable; $an->data->{health}{new}{$health_source_name} = 2; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } elsif (($variable eq "controller_status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{$variable}) ne "ok")) { # The controller isn't OK, this is major, score of 10 my $health_source_name = "controller:".$hpacucli_controller_serial_number.":data:".$variable; $an->data->{health}{new}{$health_source_name} = 10; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } } # Array foreach my $hpacucli_array_name (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}}) { # Data foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}}) { if (($variable eq "status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{$variable}) ne "ok")) { # Something is wrong with this array my $health_source_name = "controller:".$hpacucli_controller_serial_number.":array:".$hpacucli_array_name.":".$variable; $an->data->{health}{new}{$health_source_name} = 5; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } } # Logical Drive foreach my $logical_drive (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}}) { # Data foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{data}{detail}}) { if (($variable eq "caching") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{data}{detail}{$variable}) ne "enabled")) { # Not enabled is going to hurt performance. my $health_source_name = "controller:".$hpacucli_controller_serial_number.":array:".$hpacucli_array_name.":logical_drive:".$logical_drive.":".$variable; $an->data->{health}{new}{$health_source_name} = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } elsif (($variable eq "status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{data}{detail}{$variable}) ne "ok")) { # If the status isn't OK, it's degraded (or rebuilding, but # still degraded). my $health_source_name = "controller:".$hpacucli_controller_serial_number.":array:".$hpacucli_array_name.":logical_drive:".$logical_drive.":".$variable; $an->data->{health}{new}{$health_source_name} = 2; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } } # Physical Disks. foreach my $port (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}}) { foreach my $box (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}}) { foreach my $bay (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}}) { my $hpacucli_physical_drive_serial_number = $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{serial_number}; # Data foreach my $variable (sort {$a cmp $b} keys %{$an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}}) { next if $variable eq "serial_number"; next if $variable eq "port"; next if $variable eq "box"; next if $variable eq "bay"; if (($variable eq "status") && (lc($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{$variable}) ne "ok")) { # The drive is failed or is rebuilding. This adds 2. my $health_source_name = "controller:".$hpacucli_controller_serial_number.":physical_drive:".$hpacucli_physical_drive_serial_number.":data:".$variable; $an->data->{health}{new}{$health_source_name} = 2; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } } # If this was a diagnostics run, check for error # counters if ($an->data->{sys}{process_diagnostics}) { # If the diagnostics don't exist for the # drive and the drive is OK, it's likely a # 3rd party drive. If the status is not OK, # there may not be diagnostic data. if (exists $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_hard}) { # We got the data foreach my $variable (sort {$a cmp $b} keys %{$an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}}) { # Store this in the main hash. if ((($variable eq "hardware_errors") or ($variable eq "predictive_failure_errors") or ($variable eq "read_errors_hard") or ($variable eq "write_errors_hard")) && ($an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{$variable} =~ /^\d+$/) && ($an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{$variable} > 0)) { # How high is the error count? my $score = 1; if ($an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{$variable} > 10) { # Eek $score = 3; } elsif ($an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{$variable} > 5) { # Getting a little high $score = 2; } my $health_source_name = "controller:".$hpacucli_controller_serial_number.":physical_drive:".$hpacucli_physical_drive_serial_number.":diagnostics:".$variable; $an->data->{health}{new}{$health_source_name} = $score; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "health::new::controller:$health_source_name", value1 => $an->data->{health}{new}{$health_source_name}, }, file => $THIS_FILE, line => __LINE__}); } # Record the diagnostic data # under the drive's hash. $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{'diagnostics'}{$variable} = $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{$variable}; } } elsif (lc($an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{detail}{status}) eq "ok") { # No data for this drive. It might be # a 3rd party drive. We'll warn the # user that we can't predict failure. my $set = $an->Alert->check_alert_sent({ type => "warning", alert_sent_by => $THIS_FILE, alert_record_locator => $hpacucli_physical_drive_serial_number, alert_name => "no_diagnostics", modified_date => $an->data->{sys}{db_timestamp}, }); if ($set) { # Warn the user that we can't # predict this drive's death. $an->Alert->register_alert({ alert_level => "warning", alert_agent_name => $THIS_FILE, alert_title_key => "an_alert_title_0004", alert_message_key => "scan_hpacucli_warning_0001", alert_message_variables => { serial_number => $hpacucli_physical_drive_serial_number, port => $port, box => $box, bay => $bay, }, }); } } } } } } } } } return(0); } # This looks at each DB's 'updated' table to see if any are behind. If any are, it will update the tables # based on the time the last entry was made for a given host. sub update_db { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "scancore::db_resync_needed", value1 => $an->data->{scancore}{db_resync_needed}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{scancore}{db_resync_needed}) { # Request a lock. $an->DB->locking({request => 1}); # Update Controllers and the various dangly bits hanging off them. update_db_controllers($an); update_db_cache_modules($an); update_db_arrays($an); update_db_logical_drives($an); update_db_physical_drives($an); update_db_variables($an); # Release the lock $an->DB->locking({release => 1}); } return(0); } # Update the 'hpacucli_variables' table. sub update_db_variables { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_variables" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_variables' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_variable_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date FROM history.hpacucli_variables WHERE hpacucli_variable_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_variable_uuid = $row->[0]; my $hpacucli_variable_source_table = $row->[1]; my $hpacucli_variable_source_uuid = $row->[2]; my $hpacucli_variable_is_temperature = $row->[3]; my $hpacucli_variable_name = $row->[4]; my $hpacucli_variable_value = defined $row->[5] ? $row->[5] : ""; my $modified_date = $row->[6]; $an->Log->entry({log_level => 3, message_key => "an_variables_0007", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "hpacucli_variable_source_table", value2 => $hpacucli_variable_source_table, name3 => "hpacucli_variable_source_uuid", value3 => $hpacucli_variable_source_uuid, name4 => "hpacucli_variable_is_temperature", value4 => $hpacucli_variable_is_temperature, name5 => "hpacucli_variable_name", value5 => $hpacucli_variable_name, name6 => "hpacucli_variable_value", value6 => $hpacucli_variable_value, name7 => "modified_date", value7 => $modified_date }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid} = { hpacucli_variable_source_table => $hpacucli_variable_source_table, hpacucli_variable_source_uuid => $hpacucli_variable_source_uuid, hpacucli_variable_is_temperature => $hpacucli_variable_is_temperature, hpacucli_variable_name => $hpacucli_variable_name, hpacucli_variable_value => $hpacucli_variable_value, }; $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid} = { hpacucli_variable_source_table => $hpacucli_variable_source_table, hpacucli_variable_source_uuid => $hpacucli_variable_source_uuid, hpacucli_variable_is_temperature => $hpacucli_variable_is_temperature, hpacucli_variable_name => $hpacucli_variable_name, hpacucli_variable_value => $hpacucli_variable_value, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it # needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_variables}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_variable_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}}) { my $hpacucli_variable_source_table = $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{hpacucli_variable_source_table}; my $hpacucli_variable_source_uuid = $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{hpacucli_variable_source_uuid}; my $hpacucli_variable_is_temperature = $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{hpacucli_variable_is_temperature}; my $hpacucli_variable_name = $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{hpacucli_variable_name}; my $hpacucli_variable_value = $an->data->{db_data}{unified}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{hpacucli_variable_value}; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_variable_uuid", value1 => $hpacucli_variable_uuid, name2 => "hpacucli_variable_source_table", value2 => $hpacucli_variable_source_table, name3 => "hpacucli_variable_source_uuid", value3 => $hpacucli_variable_source_uuid, name4 => "hpacucli_variable_is_temperature", value4 => $hpacucli_variable_is_temperature, name5 => "hpacucli_variable_name", value5 => $hpacucli_variable_name, name6 => "hpacucli_variable_value", value6 => $hpacucli_variable_value, }, file => $THIS_FILE, line => __LINE__}); foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_variable_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_variables::hpacucli_variable_uuid::${hpacucli_variable_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_variables::hpacucli_variable_uuid::${hpacucli_variable_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_variables}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_variables::modified_date::${modified_date}::hpacucli_variable_uuid::${hpacucli_variable_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}) { # No, so UPDATE it. Note that I don't need to worry # about the host_uuid because we've only got # hpacucli_variable_uuid from this host. my $query = " UPDATE public.hpacucli_variables SET hpacucli_variable_source_table = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_table).", hpacucli_variable_source_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_uuid).", hpacucli_variable_is_temperature = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_is_temperature).", hpacucli_variable_name = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", hpacucli_variable_value = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_value).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_variable_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_table).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_is_temperature).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_variable_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_variables}{modified_date}{$modified_date}{hpacucli_variable_uuid}{$hpacucli_variable_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_variables ( hpacucli_variable_uuid, hpacucli_variable_host_uuid, hpacucli_variable_source_table, hpacucli_variable_source_uuid, hpacucli_variable_is_temperature, hpacucli_variable_name, hpacucli_variable_value, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_table).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_source_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_is_temperature).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_variable_value).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_variable_uuid? } # foreach my $id } # foreach my $hpacucli_variable_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # Update the 'hpacucli_physical_drives' table. sub update_db_physical_drives { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_physical_drives" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_physical_drives' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_physical_drive_uuid, hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model, hpacucli_physical_drive_interface, hpacucli_physical_drive_status, hpacucli_physical_drive_size, hpacucli_physical_drive_type, hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port, hpacucli_physical_drive_box, hpacucli_physical_drive_bay, modified_date FROM history.hpacucli_physical_drives WHERE hpacucli_physical_drive_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_physical_drive_uuid = $row->[0]; my $hpacucli_physical_drive_logical_drive_uuid = $row->[1]; my $hpacucli_physical_drive_serial_number = $row->[2]; my $hpacucli_physical_drive_model = $row->[3]; my $hpacucli_physical_drive_interface = $row->[4]; my $hpacucli_physical_drive_status = $row->[5]; my $hpacucli_physical_drive_size = $row->[6]; my $hpacucli_physical_drive_type = $row->[7]; my $hpacucli_physical_drive_rpm = $row->[8]; my $hpacucli_physical_drive_temperature = defined $row->[9] ? $row->[9] : ""; my $hpacucli_physical_drive_last_failure_reason = $row->[10]; my $hpacucli_physical_drive_port = $row->[11]; my $hpacucli_physical_drive_box = $row->[12]; my $hpacucli_physical_drive_bay = $row->[13]; my $modified_date = $row->[14]; $an->Log->entry({log_level => 3, message_key => "an_variables_0015", message_variables => { name1 => "hpacucli_physical_drive_uuid", value1 => $hpacucli_physical_drive_uuid, name2 => "hpacucli_physical_drive_logical_drive_uuid", value2 => $hpacucli_physical_drive_logical_drive_uuid, name3 => "hpacucli_physical_drive_serial_number", value3 => $hpacucli_physical_drive_serial_number, name4 => "hpacucli_physical_drive_model", value4 => $hpacucli_physical_drive_model, name5 => "hpacucli_physical_drive_interface", value5 => $hpacucli_physical_drive_interface, name6 => "hpacucli_physical_drive_status", value6 => $hpacucli_physical_drive_status, name7 => "hpacucli_physical_drive_size", value7 => $hpacucli_physical_drive_size, name8 => "hpacucli_physical_drive_type", value8 => $hpacucli_physical_drive_type, name9 => "hpacucli_physical_drive_rpm", value9 => $hpacucli_physical_drive_rpm, name10 => "hpacucli_physical_drive_temperature", value10 => $hpacucli_physical_drive_temperature, name11 => "hpacucli_physical_drive_last_failure_reason", value11 => $hpacucli_physical_drive_last_failure_reason, name12 => "hpacucli_physical_drive_port", value12 => $hpacucli_physical_drive_port, name13 => "hpacucli_physical_drive_box", value13 => $hpacucli_physical_drive_box, name14 => "hpacucli_physical_drive_bay", value14 => $hpacucli_physical_drive_bay, name15 => "modified_date", value15 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid} = { hpacucli_physical_drive_logical_drive_uuid => $hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number => $hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model => $hpacucli_physical_drive_model, hpacucli_physical_drive_interface => $hpacucli_physical_drive_interface, hpacucli_physical_drive_status => $hpacucli_physical_drive_status, hpacucli_physical_drive_size => $hpacucli_physical_drive_size, hpacucli_physical_drive_type => $hpacucli_physical_drive_type, hpacucli_physical_drive_rpm => $hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature => $hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason => $hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port => $hpacucli_physical_drive_port, hpacucli_physical_drive_box => $hpacucli_physical_drive_box, hpacucli_physical_drive_bay => $hpacucli_physical_drive_bay, }; $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid} = { hpacucli_physical_drive_logical_drive_uuid => $hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number => $hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model => $hpacucli_physical_drive_model, hpacucli_physical_drive_interface => $hpacucli_physical_drive_interface, hpacucli_physical_drive_status => $hpacucli_physical_drive_status, hpacucli_physical_drive_size => $hpacucli_physical_drive_size, hpacucli_physical_drive_type => $hpacucli_physical_drive_type, hpacucli_physical_drive_rpm => $hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature => $hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason => $hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port => $hpacucli_physical_drive_port, hpacucli_physical_drive_box => $hpacucli_physical_drive_box, hpacucli_physical_drive_bay => $hpacucli_physical_drive_bay, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_physical_drive_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}}) { my $hpacucli_physical_drive_logical_drive_uuid = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_logical_drive_uuid}; my $hpacucli_physical_drive_serial_number = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_serial_number}; my $hpacucli_physical_drive_model = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_model}; my $hpacucli_physical_drive_interface = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_interface}; my $hpacucli_physical_drive_status = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_status}; my $hpacucli_physical_drive_size = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_size}; my $hpacucli_physical_drive_type = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_type}; my $hpacucli_physical_drive_rpm = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_rpm}; my $hpacucli_physical_drive_temperature = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_temperature}; my $hpacucli_physical_drive_last_failure_reason = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_last_failure_reason}; my $hpacucli_physical_drive_port = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_port}; my $hpacucli_physical_drive_box = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_box}; my $hpacucli_physical_drive_bay = $an->data->{db_data}{unified}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{hpacucli_physical_drive_bay}; $an->Log->entry({log_level => 3, message_key => "an_variables_0014", message_variables => { name1 => "hpacucli_physical_drive_uuid", value1 => $hpacucli_physical_drive_uuid, name2 => "hpacucli_physical_drive_logical_drive_uuid", value2 => $hpacucli_physical_drive_logical_drive_uuid, name3 => "hpacucli_physical_drive_serial_number", value3 => $hpacucli_physical_drive_serial_number, name4 => "hpacucli_physical_drive_model", value4 => $hpacucli_physical_drive_model, name5 => "hpacucli_physical_drive_interface", value5 => $hpacucli_physical_drive_interface, name6 => "hpacucli_physical_drive_status", value6 => $hpacucli_physical_drive_status, name7 => "hpacucli_physical_drive_size", value7 => $hpacucli_physical_drive_size, name8 => "hpacucli_physical_drive_type", value8 => $hpacucli_physical_drive_type, name9 => "hpacucli_physical_drive_rpm", value9 => $hpacucli_physical_drive_rpm, name10 => "hpacucli_physical_drive_temperature", value10 => $hpacucli_physical_drive_temperature, name11 => "hpacucli_physical_drive_last_failure_reason", value11 => $hpacucli_physical_drive_last_failure_reason, name12 => "hpacucli_physical_drive_port", value12 => $hpacucli_physical_drive_port, name13 => "hpacucli_physical_drive_box", value13 => $hpacucli_physical_drive_box, name14 => "hpacucli_physical_drive_bay", value14 => $hpacucli_physical_drive_bay, }, file => $THIS_FILE, line => __LINE__}); # We need to sanity check the three numeric strings because calling 'quote' directly # will wrap the numeric values in single quotes which violates 'numeric' forms. my $quoted_hpacucli_physical_drive_size = $an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_size); my $quoted_hpacucli_physical_drive_rpm = $an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_rpm); my $quoted_hpacucli_physical_drive_temperature = $an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_temperature); $quoted_hpacucli_physical_drive_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_physical_drive_rpm =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_physical_drive_temperature =~ s/^'(.*?)'$/$1/; if ((($quoted_hpacucli_physical_drive_size) && ($quoted_hpacucli_physical_drive_size =~ /\D/)) or (($quoted_hpacucli_physical_drive_rpm) && ($quoted_hpacucli_physical_drive_rpm =~ /\D/)) or (($quoted_hpacucli_physical_drive_temperature) && ($quoted_hpacucli_physical_drive_temperature =~ /\D/))) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0010", message_variables => { size => $quoted_hpacucli_physical_drive_size, rpm => $quoted_hpacucli_physical_drive_rpm, temperature => $quoted_hpacucli_physical_drive_temperature, }, code => 8, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 8}); } $quoted_hpacucli_physical_drive_size = "NULL" if $quoted_hpacucli_physical_drive_size eq ""; $quoted_hpacucli_physical_drive_rpm = "NULL" if $quoted_hpacucli_physical_drive_rpm eq ""; $quoted_hpacucli_physical_drive_temperature = "NULL" if $quoted_hpacucli_physical_drive_temperature eq ""; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "quoted_hpacucli_physical_drive_size", value1 => $quoted_hpacucli_physical_drive_size, name2 => "quoted_hpacucli_physical_drive_rpm", value2 => $quoted_hpacucli_physical_drive_rpm, name3 => "quoted_hpacucli_physical_drive_temperature", value3 => $hpacucli_physical_drive_serial_number, }, file => $THIS_FILE, line => __LINE__}); foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_physical_drive_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_physical_drives::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_physical_drives}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_physical_drives::modified_date::${modified_date}::hpacucli_physical_drive_uuid::${hpacucli_physical_drive_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}) { # No, so UPDATE it. Note that I don't need to worry # about the host_uuid because we've only got # hpacucli_physical_drive_uuid from this host. my $query = " UPDATE public.hpacucli_physical_drives SET hpacucli_physical_drive_logical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_logical_drive_uuid).", hpacucli_physical_drive_serial_number = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_serial_number).", hpacucli_physical_drive_model = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_model).", hpacucli_physical_drive_interface = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_interface).", hpacucli_physical_drive_status = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_status).", hpacucli_physical_drive_size = $quoted_hpacucli_physical_drive_size, hpacucli_physical_drive_type = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_type).", hpacucli_physical_drive_rpm = $quoted_hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature = $quoted_hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_last_failure_reason).", hpacucli_physical_drive_port = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_port).", hpacucli_physical_drive_box = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_box).", hpacucli_physical_drive_bay = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_bay).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_physical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_physical_drives ( hpacucli_physical_drive_uuid, hpacucli_physical_drive_host_uuid, hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model, hpacucli_physical_drive_interface, hpacucli_physical_drive_status, hpacucli_physical_drive_size, hpacucli_physical_drive_type, hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port, hpacucli_physical_drive_box, hpacucli_physical_drive_bay, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_model).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_interface).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_status).", $quoted_hpacucli_physical_drive_size, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_type).", $quoted_hpacucli_physical_drive_rpm, $quoted_hpacucli_physical_drive_temperature, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_last_failure_reason).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_port).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_box).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_bay).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_physical_drive_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_physical_drives}{modified_date}{$modified_date}{hpacucli_physical_drive_uuid}{$hpacucli_physical_drive_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_physical_drives ( hpacucli_physical_drive_uuid, hpacucli_physical_drive_host_uuid, hpacucli_physical_drive_logical_drive_uuid, hpacucli_physical_drive_serial_number, hpacucli_physical_drive_model, hpacucli_physical_drive_interface, hpacucli_physical_drive_status, hpacucli_physical_drive_size, hpacucli_physical_drive_type, hpacucli_physical_drive_rpm, hpacucli_physical_drive_temperature, hpacucli_physical_drive_last_failure_reason, hpacucli_physical_drive_port, hpacucli_physical_drive_box, hpacucli_physical_drive_bay, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_model).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_interface).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_status).", $quoted_hpacucli_physical_drive_size, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_type).", $quoted_hpacucli_physical_drive_rpm, $quoted_hpacucli_physical_drive_temperature, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_last_failure_reason).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_port).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_box).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_physical_drive_bay).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_physical_drive_uuid? } # foreach my $id } # foreach my $hpacucli_physical_drive_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # Update the 'hpacucli_logical_drives' table. sub update_db_logical_drives { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_logical_drives" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_logical_drives' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_logical_drive_uuid, hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name, hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status, modified_date FROM history.hpacucli_logical_drives WHERE hpacucli_logical_drive_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_logical_drive_uuid = $row->[0]; my $hpacucli_logical_drive_array_uuid = $row->[1]; my $hpacucli_logical_drive_name = $row->[2]; my $hpacucli_logical_drive_caching = $row->[3]; my $hpacucli_logical_drive_os_device_name = $row->[4]; my $hpacucli_logical_drive_type = $row->[5]; my $hpacucli_logical_drive_raid_level = $row->[6]; my $hpacucli_logical_drive_size = $row->[7]; my $hpacucli_logical_drive_strip_size = $row->[8]; my $hpacucli_logical_drive_stripe_size = $row->[9]; my $hpacucli_logical_drive_status = $row->[10]; my $modified_date = $row->[11]; $an->Log->entry({log_level => 3, message_key => "an_variables_0012", message_variables => { name1 => "hpacucli_logical_drive_uuid", value1 => $hpacucli_logical_drive_uuid, name2 => "hpacucli_logical_drive_array_uuid", value2 => $hpacucli_logical_drive_array_uuid, name3 => "hpacucli_logical_drive_name", value3 => $hpacucli_logical_drive_name, name4 => "hpacucli_logical_drive_caching", value4 => $hpacucli_logical_drive_caching, name5 => "hpacucli_logical_drive_os_device_name", value5 => $hpacucli_logical_drive_os_device_name, name6 => "hpacucli_logical_drive_type", value6 => $hpacucli_logical_drive_type, name7 => "hpacucli_logical_drive_raid_level", value7 => $hpacucli_logical_drive_raid_level, name8 => "hpacucli_logical_drive_size", value8 => $hpacucli_logical_drive_size, name9 => "hpacucli_logical_drive_strip_size", value9 => $hpacucli_logical_drive_strip_size, name10 => "hpacucli_logical_drive_stripe_size", value10 => $hpacucli_logical_drive_stripe_size, name11 => "hpacucli_logical_drive_status", value11 => $hpacucli_logical_drive_status, name12 => "modified_date", value12 => $modified_date }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid} = { hpacucli_logical_drive_array_uuid => $hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name => $hpacucli_logical_drive_name, hpacucli_logical_drive_caching => $hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name => $hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type => $hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level => $hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size => $hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size => $hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size => $hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status => $hpacucli_logical_drive_status, }; $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid} = { hpacucli_logical_drive_array_uuid => $hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name => $hpacucli_logical_drive_name, hpacucli_logical_drive_caching => $hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name => $hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type => $hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level => $hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size => $hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size => $hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size => $hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status => $hpacucli_logical_drive_status, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it # needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_logical_drive_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}}) { my $hpacucli_logical_drive_array_uuid = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_array_uuid}; my $hpacucli_logical_drive_name = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_name}; my $hpacucli_logical_drive_caching = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_caching}; my $hpacucli_logical_drive_os_device_name = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_os_device_name}; my $hpacucli_logical_drive_type = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_type}; my $hpacucli_logical_drive_raid_level = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_raid_level}; my $hpacucli_logical_drive_size = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_size}; my $hpacucli_logical_drive_strip_size = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_strip_size}; my $hpacucli_logical_drive_stripe_size = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_stripe_size}; my $hpacucli_logical_drive_status = $an->data->{db_data}{unified}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{hpacucli_logical_drive_status}; $an->Log->entry({log_level => 3, message_key => "an_variables_0011", message_variables => { name1 => "hpacucli_logical_drive_uuid", value1 => $hpacucli_logical_drive_uuid, name2 => "hpacucli_logical_drive_array_uuid", value2 => $hpacucli_logical_drive_array_uuid, name3 => "hpacucli_logical_drive_name", value3 => $hpacucli_logical_drive_name, name4 => "hpacucli_logical_drive_caching", value4 => $hpacucli_logical_drive_caching, name5 => "hpacucli_logical_drive_os_device_name", value5 => $hpacucli_logical_drive_os_device_name, name6 => "hpacucli_logical_drive_type", value6 => $hpacucli_logical_drive_type, name7 => "hpacucli_logical_drive_raid_level", value7 => $hpacucli_logical_drive_raid_level, name8 => "hpacucli_logical_drive_size", value8 => $hpacucli_logical_drive_size, name9 => "hpacucli_logical_drive_strip_size", value9 => $hpacucli_logical_drive_strip_size, name10 => "hpacucli_logical_drive_stripe_size", value10 => $hpacucli_logical_drive_stripe_size, name11 => "hpacucli_logical_drive_status", value11 => $hpacucli_logical_drive_status, }, file => $THIS_FILE, line => __LINE__}); # We need to sanity check the three numeric strings because calling 'quote' directly # will wrap the numeric values in single quotes which violates 'numeric' forms. my $quoted_hpacucli_logical_drive_size = $an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_size); my $quoted_hpacucli_logical_drive_strip_size = $an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_strip_size); my $quoted_hpacucli_logical_drive_stripe_size = $an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_stripe_size); $quoted_hpacucli_logical_drive_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_strip_size =~ s/^'(.*?)'$/$1/; $quoted_hpacucli_logical_drive_stripe_size =~ s/^'(.*?)'$/$1/; if ((($quoted_hpacucli_logical_drive_size) && ($quoted_hpacucli_logical_drive_size =~ /\D/)) or (($quoted_hpacucli_logical_drive_strip_size) && ($quoted_hpacucli_logical_drive_strip_size =~ /\D/)) or (($quoted_hpacucli_logical_drive_stripe_size) && ($quoted_hpacucli_logical_drive_stripe_size =~ /\D/))) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0009", message_variables => { logical_drive_size => $quoted_hpacucli_logical_drive_size, strip_size => $quoted_hpacucli_logical_drive_strip_size, stripe_size => $quoted_hpacucli_logical_drive_stripe_size, }, code => 7, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 7}); } $quoted_hpacucli_logical_drive_size = "NULL" if $quoted_hpacucli_logical_drive_size eq ""; $quoted_hpacucli_logical_drive_strip_size = "NULL" if $quoted_hpacucli_logical_drive_strip_size eq ""; $quoted_hpacucli_logical_drive_stripe_size = "NULL" if $quoted_hpacucli_logical_drive_stripe_size eq ""; foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_logical_drive_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_logical_drives::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_logical_drives}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_logical_drives::modified_date::${modified_date}::hpacucli_logical_drive_uuid::${hpacucli_logical_drive_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}) { # No, so UPDATE it. Note that I don't need to worry # about the host_uuid because we've only got # hpacucli_logical_drive_uuid from this host. my $query = " UPDATE public.hpacucli_logical_drives SET hpacucli_logical_drive_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_array_uuid).", hpacucli_logical_drive_name = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_name).", hpacucli_logical_drive_caching = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_caching).", hpacucli_logical_drive_os_device_name = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_os_device_name).", hpacucli_logical_drive_type = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_type).", hpacucli_logical_drive_raid_level = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_raid_level).", hpacucli_logical_drive_size = $quoted_hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size = $quoted_hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size = $quoted_hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_status).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_logical_drive_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_logical_drives ( hpacucli_logical_drive_uuid, hpacucli_logical_drive_host_uuid, hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name, hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_caching).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_os_device_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_type).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_raid_level).", $quoted_hpacucli_logical_drive_size, $quoted_hpacucli_logical_drive_strip_size, $quoted_hpacucli_logical_drive_stripe_size, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_status).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_logical_drive_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_logical_drives}{modified_date}{$modified_date}{hpacucli_logical_drive_uuid}{$hpacucli_logical_drive_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_logical_drives ( hpacucli_logical_drive_uuid, hpacucli_logical_drive_host_uuid, hpacucli_logical_drive_array_uuid, hpacucli_logical_drive_name, hpacucli_logical_drive_caching, hpacucli_logical_drive_os_device_name, hpacucli_logical_drive_type, hpacucli_logical_drive_raid_level, hpacucli_logical_drive_size, hpacucli_logical_drive_strip_size, hpacucli_logical_drive_stripe_size, hpacucli_logical_drive_status, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_caching).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_os_device_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_type).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_raid_level).", $quoted_hpacucli_logical_drive_size, $quoted_hpacucli_logical_drive_strip_size, $quoted_hpacucli_logical_drive_stripe_size, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_logical_drive_status).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_logical_drive_uuid? } # foreach my $id } # foreach my $hpacucli_logical_drive_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # Update the 'hpacucli_arrays' table. sub update_db_arrays { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_arrays" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_arrays' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_array_uuid, hpacucli_array_controller_uuid, hpacucli_array_name, hpacucli_array_type, hpacucli_array_status, hpacucli_array_error_message, modified_date FROM history.hpacucli_arrays WHERE hpacucli_array_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_array_uuid = $row->[0]; my $hpacucli_array_controller_uuid = $row->[1]; my $hpacucli_array_name = $row->[2]; my $hpacucli_array_type = $row->[3]; my $hpacucli_array_status = $row->[4]; my $hpacucli_array_error_message = defined $row->[5] ? $row->[5] : ""; my $modified_date = $row->[6]; $an->Log->entry({log_level => 3, message_key => "an_variables_0007", message_variables => { name1 => "hpacucli_array_uuid", value1 => $hpacucli_array_uuid, name2 => "hpacucli_array_controller_uuid", value2 => $hpacucli_array_controller_uuid, name3 => "hpacucli_array_name", value3 => $hpacucli_array_name, name4 => "hpacucli_array_type", value4 => $hpacucli_array_type, name5 => "hpacucli_array_status", value5 => $hpacucli_array_status, name6 => "hpacucli_array_error_message", value6 => $hpacucli_array_error_message, name7 => "modified_date", value7 => $modified_date }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid} = { hpacucli_array_controller_uuid => $hpacucli_array_controller_uuid, hpacucli_array_name => $hpacucli_array_name, hpacucli_array_type => $hpacucli_array_type, hpacucli_array_status => $hpacucli_array_status, hpacucli_array_error_message => $hpacucli_array_error_message, }; $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid} = { hpacucli_array_controller_uuid => $hpacucli_array_controller_uuid, hpacucli_array_name => $hpacucli_array_name, hpacucli_array_type => $hpacucli_array_type, hpacucli_array_status => $hpacucli_array_status, hpacucli_array_error_message => $hpacucli_array_error_message, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it # needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_array_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}}) { my $hpacucli_array_controller_uuid = $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_controller_uuid}; my $hpacucli_array_name = $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_name}; my $hpacucli_array_type = $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_type}; my $hpacucli_array_status = $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_status}; my $hpacucli_array_error_message = $an->data->{db_data}{unified}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}{hpacucli_array_error_message}; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_array_uuid", value1 => $hpacucli_array_uuid, name2 => "hpacucli_array_controller_uuid", value2 => $hpacucli_array_controller_uuid, name3 => "hpacucli_array_name", value3 => $hpacucli_array_name, name4 => "hpacucli_array_type", value4 => $hpacucli_array_type, name5 => "hpacucli_array_status", value5 => $hpacucli_array_status, name6 => "hpacucli_array_error_message", value6 => $hpacucli_array_error_message, }, file => $THIS_FILE, line => __LINE__}); foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_array_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_arrays::hpacucli_array_uuid::${hpacucli_array_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_arrays}{hpacucli_array_uuid}{$hpacucli_array_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_arrays::modified_date::${modified_date}::hpacucli_array_uuid::${hpacucli_array_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}) { # No, so UPDATE it. Note that I don't need to worry # about the host_uuid because we've only got # hpacucli_array_uuid from this host. my $query = " UPDATE public.hpacucli_arrays SET hpacucli_array_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_controller_uuid).", hpacucli_array_name = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_name).", hpacucli_array_type = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_type).", hpacucli_array_status = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_status).", hpacucli_array_error_message = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_error_message).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_array_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_arrays ( hpacucli_array_uuid, hpacucli_array_host_uuid, hpacucli_array_controller_uuid, hpacucli_array_name, hpacucli_array_type, hpacucli_array_status, hpacucli_array_error_message, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_type).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_status).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_error_message).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_array_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_arrays}{modified_date}{$modified_date}{hpacucli_array_uuid}{$hpacucli_array_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_arrays ( hpacucli_array_uuid, hpacucli_array_host_uuid, hpacucli_array_controller_uuid, hpacucli_array_name, hpacucli_array_type, hpacucli_array_status, hpacucli_array_error_message, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_name).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_type).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_status).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_array_error_message).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_array_uuid? } # foreach my $id } # foreach my $hpacucli_array_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # Update the 'hpacucli_cache_modules' table. sub update_db_cache_modules { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_cache_modules" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_cache_modules' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_cache_module_uuid, hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number, hpacucli_cache_module_status, hpacucli_cache_module_type, hpacucli_cache_module_size, modified_date FROM history.hpacucli_cache_modules WHERE hpacucli_cache_module_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_cache_module_uuid = $row->[0]; my $hpacucli_cache_module_controller_uuid = $row->[1]; my $hpacucli_cache_module_serial_number = $row->[2]; my $hpacucli_cache_module_status = $row->[3]; my $hpacucli_cache_module_type = $row->[4]; my $hpacucli_cache_module_size = $row->[5]; my $modified_date = $row->[6]; $an->Log->entry({log_level => 3, message_key => "an_variables_0007", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "hpacucli_cache_module_controller_uuid", value2 => $hpacucli_cache_module_controller_uuid, name3 => "hpacucli_cache_module_serial_number", value3 => $hpacucli_cache_module_serial_number, name4 => "hpacucli_cache_module_status", value4 => $hpacucli_cache_module_status, name5 => "hpacucli_cache_module_type", value5 => $hpacucli_cache_module_type, name6 => "hpacucli_cache_module_size", value6 => $hpacucli_cache_module_size, name7 => "modified_date", value7 => $modified_date }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid} = { hpacucli_cache_module_controller_uuid => $hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number => $hpacucli_cache_module_serial_number, hpacucli_cache_module_status => $hpacucli_cache_module_status, hpacucli_cache_module_type => $hpacucli_cache_module_type, hpacucli_cache_module_size => $hpacucli_cache_module_size, }; $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid} = { hpacucli_cache_module_controller_uuid => $hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number => $hpacucli_cache_module_serial_number, hpacucli_cache_module_status => $hpacucli_cache_module_status, hpacucli_cache_module_type => $hpacucli_cache_module_type, hpacucli_cache_module_size => $hpacucli_cache_module_size, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it # needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_cache_module_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}}) { my $hpacucli_cache_module_controller_uuid = $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_controller_uuid}; my $hpacucli_cache_module_serial_number = $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_serial_number}; my $hpacucli_cache_module_status = $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_status}; my $hpacucli_cache_module_type = $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_type}; my $hpacucli_cache_module_size = $an->data->{db_data}{unified}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{hpacucli_cache_module_size}; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "hpacucli_cache_module_uuid", value1 => $hpacucli_cache_module_uuid, name2 => "hpacucli_cache_module_controller_uuid", value2 => $hpacucli_cache_module_controller_uuid, name3 => "hpacucli_cache_module_serial_number", value3 => $hpacucli_cache_module_serial_number, name4 => "hpacucli_cache_module_status", value4 => $hpacucli_cache_module_status, name5 => "hpacucli_cache_module_type", value5 => $hpacucli_cache_module_type, name6 => "hpacucli_cache_module_size", value6 => $hpacucli_cache_module_size, }, file => $THIS_FILE, line => __LINE__}); # We need to sanity check the three numeric strings because calling 'quote' directly # will wrap the numeric values in single quotes which violates 'numeric' forms. my $quoted_hpacucli_cache_module_size = $an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_size); $quoted_hpacucli_cache_module_size =~ s/^'(.*?)'$/$1/; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "quoted_hpacucli_cache_module_size", value1 => $quoted_hpacucli_cache_module_size, }, file => $THIS_FILE, line => __LINE__}); if ((($quoted_hpacucli_cache_module_size) && ($quoted_hpacucli_cache_module_size =~ /\D/))) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0007", message_variables => { size => $quoted_hpacucli_cache_module_size, }, code => 5, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 5}); } $quoted_hpacucli_cache_module_size = "NULL" if $quoted_hpacucli_cache_module_size eq ""; foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_cache_module_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_cache_modules::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_cache_modules}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_cache_modules::modified_date::${modified_date}::hpacucli_cache_module_uuid::${hpacucli_cache_module_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}) { # No, so UPDATE it. Note that I don't need to worry # about the host_uuid because we've only got # hpacucli_cache_module_uuid from this host. my $query = " UPDATE public.hpacucli_cache_modules SET hpacucli_cache_module_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_controller_uuid).", hpacucli_cache_module_serial_number = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_serial_number).", hpacucli_cache_module_status = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_status).", hpacucli_cache_module_type = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_type).", hpacucli_cache_module_size = $quoted_hpacucli_cache_module_size, modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_cache_module_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_cache_modules ( hpacucli_cache_module_uuid, hpacucli_cache_module_host_uuid, hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number, hpacucli_cache_module_status, hpacucli_cache_module_type, hpacucli_cache_module_size, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_status).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_type).", $quoted_hpacucli_cache_module_size, ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_cache_module_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_cache_modules}{modified_date}{$modified_date}{hpacucli_cache_module_uuid}{$hpacucli_cache_module_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_cache_modules ( hpacucli_cache_module_uuid, hpacucli_cache_module_host_uuid, hpacucli_cache_module_controller_uuid, hpacucli_cache_module_serial_number, hpacucli_cache_module_status, hpacucli_cache_module_type, hpacucli_cache_module_size, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_uuid).", ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_status).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_cache_module_type).", $quoted_hpacucli_cache_module_size, ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_cache_module_uuid? } # foreach my $id } # foreach my $hpacucli_cache_module_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # Update the 'hpacucli_controllers' table. sub update_db_controllers { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "update_db_controllers" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Now read in all the 'hpacucli_controllers' table records that came from us. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # These will store the INSERTs for this DB, if needed. $an->data->{db_resync}{$id}{sql} = []; $an->data->{db_resync}{$id}{public}{sql} = []; $an->data->{db_resync}{$id}{history}{sql} = []; # Read in the history schema my $query = " SELECT hpacucli_controller_uuid, hpacucli_controller_serial_number, hpacucli_controller_model, hpacucli_controller_status, hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache, modified_date FROM history.hpacucli_controllers WHERE hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); # Do the query against the source DB and loop through the results. my $results = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "results", value1 => $results }, file => $THIS_FILE, line => __LINE__}); foreach my $row (@{$results}) { my $hpacucli_controller_uuid = $row->[0]; my $hpacucli_controller_serial_number = $row->[1]; my $hpacucli_controller_model = $row->[2]; my $hpacucli_controller_status = $row->[3]; my $hpacucli_controller_last_diagnostics = defined $row->[4] ? $row->[4] : 'NULL'; my $hpacucli_controller_cache_present = $row->[5]; my $hpacucli_controller_drive_write_cache = $row->[6]; my $hpacucli_controller_firmware_version = defined $row->[7] ? $row->[7] : 'NULL'; my $hpacucli_controller_unsafe_writeback_cache = defined $row->[8] ? $row->[8] : 'NULL'; my $modified_date = $row->[9]; $an->Log->entry({log_level => 3, message_key => "an_variables_0010", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "hpacucli_controller_serial_number", value2 => $hpacucli_controller_serial_number, name3 => "hpacucli_controller_model", value3 => $hpacucli_controller_model, name4 => "hpacucli_controller_status", value4 => $hpacucli_controller_status, name5 => "hpacucli_controller_last_diagnostics", value5 => $hpacucli_controller_last_diagnostics, name6 => "hpacucli_controller_cache_present", value6 => $hpacucli_controller_cache_present, name7 => "hpacucli_controller_drive_write_cache", value7 => $hpacucli_controller_drive_write_cache, name8 => "hpacucli_controller_firmware_version", value8 => $hpacucli_controller_firmware_version, name9 => "hpacucli_controller_unsafe_writeback_cache", value9 => $hpacucli_controller_unsafe_writeback_cache, name10 => "modified_date", value10 => $modified_date }, file => $THIS_FILE, line => __LINE__}); ### There can only be one entry per host, so we don't have a subhash. # Record this in the unified and local hashes. $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid} = { hpacucli_controller_serial_number => $hpacucli_controller_serial_number, hpacucli_controller_model => $hpacucli_controller_model, hpacucli_controller_status => $hpacucli_controller_status, hpacucli_controller_last_diagnostics => $hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present => $hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache => $hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version => $hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache => $hpacucli_controller_unsafe_writeback_cache, }; $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{'exists'} = 1; $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{seen} = 0; $an->data->{db_data}{$id}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid} = { hpacucli_controller_serial_number => $hpacucli_controller_serial_number, hpacucli_controller_model => $hpacucli_controller_model, hpacucli_controller_status => $hpacucli_controller_status, hpacucli_controller_last_diagnostics => $hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present => $hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache => $hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version => $hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache => $hpacucli_controller_unsafe_writeback_cache, }; } } ### NOTE: Sort '$b cmp $a' on the modified date. # Now, loop through each record from the unified table and see if it # needs to be added to any DBs. foreach my $modified_date (sort {$b cmp $a} keys %{$an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "modified_date", value1 => $modified_date, }, file => $THIS_FILE, line => __LINE__}); foreach my $hpacucli_controller_uuid (sort {$a cmp $b} keys %{$an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}}) { my $hpacucli_controller_serial_number = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_serial_number}; my $hpacucli_controller_model = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_model}; my $hpacucli_controller_status = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_status}; my $hpacucli_controller_last_diagnostics = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_last_diagnostics}; my $hpacucli_controller_cache_present = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_cache_present}; my $hpacucli_controller_drive_write_cache = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_drive_write_cache}; my $hpacucli_controller_firmware_version = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_firmware_version}; my $hpacucli_controller_unsafe_writeback_cache = $an->data->{db_data}{unified}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{hpacucli_controller_unsafe_writeback_cache}; $an->Log->entry({log_level => 3, message_key => "an_variables_0009", message_variables => { name1 => "hpacucli_controller_uuid", value1 => $hpacucli_controller_uuid, name2 => "hpacucli_controller_serial_number", value2 => $hpacucli_controller_serial_number, name3 => "hpacucli_controller_model", value3 => $hpacucli_controller_model, name4 => "hpacucli_controller_status", value4 => $hpacucli_controller_status, name5 => "hpacucli_controller_last_diagnostics", value5 => $hpacucli_controller_last_diagnostics, name6 => "hpacucli_controller_cache_present", value6 => $hpacucli_controller_cache_present, name7 => "hpacucli_controller_drive_write_cache", value7 => $hpacucli_controller_drive_write_cache, name8 => "hpacucli_controller_firmware_version", value8 => $hpacucli_controller_firmware_version, name9 => "hpacucli_controller_unsafe_writeback_cache", value9 => $hpacucli_controller_unsafe_writeback_cache, }, file => $THIS_FILE, line => __LINE__}); # We need to sanity check the three numeric strings because calling 'quote' directly # will wrap the numeric values in single quotes which violates 'numeric' forms. my $quoted_hpacucli_controller_last_diagnostics = $an->data->{sys}{use_db_fh}->quote($hpacucli_controller_last_diagnostics); $quoted_hpacucli_controller_last_diagnostics =~ s/^'(.*?)'$/$1/; if (($quoted_hpacucli_controller_last_diagnostics) && ($quoted_hpacucli_controller_last_diagnostics =~ /\D/)) { $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0006", message_variables => { last_diagnostics => $quoted_hpacucli_controller_last_diagnostics, }, code => 4, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 4}); } $quoted_hpacucli_controller_last_diagnostics = "NULL" if $quoted_hpacucli_controller_last_diagnostics eq ""; foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # For each 'hpacucli_controller_uuid' we see; # - Check if we've *seen* it before # |- If not; See if it *exists* in the public schema yet. # | |- If so, check to see if the entry in the public schema is up to date. # | | \- If not, _UPDATE_ public schema. # | \- If not, do an _INSERT_ into public schema. # \- If we have, see if it exists at the current timestamp. # \- If not, _INSERT_ it into history schema. # $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::seen", value1 => $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{seen}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{seen}) { # Mark this record as now having been seen. $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{seen} = 1; # Never seen it. Check if it exists. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_controllers::hpacucli_controller_uuid::${hpacucli_controller_uuid}::exists", value1 => $an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{'exists'}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{db_data}{$id}{hpacucli_controllers}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}{'exists'}) { # It exists, but does it exist at this time stamp? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "db_data::${id}::hpacucli_controllers::modified_date::${modified_date}::hpacucli_controller_uuid::${hpacucli_controller_uuid}", value1 => $an->data->{db_data}{$id}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{db_data}{$id}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}) { # No, so UPDATE it. my $query = " UPDATE public.hpacucli_controllers SET hpacucli_controller_serial_number = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_serial_number).", hpacucli_controller_model = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_model).", hpacucli_controller_status = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_status).", hpacucli_controller_last_diagnostics = $quoted_hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_cache_present).", hpacucli_controller_drive_write_cache = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_drive_write_cache).", hpacucli_controller_firmware_version = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_firmware_version).", hpacucli_controller_unsafe_writeback_cache = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_unsafe_writeback_cache).", modified_date = ".$an->data->{sys}{use_db_fh}->quote($modified_date)." WHERE hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." AND hpacucli_controller_uuid = ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid)." ;"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # It doesn't exist, so INSERT it. my $query = " INSERT INTO public.hpacucli_controllers ( hpacucli_controller_host_uuid, hpacucli_controller_uuid, hpacucli_controller_serial_number, hpacucli_controller_model, hpacucli_controller_status, hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_model).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_status).", $quoted_hpacucli_controller_last_diagnostics, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_cache_present).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_drive_write_cache).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_firmware_version).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_unsafe_writeback_cache).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{public}{sql}}, $query; } } else { # We've seen this 'hpacucli_controller_uuid' before, so it is just a question # of whether the entry for the current timestamp exists in the # history schema. if (not $an->data->{db_data}{$id}{hpacucli_controllers}{modified_date}{$modified_date}{hpacucli_controller_uuid}{$hpacucli_controller_uuid}) { # It doesn't, INSERT it. my $query = " INSERT INTO history.hpacucli_controllers ( hpacucli_controller_host_uuid, hpacucli_controller_uuid, hpacucli_controller_serial_number, hpacucli_controller_model, hpacucli_controller_status, hpacucli_controller_last_diagnostics, hpacucli_controller_cache_present, hpacucli_controller_drive_write_cache, hpacucli_controller_firmware_version, hpacucli_controller_unsafe_writeback_cache, modified_date ) VALUES ( ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_uuid).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_serial_number).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_model).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_status).", $quoted_hpacucli_controller_last_diagnostics, ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_cache_present).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_drive_write_cache).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_firmware_version).", ".$an->data->{sys}{use_db_fh}->quote($hpacucli_controller_unsafe_writeback_cache).", ".$an->data->{sys}{use_db_fh}->quote($modified_date)." );"; # Now record the query in the array $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "id", value1 => $id, name2 => "query", value2 => $query }, file => $THIS_FILE, line => __LINE__}); push @{$an->data->{db_resync}{$id}{history}{sql}}, $query; } # Exist in history at timestamp? } # Seen hpacucli_controller_uuid? } # foreach my $id } # foreach my $hpacucli_controller_uuid ... } # foreach $modified_date ... # Free up memory by deleting the DB data from the main hash. delete $an->data->{db_data}; # Do the INSERTs now and then release the memory. foreach my $id (sort {$a cmp $b} keys %{$an->data->{dbh}}) { # Merge the queries with public schema queries being first. @{$an->data->{db_resync}{$id}{sql}} = (@{$an->data->{db_resync}{$id}{public}{sql}}, @{$an->data->{db_resync}{$id}{history}{sql}}); if (@{$an->data->{db_resync}{$id}{sql}} > 0) { $an->DB->do_db_write({id => $id, query => $an->data->{db_resync}{$id}{sql}, source => $THIS_FILE, line => __LINE__}); delete $an->data->{db_resync}{$id}{sql}; } } return(0); } # This will archive stuff in the 'history' schema, if needed. sub archive_if_needed { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "archive_if_needed" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # If the 'trigger' is '0', archiving is disabled. if (not $an->data->{scancore}{archive}{trigger}) { return(1); } ### NOTE: If a ScanCore db server was offline when an archive ran, when it returns, it's records will ### sync back, triggering a sooner-than-expected subsequent archive. This shouldn't happen ### often, and the complexity of tracking archive dates is such that we'll not try to account ### for these cases. ### TODO: What we can do later is, when we write the restore stuff, build in a dedupe function. ### Process: # 1. Count the records in history for each table, restricting the results to those from this host # (save for special tables like 'server') and if the number of records is greater than # 'scancore::archive::trigger', start an archive. # 2. Set/update the 'archive_date' state. # 3. Lock the database. # 4. Select 'modified_date' from history.foo, offset by # ('scancore::archive::trigger' - 'scancore::archive::count'). # 5. Make sure the 'scancore::archive::directory' exists, creating it if needed. # 6. Select all records older that the 'modified_date', write them to a file and then DELETE those # records from the database. # Update the archive path, if set by a user. Also verify that there are sane archive values. $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "path::scancore_archive", value1 => $an->data->{path}{scancore_archive}, name2 => "scancore::archive::directory", value2 => $an->data->{scancore}{archive}{directory}, name3 => "scancore::archive::trigger", value3 => $an->data->{scancore}{archive}{trigger}, name4 => "scancore::archive::count", value4 => $an->data->{scancore}{archive}{count}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{scancore}{archive}{directory} =~ /\/.*/) { $an->data->{path}{scancore_archive} = $an->data->{scancore}{archive}{directory}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "path::scancore_archive", value1 => $an->data->{path}{scancore_archive}, }, file => $THIS_FILE, line => __LINE__}); } if ((not $an->data->{scancore}{archive}{trigger}) or ($an->data->{scancore}{archive}{trigger} =~ /\D/)) { $an->data->{scancore}{archive}{trigger} = 100000; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "scancore::archive::trigger", value1 => $an->data->{scancore}{archive}{trigger}, }, file => $THIS_FILE, line => __LINE__}); } if ((not $an->data->{scancore}{archive}{count}) or ($an->data->{scancore}{archive}{count} =~ /\D/)) { $an->data->{scancore}{archive}{count} = 50000; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "scancore::archive::count", value1 => $an->data->{scancore}{archive}{count}, }, file => $THIS_FILE, line => __LINE__}); } if (not -e $an->data->{path}{scancore_archive}) { my $shell_call = $an->data->{path}{'mkdir'}." -p '".$an->data->{path}{scancore_archive}."'"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "shell_call", value1 => $shell_call, }, file => $THIS_FILE, line => __LINE__}); open (my $file_handle, "$shell_call 2>&1 |") or $an->Alert->error({title_key => "an_0003", message_key => "error_title_0014", message_variables => { shell_call => $shell_call, error => $! }, code => 2, file => $THIS_FILE, line => __LINE__}); while(<$file_handle>) { chomp; my $line = $_; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); } close $file_handle; # Did it work? if (not -e $an->data->{path}{scancore_archive}) { # Nope. :( $an->Alert->warning({message_key => "scancore_warning_0030", message_variables => { directory => $an->data->{path}{scancore_archive} }, quiet => 1, file => $THIS_FILE, line => __LINE__}); return(1); } } # All of the changes happen in the variables table. This is set up like ScanCore and other agents in # case we find it necessary to add additional tables later. $an->data->{archive}{table} = { hpacucli_controllers => { archive_date => "", host_column => "hpacucli_controller_host_uuid", offset => 0, }, hpacucli_cache_modules => { archive_date => "", host_column => "hpacucli_cache_module_host_uuid", offset => 0, }, hpacucli_arrays => { archive_date => "", host_column => "hpacucli_array_host_uuid", offset => 0, }, hpacucli_logical_drives => { archive_date => "", host_column => "hpacucli_logical_drive_host_uuid", offset => 0, }, hpacucli_physical_drives => { archive_date => "", host_column => "hpacucli_physical_drive_host_uuid", offset => 0, }, hpacucli_variables => { archive_date => "", host_column => "hpacucli_variable_host_uuid", offset => 0, }, }; my $archive_needed = 0; foreach my $table (sort {$a cmp $b} keys %{$an->data->{archive}{table}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "table", value1 => $table, }, file => $THIS_FILE, line => __LINE__}); my $query = " SELECT COUNT(*) FROM history.$table WHERE ".$an->data->{archive}{table}{$table}{host_column}." = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid})." ;"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query, }, file => $THIS_FILE, line => __LINE__}); my $records = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $records = 0 if not defined $records; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "records", value1 => $records, }, file => $THIS_FILE, line => __LINE__}); if ($records > $an->data->{scancore}{archive}{trigger}) { $archive_needed = 1; my $records_to_save = ($an->data->{scancore}{archive}{trigger} - $an->data->{scancore}{archive}{count}); my $offset = $records - $records_to_save; $an->data->{archive}{table}{$table}{offset} = $offset; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "archive_needed", value1 => $archive_needed, name2 => "records_to_save", value2 => $records_to_save, name3 => "archive::table::${table}::offset", value3 => $an->data->{archive}{table}{$table}{offset}, }, file => $THIS_FILE, line => __LINE__}); } } # If I have something to archive, do so now. if ($archive_needed) { # This will store the files to compress after we release the locks. my $compress = []; # Request a lock. $an->DB->locking({request => 1}); # Now loop through the table(s) that need to be archived. foreach my $table (sort {$a cmp $b} keys %{$an->data->{archive}{table}}) { next if not $an->data->{archive}{table}{$table}{offset}; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "table", value1 => $table, }, file => $THIS_FILE, line => __LINE__}); # Now to do the archive. if ($table eq "hpacucli_controllers") { ### NOTE: Not tested yet $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_controller_uuid", "hpacucli_controller_host_uuid", "hpacucli_controller_serial_number", "hpacucli_controller_model", "hpacucli_controller_status", "hpacucli_controller_last_diagnostics", "hpacucli_controller_cache_present", "hpacucli_controller_drive_write_cache", "hpacucli_controller_firmware_version", "hpacucli_controller_unsafe_writeback_cache"], }); } elsif ($table eq "hpacucli_cache_modules") { ### NOTE: Not tested yet $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_cache_module_uuid", "hpacucli_cache_module_host_uuid", "hpacucli_cache_module_controller_uuid", "hpacucli_cache_module_serial_number", "hpacucli_cache_module_status", "hpacucli_cache_module_type", "hpacucli_cache_module_size"], }); } elsif ($table eq "hpacucli_arrays") { $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_array_uuid", "hpacucli_array_host_uuid", "hpacucli_array_controller_uuid", "hpacucli_array_name", "hpacucli_array_type", "hpacucli_array_status", "hpacucli_array_error_message"], }); } elsif ($table eq "hpacucli_physical_drives") { $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_physical_drive_uuid", "hpacucli_physical_drive_host_uuid", "hpacucli_physical_drive_logical_drive_uuid", "hpacucli_physical_drive_serial_number", "hpacucli_physical_drive_model", "hpacucli_physical_drive_interface", "hpacucli_physical_drive_status", "hpacucli_physical_drive_size", "hpacucli_physical_drive_type", "hpacucli_physical_drive_rpm", "hpacucli_physical_drive_temperature", "hpacucli_physical_drive_last_failure_reason", "hpacucli_physical_drive_port", "hpacucli_physical_drive_box", "hpacucli_physical_drive_bay"], }); } elsif ($table eq "hpacucli_variables") { $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_variable_uuid", "hpacucli_variable_host_uuid", "hpacucli_variable_source_table", "hpacucli_variable_source_uuid", "hpacucli_variable_is_temperature", "hpacucli_variable_name", "hpacucli_variable_value"], }); } elsif ($table eq "hpacucli_logical_drives") { ### NOTE: Not tested yet $an->DB->archive_table({ table => $table, offset => $an->data->{archive}{table}{$table}{offset}, conditionals => { $an->data->{archive}{table}{$table}{host_column} => $an->data->{sys}{host_uuid} }, columns => ["hpacucli_logical_drive_uuid", "hpacucli_logical_drive_host_uuid", "hpacucli_logical_drive_array_uuid", "hpacucli_logical_drive_name", "hpacucli_logical_drive_caching", "hpacucli_logical_drive_os_device_name", "hpacucli_logical_drive_type", "hpacucli_logical_drive_raid_level", "hpacucli_logical_drive_size", "hpacucli_logical_drive_strip_size", "hpacucli_logical_drive_stripe_size", "hpacucli_logical_drive_status"], }); } } ### TODO: Make this less of a hackish mc-hackington... # VACUUM FULL, if the database is on this machine. I need to do this from the command line # because the user we connect as isn't allowed to do it. We'll also only vacuum our DB. my $db_name = ""; foreach my $id (sort {$a cmp $b} keys %{$an->data->{scancore}{db}}) { $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "id", value1 => $id, name2 => "scancore::db::${id}::host", value2 => $an->data->{scancore}{db}{$id}{host}, name3 => "hostname", value3 => $an->hostname, name4 => "short_hostname", value4 => $an->short_hostname, }, file => $THIS_FILE, line => __LINE__}); if (($an->data->{scancore}{db}{$id}{host} eq $an->hostname) or ($an->data->{scancore}{db}{$id}{host} eq $an->short_hostname)) { $db_name = $an->data->{scancore}{db}{$id}{name}; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "db_name", value1 => $db_name, name2 => "scancore::db::${id}::name", value2 => $an->data->{scancore}{db}{$id}{name}, }, file => $THIS_FILE, line => __LINE__}); last; } } if ($db_name) { my $start = time; my $shell_call = $an->data->{path}{su}." - postgres -c \"".$an->data->{path}{psql}." $db_name -c 'VACUUM FULL;'\""; $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "start", value1 => $start, name2 => "shell_call", value2 => $shell_call, }, file => $THIS_FILE, line => __LINE__}); open (my $file_handle, "$shell_call 2>&1 |") or $an->Alert->error({title_key => "an_0003", message_key => "error_title_0014", message_variables => { shell_call => $shell_call, error => $! }, code => 2, file => $THIS_FILE, line => __LINE__}); while(<$file_handle>) { chomp; my $line = $_; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); } close $file_handle; my $finished = time - $start; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "finished", value1 => $finished, }, file => $THIS_FILE, line => __LINE__}); } # Release the lock $an->DB->locking({release => 1}); } return(0); } # This gets the basic information about the controller. sub get_controller_info { my ($an, $controller) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "get_controller_info" }, message_key => "an_variables_0001", message_variables => { name1 => "controller", value1 => $controller, }, file => $THIS_FILE, line => __LINE__}); my $model_name = ""; my $hpacucli_controller_serial_number = ""; my $cache_serial_number = ""; my $hpacucli_physical_drive_serial_number = ""; my $hpacucli_array_name = ""; my $logical_drive = ""; my $port = ""; my $box = ""; my $bay = ""; my $in_array = 0; my $shell_call = $an->data->{path}{hpacucli}." controller slot=".$controller." show config detail"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "shell_call", value1 => $shell_call, }, file => $THIS_FILE, line => __LINE__}); open (my $file_handle, "$shell_call 2>&1 |") or $an->Alert->error({title_key => "an_0003", message_key => "error_title_0014", message_variables => { shell_call => $shell_call, error => $! }, code => 2, file => $THIS_FILE, line => __LINE__}); while(<$file_handle>) { chomp; my $line = $an->String->clean_spaces({string => $_}); $line =~ s/\r//; next if not $line; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); if ((not $hpacucli_controller_serial_number) && ($line =~ /^(.*?) in Slot $controller /)) { $model_name = $1; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "model_name", value1 => $model_name, }, file => $THIS_FILE, line => __LINE__}); } if (($line =~ /^Serial Number: (.*?)$/) && (not $port) && (not $box) && (not $bay)) { $hpacucli_controller_serial_number = $1; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, }, file => $THIS_FILE, line => __LINE__}); # Record the model number if ($model_name) { $an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{model_name} = $model_name; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::data::detail::model_name", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{model_name}, }, file => $THIS_FILE, line => __LINE__}); } # Make a reference between the slot and SN $an->data->{controller}{metadata}{sn_to_slot}{$hpacucli_controller_serial_number} = $controller; $an->data->{controller}{metadata}{slot_to_sn}{$controller} = $hpacucli_controller_serial_number; $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "controller::metadata::sn_to_slot::${hpacucli_controller_serial_number}", value1 => $an->data->{controller}{metadata}{sn_to_slot}{$hpacucli_controller_serial_number}, name2 => "controller::metadata::slot_to_sn::${controller}", value2 => $an->data->{controller}{metadata}{slot_to_sn}{$controller}, }, file => $THIS_FILE, line => __LINE__}); next; } next if not $hpacucli_controller_serial_number; if ($line =~ /Cache Serial Number: (.*?)$/i) { $an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{cache_serial_number} = $1; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::data::detail::cache_serial_number", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{data}{detail}{cache_serial_number}, }, file => $THIS_FILE, line => __LINE__}); next; } if ($line =~ /Array: (.*?)$/i) { $hpacucli_array_name = $1; $in_array = 1; $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "hpacucli_array_name", value1 => $hpacucli_array_name, name2 => "in_array", value2 => $in_array, }, file => $THIS_FILE, line => __LINE__}); next; } if ($line =~ /Logical Drive: (.*?)$/i) { $logical_drive = $1; $in_array = 0; $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "logical_drive", value1 => $logical_drive, name2 => "in_array", value2 => $in_array, }, file => $THIS_FILE, line => __LINE__}); next; } if ($line =~ /physicaldrive (.*?):(.*?):(.*)$/) { $port = $1; $box = $2; $bay = $3; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "port", value1 => $port, name2 => "box", value2 => $box, name3 => "bay", value3 => $bay, }, file => $THIS_FILE, line => __LINE__}); next; } elsif (($port) && (($line eq "Drive Type: Data") or ($line =~ /^Mirror Group \d+:$/))) { $port = ""; $box = ""; $bay = ""; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "port", value1 => $port, name2 => "box", value2 => $box, name3 => "bay", value3 => $bay, }, file => $THIS_FILE, line => __LINE__}); } if (lc($line) eq "unassigned") { $hpacucli_array_name = "ZZZZ"; $logical_drive = "9999"; $port = ""; $box = ""; $bay = ""; $an->Log->entry({log_level => 2, message_key => "an_variables_0005", message_variables => { name1 => "hpacucli_array_name", value1 => $hpacucli_array_name, name2 => "logical_drive", value2 => $logical_drive, name3 => "port", value3 => $port, name4 => "box", value4 => $box, name5 => "bay", value5 => $bay, }, file => $THIS_FILE, line => __LINE__}); next; } # Lines I don't care about next if $line =~ /^Slot: $controller$/i; my $type = "detail"; if ($line =~ /^(.*?): (.*)$/) { my $variable = $1; my $value = $2; $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "variable", value1 => $variable, name2 => "value", value2 => $value, }, file => $THIS_FILE, line => __LINE__}); # If the variable has units, pull them out. if ($variable =~ / \(C\)$/i) { $variable =~ s/ \(C\)$//i; $variable = $an->String->clean_spaces({string => $variable}); $type = "temperature"; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "variable", value1 => $variable, name2 => "value", value2 => $value, name3 => "type", value3 => $type, }, file => $THIS_FILE, line => __LINE__}); } elsif ($variable =~ / \(F\)/i) { # Covert to °C $variable =~ s/ \(F\)$//i; $variable = $an->String->clean_spaces({string => $variable}); $value = $an->Convert->convert_to_celsius({temperature => $value}); $type = "temperature"; $an->Log->entry({log_level => 2, message_key => "an_variables_0003", message_variables => { name1 => "variable", value1 => $variable, name2 => "value", value2 => $value, name3 => "type", value3 => $type, }, file => $THIS_FILE, line => __LINE__}); } elsif (($value =~ /^\d+ \wB$/) or ($value =~ /^\d+\.\d+ \wB$/)) { $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "variable", value1 => $variable, name2 => ">> value", value2 => $value, }, file => $THIS_FILE, line => __LINE__}); if (($variable eq "Total Cache Size") or ($variable eq "Total Cache Memory Available") or ($variable eq "Strip Size") or ($variable eq "Size") or ($variable eq "Full Stripe Size")) { # HP reports in MB, etc, but means MiB. $value = $an->Readable->hr_to_bytes({size => $value, base2 => 1}); $an->Log->entry({log_level => 2, message_key => "an_variables_0002", message_variables => { name1 => "variable", value1 => $variable, name2 => "<< value", value2 => $value, }, file => $THIS_FILE, line => __LINE__}); } } # Save it. if (exists $an->data->{controller}{$hpacucli_controller_serial_number}{$type}{$variable}) { # Conflict! This is a dirty way to keep them separate $variable .= " 2"; } $variable = process_variable_name($an, $variable); # What am I saving? if (($port) && ($box) && ($bay)) { $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); # Physical drive info $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{$type}{$variable} = $value; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::array::${hpacucli_array_name}::logical_drive::${logical_drive}::physical_drive::port::${port}::box::${box}::bay::${bay}::${type}::$variable", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{physical_drive}{port}{$port}{box}{$box}{bay}{$bay}{$type}{$variable}, }, file => $THIS_FILE, line => __LINE__}); # Map the SN to it's current location. if ($line =~ /Serial Number: (.*?)$/) { $hpacucli_physical_drive_serial_number = $1; my $location = $port.":".$box.":".$bay; $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number} = { array => $hpacucli_array_name, logical_drive => $logical_drive, port => $port, box => $box, bay => $bay, }; $an->data->{physical_drive}{by_location}{$location} = $hpacucli_physical_drive_serial_number; $an->Log->entry({log_level => 2, message_key => "an_variables_0006", message_variables => { name1 => "physical_drive::by_serial_number::${hpacucli_physical_drive_serial_number}::array", value1 => $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number}{array}, name2 => "physical_drive::by_serial_number::${hpacucli_physical_drive_serial_number}::logical_drive", value2 => $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number}{logical_drive}, name3 => "physical_drive::by_serial_number::${hpacucli_physical_drive_serial_number}::port", value3 => $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number}{port}, name4 => "physical_drive::by_serial_number::${hpacucli_physical_drive_serial_number}::box", value4 => $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number}{box}, name5 => "physical_drive::by_serial_number::${hpacucli_physical_drive_serial_number}::bay", value5 => $an->data->{physical_drive}{by_serial_number}{$hpacucli_physical_drive_serial_number}{bay}, name6 => "physical_drive::by_location::$location", value6 => $an->data->{physical_drive}{by_location}{$location}, }, file => $THIS_FILE, line => __LINE__}); } } elsif ($logical_drive) { # Logical drive $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{data}{$type}{$variable} = $value; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::array::${hpacucli_array_name}::logical_drive::${logical_drive}::data::${type}::$variable", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{logical_drive}{$logical_drive}{data}{$type}{$variable}, }, file => $THIS_FILE, line => __LINE__}); } elsif ($hpacucli_array_name) { # Array $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{$type}{$variable} = $value; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::array::${hpacucli_array_name}::data::${type}::$variable", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{$type}{$variable}, }, file => $THIS_FILE, line => __LINE__}); } else { # Controller data $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable} = $value; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::data::${type}::$variable", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{data}{$type}{$variable}, }, file => $THIS_FILE, line => __LINE__}); } } elsif ($in_array) { # Messages about a degraded array can be here. # ie: "One of the drives on this array have failed or has been removed." if ($line =~ /this array have failed/) { # We'll concatonate in case there are multiple errors. if (not exists $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message}) { $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message} = ""; } $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message} .= $line."\n"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::array::${hpacucli_array_name}::data::detail::error_message", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{array}{$hpacucli_array_name}{data}{detail}{error_message}, }, file => $THIS_FILE, line => __LINE__}); } } } close $file_handle; # If I didn't find a serial number, something went wrong. if (not $hpacucli_controller_serial_number) { # Error out. $an->Alert->error({title_key => "an_0003", message_key => "scan_hpacucli_error_0004", message_variables => { controller => $controller }, code => 6, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 6}); } $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, }, file => $THIS_FILE, line => __LINE__}); return($hpacucli_controller_serial_number); } # This will do a details diagnostics check, if enough time has passed. sub get_diagnostics { my ($an, $controller) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "get_diagnostics" }, message_key => "an_variables_0001", message_variables => { name1 => "controller", value1 => $controller, }, file => $THIS_FILE, line => __LINE__}); # Every 'scan-hpacucli::diagnostics_interval' seconds, run a full diagnostics to check for drives in # pre-failure. $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sys::process_diagnostics", value1 => $an->data->{sys}{process_diagnostics}, }, file => $THIS_FILE, line => __LINE__}); if (not $an->data->{sys}{process_diagnostics}) { # Is it time? my $query = "SELECT hpacucli_controller_last_diagnostics FROM hpacucli_controllers WHERE hpacucli_controller_host_uuid = ".$an->data->{sys}{use_db_fh}->quote($an->data->{sys}{host_uuid}).";"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "query", value1 => $query }, file => $THIS_FILE, line => __LINE__}); # The actual query -----------------. .------- Row 0 # Query this DB --. | | .-- Columns 0 my $last_diagnostics = $an->DB->do_db_query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $last_diagnostics = 0 if not defined $last_diagnostics; my $current_time = time; my $last_scan_was = $current_time - $last_diagnostics; $an->Log->entry({log_level => 3, message_key => "an_variables_0004", message_variables => { name1 => "last_diagnostics", value1 => $last_diagnostics, name2 => "current_time", value2 => $current_time, name3 => "last_scan_was", value3 => $last_scan_was, name4 => "scan-hpacucli::diagnostics_interval", value4 => $an->data->{'scan-hpacucli'}{diagnostics_interval}, }, file => $THIS_FILE, line => __LINE__}); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "scan-hpacucli::diagnostics_interval", value1 => $last_diagnostics, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{'scan-hpacucli'}{diagnostics_interval} !~ /^\d+$/) { # Invalid value, override. $an->data->{'scan-hpacucli'}{diagnostics_interval} = 1800; $an->Log->entry({log_level => 1, message_key => "an_variables_0001", message_variables => { name1 => "scan-hpacucli::diagnostics_interval", value1 => $an->data->{'scan-hpacucli'}{diagnostics_interval}, }, file => $THIS_FILE, line => __LINE__}); } if ($last_scan_was > $an->data->{'scan-hpacucli'}{diagnostics_interval}) { $an->data->{sys}{process_diagnostics} = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sys::process_diagnostics", value1 => $an->data->{sys}{process_diagnostics}, }, file => $THIS_FILE, line => __LINE__}); } } # Well, is it? $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "sys::process_diagnostics", value1 => $an->data->{sys}{process_diagnostics}, }, file => $THIS_FILE, line => __LINE__}); if ($an->data->{sys}{process_diagnostics}) { # Yup! We use hpacucli's diagnostics to gather all data. my $shell_call = " cd /tmp/ ".$an->data->{path}{hpacucli}." controller slot=$controller diag file=/tmp/ADUReport.zip ".$an->data->{path}{'unzip'}." -o /tmp/ADUReport.zip -d /tmp/ if [ -e '/tmp/ADUReport.xml' ]; then ".$an->data->{path}{rm}." -f /tmp/ADUReport.zip ".$an->data->{path}{rm}." -f /tmp/ADUReport.htm ".$an->data->{path}{rm}." -f /tmp/ADUReport.xml ".$an->data->{path}{rm}." -f /tmp/report.checksum fi "; # Write a log message to warn the user that we're starting a long process. $an->Log->entry({log_level => 1, message_key => "scan_hpacucli_log_0003", message_variables => { shell_call => $shell_call }, file => $THIS_FILE, line => __LINE__}); open (my $file_handle, "$shell_call 2>&1 |") or $an->Alert->error({title_key => "an_0003", message_key => "error_title_0014", message_variables => { shell_call => $shell_call, error => $! }, code => 2, file => $THIS_FILE, line => __LINE__}); while(<$file_handle>) { chomp; my $line = $_; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); } close $file_handle; # Did it work? if (not -r "/tmp/ADUReport.txt") { # Something went wrong. print $an->String->get({key => "scan_hpacucli_error_0005", variables => { path => "/tmp/ADUReport.txt" }})."\n"; $an->Log->entry({log_level => 0, message_key => "scan_hpacucli_error_0005", message_variables => { file => "/tmp/ADUReport.txt" }, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 4}); } # Get this controller's serial number my $hpacucli_controller_serial_number = $an->data->{controller}{metadata}{slot_to_sn}{$controller}; # Parse! my $in_cache_config_status = 0; my $in_physical_drive = 0; my $hpacucli_physical_drive_serial_number = ""; my $port = ""; my $box = ""; my $bay = ""; my $skip_blank_line = 0; $shell_call = "/tmp/ADUReport.txt"; $an->Log->entry({log_level => 2, message_key => "an_variables_0001", message_variables => { name1 => "shell_call", value1 => $shell_call, }, file => $THIS_FILE, line => __LINE__}); open ($file_handle, "<$shell_call") or $an->Alert->error({title_key => "tools_title_0003", message_key => "error_message_0066", message_variables => { shell_call => $shell_call, error => $! }, code => 3, file => $THIS_FILE, line => __LINE__}); while (<$file_handle>) { chomp; my $line = $an->String->clean_spaces({string => $_}); if (not $line) { if ($skip_blank_line) { next; } $in_cache_config_status = 0; $in_physical_drive = 0; $hpacucli_physical_drive_serial_number = ""; $port = ""; $box = ""; $bay = ""; $an->Log->entry({log_level => 3, message_key => "an_variables_0006", message_variables => { name1 => "in_cache_config_status", value1 => $in_cache_config_status, name2 => "in_physical_drive", value2 => $in_physical_drive, name3 => "hpacucli_physical_drive_serial_number", value3 => $hpacucli_physical_drive_serial_number, name4 => "port", value4 => $port, name5 => "box", value5 => $box, name6 => "bay", value6 => $bay, }, file => $THIS_FILE, line => __LINE__}); next; } $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line }, file => $THIS_FILE, line => __LINE__}); $skip_blank_line = 0; if ($line =~ /: Cache Config Status$/i) { $in_cache_config_status = 1; $skip_blank_line = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "in_cache_config_status", value1 => $in_cache_config_status, }, file => $THIS_FILE, line => __LINE__}); next; } if ($line =~ /: Physical Drive \(.*?\) (.*?):(.*?):(.*?) : Monitor and Performance Statistics \(Since Factory\)/) { $port = $1; $box = $2; $bay = $3; $skip_blank_line = 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "port", value1 => $port, name2 => "box", value2 => $box, name3 => "bay", value3 => $bay, }, file => $THIS_FILE, line => __LINE__}); } if ($in_cache_config_status) { if ($line =~ /Parity Read Errors (\d+) \(/) { $an->data->{controller}{$hpacucli_controller_serial_number}{'diagnostics'}{cache}{parity_read_errors} = $1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::diagnostics::cache::parity_read_errors", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{'diagnostics'}{cache}{parity_read_errors}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Parity Write Errors (\d+) \(/) { $an->data->{controller}{$hpacucli_controller_serial_number}{'diagnostics'}{cache}{parity_write_errors} = $1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "controller::${hpacucli_controller_serial_number}::diagnostics::cache::parity_write_errors", value1 => $an->data->{controller}{$hpacucli_controller_serial_number}{'diagnostics'}{cache}{parity_write_errors}, }, file => $THIS_FILE, line => __LINE__}); } } if (($port) && ($box) && ($bay)) { my $location = $port.":".$box.":".$bay; $hpacucli_physical_drive_serial_number = $an->data->{physical_drive}{by_location}{$location}; if ($line =~ /Read Errors Hard (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_hard} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::read_errors_hard", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_hard}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Read Errors Retry Recovered (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_retry_recovered} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::read_errors_retry_recovered", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_retry_recovered}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Read Errors ECC Corrected (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_ecc_corrected} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::read_errors_ecc_corrected", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{read_errors_ecc_corrected}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Write Errors Hard (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_hard} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::write_errors_hard", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_hard}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Write Errors Retry Recovered (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_retry_recovered} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::write_errors_retry_recovered", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_retry_recovered}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Format Errors (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{format_errors} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::format_errors", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{format_errors}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Write Errors After Remap (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_after_remap} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::write_errors_after_remap", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{write_errors_after_remap}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Hardware Errors (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{hardware_errors} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::hardware_errors", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{hardware_errors}, }, file => $THIS_FILE, line => __LINE__}); } if ($line =~ /Predictive Failure Errors (0x.*?)$/) { my $hex = $1; $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{predictive_failure_errors} = $an->Convert->hex_to_decimal({hex => $hex}); $an->Log->entry({log_level => 3, message_key => "an_variables_0002", message_variables => { name1 => "hex", value1 => $hex, name2 => "physical_drive::${hpacucli_physical_drive_serial_number}::diagnostics::predictive_failure_errors", value2 => $an->data->{physical_drive}{$hpacucli_physical_drive_serial_number}{'diagnostics'}{predictive_failure_errors}, }, file => $THIS_FILE, line => __LINE__}); } } } close $file_handle; } return(0); } # This gathers the various data from the controller(s). sub gather_data { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "gather_data" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); ### TODO: This assumes the controllers go 0, 1, ... n. If this is wrong, we'll need to call ### 'hpacucli controller all show' and parse the output as our outer loop. # Loops through reach found controller. foreach my $count (1..$an->data->{sys}{controller_count}) { my $controller = $count - 1; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "controller", value1 => $controller, }, file => $THIS_FILE, line => __LINE__}); # Read in controller data. my $hpacucli_controller_serial_number = get_controller_info($an, $controller); $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "hpacucli_controller_serial_number", value1 => $hpacucli_controller_serial_number, }, file => $THIS_FILE, line => __LINE__}); get_diagnostics($an, $controller); } return(0); } # This processes variable names to flatten them and remove spaces and special characters. sub process_variable_name { my ($an, $variable) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "process_variable_name" }, message_key => "an_variables_0001", message_variables => { name1 => "variable", value1 => $variable, }, file => $THIS_FILE, line => __LINE__}); $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; $variable =~ s/_+/_/g; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "variable", value1 => $variable, }, file => $THIS_FILE, line => __LINE__}); return($variable); } # This does two things; It checks to see if hpacucli 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_hp_controllers { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "find_hp_controllers" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # This will keep track of how many controllers we find. my $controller_count = 0; # First, do we have hpacucli installed? if (not -e $an->data->{path}{hpacucli}) { # Nope, exit. print $an->String->get({key => "scan_hpacucli_error_0001", variables => { path => $an->data->{path}{hpacucli} }})."\n"; $an->Log->entry({log_level => 1, message_key => "scan_hpacucli_error_0001", message_variables => { path => $an->data->{path}{hpacucli} }, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 1}); } # Make sure it is executable if (not -x $an->data->{path}{hpacucli}) { print $an->String->get({key => "scan_hpacucli_error_0002", variables => { path => $an->data->{path}{hpacucli} }})."\n"; $an->Log->entry({log_level => 0, message_key => "scan_hpacucli_error_0002", message_variables => { path => $an->data->{path}{hpacucli} }, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 2}); } # Still alive? Good! Look for controllers now. my $shell_call = $an->data->{path}{hpacucli}." controller all show"; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "shell_call", value1 => $shell_call, }, file => $THIS_FILE, line => __LINE__}); open (my $file_handle, "$shell_call 2>&1 |") or $an->Alert->error({title_key => "an_0003", message_key => "error_title_0014", message_variables => { shell_call => $shell_call, error => $! }, code => 2, file => $THIS_FILE, line => __LINE__}); while(<$file_handle>) { chomp; my $line = $_; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "line", value1 => $line, }, file => $THIS_FILE, line => __LINE__}); if ($line =~ /.*? Slot (\d+) .*?\(sn: (.*?)\)/i) { my $controller_number = $1; my $controller_serial_number = $2; $controller_count++; $an->Log->entry({log_level => 3, message_key => "an_variables_0003", message_variables => { name1 => "controller_number", value1 => $controller_number, name2 => "controller_serial_number", value2 => $controller_serial_number, name3 => "controller_count", value3 => $controller_count, }, file => $THIS_FILE, line => __LINE__}); } } close $file_handle; # Have we any controllers? if ($controller_count > 0) { $an->data->{sys}{controller_count} = $controller_count; $an->Log->entry({log_level => 3, message_key => "scan_hpacucli_log_0001", message_variables => { count => $an->data->{sys}{controller_count}, }, file => $THIS_FILE, line => __LINE__}); } else { print $an->String->get({key => "scan_hpacucli_error_0003", variables => { path => $an->data->{path}{hpacucli} }})."\n"; $an->Log->entry({log_level => 1, message_key => "scan_hpacucli_error_0003", message_variables => { path => $an->data->{path}{hpacucli} }, file => $THIS_FILE, line => __LINE__}); $an->nice_exit({exit_code => 3}); } return(0); } # This checks to see if this agent's databases tables exist and, if not, load the schema. If the schema gets # loaded, we'll check other databases for older information and load it. sub prep_databases { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "prep_databases" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); # Loop through the databases... $an->Log->entry({log_level => 3, message_key => "scancore_log_0016", message_variables => { agent => $THIS_FILE }, file => $THIS_FILE, line => __LINE__}); foreach my $id (sort {$a cmp $b} keys %{$an->data->{scancore}{db}}) { my $query = "SELECT COUNT(*) FROM pg_catalog.pg_tables WHERE tablename='hpacucli_controllers' AND schemaname='public';"; # The actual query -----------------. .------- Row 0 # Query this DB --. | | .-- Columns 0 my $count = $an->DB->do_db_query({id => $id, query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $an->Log->entry({log_level => 3, message_key => "an_variables_0001", message_variables => { name1 => "count", value1 => $count }, file => $THIS_FILE, line => __LINE__}); # Did we find the table? if ($count < 1) { # Nope. Need to load the database schema. $an->Log->entry({log_level => 3, message_key => "scancore_log_0017", file => $THIS_FILE, line => __LINE__}); $an->DB->load_schema({id => $id, file => $an->data->{path}{sql}}); # Send an alert telling the user that we've initialized this database. $an->Alert->register_alert({ alert_level => "notice", alert_agent_name => $THIS_FILE, alert_title_key => "an_alert_title_0003", alert_message_key => "notice_message_0002", alert_message_variables => { name => $an->data->{scancore}{db}{$id}{name}, host => $an->data->{scancore}{db}{$id}{host}, agent => $THIS_FILE, }, }); } else { # Table exists, schema load is not needed. $an->Log->entry({log_level => 3, message_key => "scancore_log_0018", file => $THIS_FILE, line => __LINE__}); } } return(0); } # Print the usage information. sub print_usage { my ($an) = @_; $an->Log->entry({log_level => 3, title_key => "tools_log_0001", title_variables => { function => "print_usage" }, message_key => "tools_log_0002", file => $THIS_FILE, line => __LINE__}); print $an->String->get({key => "scan_hpacucli_message_0002"})."\n"; return(0); }