From 4ecc6097d33092a627c0b1a559a9a8567a1b7634 Mon Sep 17 00:00:00 2001 From: Digimer Date: Fri, 12 Aug 2022 16:32:20 -0400 Subject: [PATCH] * Cleaned up some old 'die' calls with better nice_exit() calls to help avoid dangling db_in_use flags. * Reworked Network->bridge_info() to use 'ip' to get the list of bridges, and 'bridge' to find interfaces connected to the bridge. * Added 'test' messages to Words->string(). * Fixed a bug in scan-lvm where mdadm based PVs didn't read the sector size properly. Signed-off-by: Digimer --- Anvil/Tools.pm | 7 +- Anvil/Tools/Database.pm | 9 +- Anvil/Tools/Get.pm | 12 +- Anvil/Tools/Log.pm | 14 +- Anvil/Tools/Network.pm | 123 +++++++++++++++--- Anvil/Tools/Remote.pm | 9 +- Anvil/Tools/Words.pm | 63 +++++++-- scancore-agents/scan-drbd/scan-drbd | 12 +- scancore-agents/scan-drbd/scan-drbd.xml | 4 + scancore-agents/scan-ipmitool/scan-ipmitool | 13 +- .../scan-ipmitool/scan-ipmitool.xml | 3 + scancore-agents/scan-lvm/scan-lvm | 91 ++++++++++--- scancore-agents/scan-lvm/scan-lvm.xml | 3 + scancore-agents/scan-network/scan-network | 23 +--- scancore-agents/scan-network/scan-network.xml | 2 + tools/anvil-update-states | 14 -- 16 files changed, 298 insertions(+), 104 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index aecb7394..2335d59b 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -415,6 +415,7 @@ sub nice_exit $anvil->data->{HANDLE}{'log'}{main} = ""; } + #print "Exiting with RC: [".$exit_code."]\n"; exit($exit_code); } @@ -772,7 +773,11 @@ sub _get_hash_reference my $parameter = shift; my $anvil = $self; - die "$THIS_FILE ".__LINE__."; The hash key string: [".$parameter->{key}."] doesn't seem to be valid. It should be a string in the format 'foo::bar::baz'.\n" if $parameter->{key} !~ /::/; + if ($parameter->{key} !~ /::/) + { + print "$THIS_FILE ".__LINE__."; The hash key string: [".$parameter->{key}."] doesn't seem to be valid. It should be a string in the format 'foo::bar::baz'.\n"; + $anvil->nice_exit({exit_code => 1}); + } # Split up the keys. my $key = $parameter->{key} ? $parameter->{key} : ""; diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 35b9a8a0..ca529f15 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -1644,7 +1644,6 @@ sub connect query => $query, }}); $anvil->nice_exit({exit_code => 1}); - die; } # Check to see if the schema needs to be loaded. @@ -2711,7 +2710,7 @@ WHERE next if not exists $anvil->data->{files}{file_uuid}{$file_uuid}; my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_uuid => $file_uuid, file_name => $file_name, }}); @@ -2723,7 +2722,7 @@ WHERE $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_md5sum} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum}; $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_type} = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_name" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_name}, "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_directory" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_directory}, "anvils::anvil_uuid::${anvil_uuid}::file_uuid::${file_uuid}::file_size" => $anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}})." (".$anvil->Convert->add_commas({number => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_size}}).")", @@ -2733,7 +2732,7 @@ WHERE # Make it so that we can list the files by name. $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid} = $file_uuid; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "anvils::anvil_uuid::${anvil_uuid}::file_name::${file_name}::file_uuid" => $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_name}{$file_name}{file_uuid}, }}); } @@ -16447,7 +16446,6 @@ sub resync_databases { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0114", variables => { query => $query }}); $anvil->nice_exit({exit_code => 1}); - die; } # If we don't have a row uuid, something has also gone wrong... @@ -16458,7 +16456,6 @@ sub resync_databases query => $query, }}); $anvil->nice_exit({exit_code => 1}); - die; } # Record this in the unified and local hashes. diff --git a/Anvil/Tools/Get.pm b/Anvil/Tools/Get.pm index 6b56ef5d..e272bda2 100644 --- a/Anvil/Tools/Get.pm +++ b/Anvil/Tools/Get.pm @@ -791,11 +791,11 @@ sub bridges if (not $test) { # JSON parse failed. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "error_0140", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "error_0140", variables => { json => $output, error => $@, }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0519"}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0519"}); # NOTE: This is not design to be normally used. It was created as a stop-gap while waiting # for resolution on: https://bugzilla.redhat.com/show_bug.cgi?id=1868467 @@ -1027,7 +1027,7 @@ sub cgi if (not $cgi->upload('upload_file')) { # Empty file passed, looks like the user forgot to select a file to upload. - $anvil->Log->entry({log_level => 2, message_key => "log_0242", file => $THIS_FILE, line => __LINE__}); + $anvil->Log->entry({level => 2, message_key => "log_0242", file => $THIS_FILE, line => __LINE__}); } else { @@ -1183,11 +1183,13 @@ sub date_and_time # Are things sane? if ($use_time =~ /D/) { - die "Get->date_and_time() was called with 'use_time' set to: [$use_time]. Only a unix timestamp is allowed.\n"; + warn "Get->date_and_time() was called with 'use_time' set to: [$use_time]. Only a unix timestamp is allowed.\n"; + $anvil->nice_exit({exit_code => 1}); } if ($offset =~ /D/) { - die "Get->date_and_time() was called with 'offset' set to: [$offset]. Only real number is allowed.\n"; + warn "Get->date_and_time() was called with 'offset' set to: [$offset]. Only real number is allowed.\n"; + $anvil->nice_exit({exit_code => 1}); } # Do my initial calculation. diff --git a/Anvil/Tools/Log.pm b/Anvil/Tools/Log.pm index 088628d4..d93b6a22 100644 --- a/Anvil/Tools/Log.pm +++ b/Anvil/Tools/Log.pm @@ -481,7 +481,7 @@ sub entry my $shell_call = $log_file; print $THIS_FILE." ".__LINE__."; shell_call: [".$shell_call."]\n" if $test; # NOTE: Don't call '$anvil->Log->entry()' here, it will cause a loop! - open (my $file_handle, ">>", $shell_call) or die "Failed to open: [$shell_call] for writing. The error was: $!\n"; + open (my $file_handle, ">>", $shell_call) or die "Failed to open: [".$shell_call."] for writing. The error was: $!\n"; $file_handle->autoflush(1); $anvil->data->{HANDLE}{'log'}{main} = $file_handle; binmode($anvil->data->{HANDLE}{'log'}{main}, ':encoding(utf-8)'); @@ -494,7 +494,8 @@ sub entry if (not $anvil->data->{HANDLE}{'log'}{main}) { # NOTE: This can't be a normal error because we can't write to the logs. - die $THIS_FILE." ".__LINE__."; log main file handle doesn't exist, but it should by now.\n"; + print $THIS_FILE." ".__LINE__."; log main file handle doesn't exist, but it should by now.\n"; + exit 1; } # The handle has to be wrapped in a block to make 'print' happy as it doesn't like non-scalars for file handles @@ -533,7 +534,8 @@ sub entry if (not $anvil->data->{HANDLE}{'log'}{alert}) { # NOTE: This can't be a normal error because we can't write to the logs. - die $THIS_FILE." ".__LINE__."; log alert file handle doesn't exist, but it should by now.\n"; + print $THIS_FILE." ".__LINE__."; log alert file handle doesn't exist, but it should by now.\n"; + exit 1; } # The handle has to be wrapped in a block to make 'print' happy as it doesn't like non-scalars for file handles @@ -871,11 +873,13 @@ sub variables #die if $test; if (not defined $level) { - die $THIS_FILE." ".__LINE__."; Log->variables() called without 'level': [".$level."] defined from: [$source : $line]\n"; + warn $THIS_FILE." ".__LINE__."; Log->variables() called without 'level': [".$level."] defined from: [$source : $line]\n"; + $anvil->nice_exit({exit_code => 1}); } elsif (not defined $anvil->Log->level) { - die $THIS_FILE." ".__LINE__."; Log->variables() called without Log->level: [".$anvil->Log->level."] defined from: [$source : $line]\n"; + warn $THIS_FILE." ".__LINE__."; Log->variables() called without Log->level: [".$anvil->Log->level."] defined from: [$source : $line]\n"; + $anvil->nice_exit({exit_code => 1}); } print "level: [$level], logging: [".$anvil->Log->level."], secure: [$secure], logging secure: [".$anvil->Log->secure."]\n" if $test; if ($level > $anvil->Log->level) diff --git a/Anvil/Tools/Network.pm b/Anvil/Tools/Network.pm index 3307dfae..82fdd94d 100644 --- a/Anvil/Tools/Network.pm +++ b/Anvil/Tools/Network.pm @@ -159,8 +159,80 @@ sub bridge_info target => $target, }}); - my $shell_call = $anvil->data->{path}{exe}{bridge}." -json -pretty link show"; - my $output = ""; + my $host = $target ? $target : $anvil->Get->short_host_name(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host => $host }}); + + # First get the list of bridges. + my $shell_call = $anvil->data->{path}{exe}{ip}." link show type bridge"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my $output = ""; + if ($anvil->Network->is_local({host => $target})) + { + # Local call. + ($output, my $return_code) = $anvil->System->call({debug => $debug, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:output' => $output, + 's2:return_code' => $return_code, + }}); + } + else + { + # Remote call + ($output, my $error, my $return_code) = $anvil->Remote->call({ + debug => $debug, + shell_call => $shell_call, + target => $target, + user => $remote_user, + password => $password, + remote_user => $remote_user, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:output' => $output, + 's2:error' => $error, + 's3:return_code' => $return_code, + }}); + } + + # Find the bridge interfaces + my $bridge = ""; + foreach my $line (split/\n/, $output) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + + if ($line =~ /^\d+:\s+(.*?):/) + { + $bridge = $1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bridge => $bridge }}); + + $anvil->data->{bridge}{$host}{$bridge}{found} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "bridge::${host}::${bridge}::found" => $anvil->data->{bridge}{$host}{$bridge}{found}, + }}); + } + next if not $bridge; + + if ($line =~ /mtu (\d+) /) + { + $anvil->data->{bridge}{$host}{$bridge}{mtu} = $1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "bridge::${host}::${bridge}::mtu" => $anvil->data->{bridge}{$host}{$bridge}{mtu}, + }}); + } + if ($line =~ /link\/ether (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w) /) + { + $anvil->data->{bridge}{$host}{$bridge}{mac} = $1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "bridge::${host}::${bridge}::mac" => $anvil->data->{bridge}{$host}{$bridge}{mac}, + }}); + } + } + + # Now use bridge to find the interfaces connected to the bridges. + $shell_call = $anvil->data->{path}{exe}{bridge}." -json -pretty link show"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + $output = ""; if ($anvil->Network->is_local({host => $target})) { # Local call. @@ -201,33 +273,46 @@ sub bridge_info foreach my $hash_ref (@{$bridge_data}) { next if not defined $hash_ref->{master}; - my $bridge = $hash_ref->{master}; + my $master = $hash_ref->{master}; # This can be the bond name for bond members. my $interface = $hash_ref->{ifname}; - my $host = $target ? $target : $anvil->Get->short_host_name(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - 's1:bridge' => $bridge, + 's1:master' => $master, 's2:interface' => $interface, - 's3:host' => $host, }}); - if ((not exists $anvil->data->{bridge}{$host}{$bridge}) or (ref($anvil->data->{bridge}{$host}{$bridge}{interfaces}) ne "ARRAY")) - { - $anvil->data->{bridge}{$host}{$bridge}{interfaces} = []; - $anvil->data->{bridge}{$host}{$bridge}{found} = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - "bridge::${host}::${bridge}::interfaces" => $anvil->data->{bridge}{$host}{$bridge}{interfaces}, - "bridge::${host}::${bridge}::found" => $anvil->data->{bridge}{$host}{$bridge}{found}, - }}); - } - push @{$anvil->data->{bridge}{$host}{$bridge}{interfaces}}, $interface; + + # If the 'master' wasn't found in the call above, the 'master' is not a bridge. + next if not exists $anvil->data->{bridge}{$host}{$master}; + + # Record this interface as being connected to this bridge. + $anvil->data->{bridge}{$host}{$master}{interface}{$interface}{found} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "bridge::${host}::${master}::interface::${interface}::found" => $anvil->data->{bridge}{$host}{$master}{interface}{$interface}{found}, + }}); # Now store the rest of the data. foreach my $key (sort {$a cmp $b} keys %{$hash_ref}) { next if $key eq "master"; next if $key eq "ifname"; - $anvil->data->{bridge}{$host}{$bridge}{$interface}{$key} = $hash_ref->{$key}; + $anvil->data->{bridge}{$host}{$master}{interface}{$interface}{$key} = $hash_ref->{$key}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "bridge::${host}::${master}::interface::${interface}::${key}" => $anvil->data->{bridge}{$host}{$master}{interface}{$interface}{$key}, + }}); + } + } + + # Make it easy to find the bridge an interface is in. + delete $anvil->data->{interface_to_bridge} if exists $anvil->data->{interface_to_bridge}; + foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{bridge}{$host}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { bridge_name => $bridge_name }}); + foreach my $interface_name (sort {$a cmp $b} keys %{$anvil->data->{bridge}{$host}{$bridge_name}{interface}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { interface_name => $interface_name }}); + + $anvil->data->{interface_to_bridge}{$interface_name} = $bridge_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - "bridge::${host}::${bridge}::${interface}::${key}" => $anvil->data->{bridge}{$host}{$bridge}{$interface}{$key}, + "interface_to_bridge::${interface_name}" => $anvil->data->{interface_to_bridge}{$interface_name}, }}); } } @@ -1185,7 +1270,7 @@ sub find_matches source => $source, line => $line, }}); - die; + $anvil->nice_exit({exit_code => 1}); return(""); } } diff --git a/Anvil/Tools/Remote.pm b/Anvil/Tools/Remote.pm index 9e2ee521..aa9582b0 100644 --- a/Anvil/Tools/Remote.pm +++ b/Anvil/Tools/Remote.pm @@ -789,21 +789,24 @@ sub read_snmp_oid { # Um, what are we supposed to read? $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Remote->read_snmp_oid()", parameter => "oid" }}); - die; + $anvil->nice_exit({exit_code => 1}); + return("!!error!!"); } if (not $target) { # Who ya gonna call? No, seriously, I have no idea... $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Remote->read_snmp_oid()", parameter => "target" }}); - die; + $anvil->nice_exit({exit_code => 1}); + return("!!error!!"); } if (($mib) && (not -r $mib)) { # Bad MIB path $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0163", variables => { mib => $mib }}); - die; + $anvil->nice_exit({exit_code => 1}); + return("!!error!!"); } diff --git a/Anvil/Tools/Words.pm b/Anvil/Tools/Words.pm index 672ebd15..a038e879 100644 --- a/Anvil/Tools/Words.pm +++ b/Anvil/Tools/Words.pm @@ -579,7 +579,7 @@ sub parse_banged_string } print $THIS_FILE." ".__LINE__."; Failed to parse the pair from: [".$variable_string."]\n"; print $THIS_FILE." ".__LINE__."; Was parsing message: [".$message."] from key string: [".$key_string."]\n"; - die; + $anvil->nice_exit({exit_code => 1}); } my ($variable, $value) = ($pair =~ /^!!(.*?)!(.*?)!!$/); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { @@ -958,6 +958,7 @@ sub string # We've got a string and variables from the caller, so inject them as needed. my $loops = 0; my $limit = $anvil->data->{defaults}{limits}{string_loops} =~ /^\d+$/ ? $anvil->data->{defaults}{limits}{string_loops} : 1000; + print $THIS_FILE." ".__LINE__."; limit: [".$limit."]\n" if $test; # If the user didn't pass in any variables, then we're in trouble. if (($string =~ /#!variable!(.+?)!#/s) && ((not $variables) or (ref($variables) ne "HASH"))) @@ -966,17 +967,21 @@ sub string while ($string =~ /#!variable!(.+?)!#/s) { $string =~ s/#!variable!(.*?)!#/!!variable!$1!!/s; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; # Die if I've looped too many times. $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } } my $error = "[ Error ] - The method Words->string() was asked to process the string: [".$string."] which has insertion variables, but nothing was passed to the 'variables' parameter."; @@ -994,24 +999,29 @@ sub string # restore them once we're out of this loop. foreach my $check ($string =~ /#!([^\s]+?)!#/) { + print $THIS_FILE." ".__LINE__."; check: [".$check."]\n" if $test; if (($check !~ /^data/) && ($check !~ /^string/) && ($check !~ /^variable/)) { # Simply invert the '#!...!#' to '!#...#!'. $string =~ s/#!($check)!#/!#$1#!/g; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } # Die if I've looped too many times. $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language]. Is there a bad '#!!!# replacement key? Exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language]. Is there a bad '#!!!# replacement key? Exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } } @@ -1024,26 +1034,32 @@ sub string language => $language, file => $file, }); + print $THIS_FILE." ".__LINE__."; string: [".$string."], key: [".$key."], this_string: [".$this_string."]\n" if $test; if ($this_string eq "#!not_found!#") { # The key was bad... $string =~ s/#!string!$key!#/!!e[$key]!!/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } else { $string =~ s/#!string!$key!#/$this_string/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } # Die if I've looped too many times. $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } } @@ -1051,17 +1067,20 @@ sub string while ($string =~ /#!variable!(.+?)!#/s) { my $variable = $1; + print $THIS_FILE." ".__LINE__."; string: [".$string."], variable: [".$variable."]\n" if $test; # Sometimes, #!variable!*!# is used in explaining things to users. So we need # to escape it. It will be restored later in '_restore_protected()'. if ($variable eq "*") { $string =~ s/#!variable!\*!#/!#variable!*#!/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; next; } if ($variable eq "") { $string =~ s/#!variable!\*!#/!#variable!#!/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; next; } @@ -1070,24 +1089,29 @@ sub string # I can't expect there to always be a defined value in the variables # array at any given position so if it is blank qw blank the key. $string =~ s/#!variable!$variable!#//; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } else { my $value = $variables->{$variable}; chomp $value; $string =~ s/#!variable!$variable!#/$value/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } # Die if I've looped too many times. $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } } @@ -1095,61 +1119,77 @@ sub string while ($string =~ /#!data!(.+?)!#/) { my $id = $1; + print $THIS_FILE." ".__LINE__."; string: [".$string."], id: [".$id."]\n" if $test; if ($id =~ /::/) { # Multi-dimensional hash. + print $THIS_FILE." ".__LINE__."; multi-dimensional\n" if $test; my $value = $anvil->_get_hash_reference({ key => $id }); + print $THIS_FILE." ".__LINE__."; value: [".$value."]\n" if $test; if (not defined $value) { $string =~ s/#!data!$id!#/!!a[$id]!!/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } else { $string =~ s/#!data!$id!#/$value/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } } else { # One dimension + print $THIS_FILE." ".__LINE__."; one dimension\n" if $test; if (not defined $anvil->data->{$id}) { $string =~ s/#!data!$id!#/!!b[$id]!!/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } else { my $value = $anvil->data->{$id}; $string =~ s/#!data!$id!#/$value/; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; } } # Die if I've looped too many times. $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } } $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } # If there are no replacement keys left, exit the loop. + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; if ($string !~ /#!([^\s]+?)!#/) { $loop = 0; + print $THIS_FILE." ".__LINE__."; loop: [".$loop."]\n" if $test; } } @@ -1159,27 +1199,34 @@ sub string while ($loop) { $string =~ s/!#([^\s]+?)#!/#!$1!#/g; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; $loops++; + print $THIS_FILE." ".__LINE__."; loops: [".$loops."], limit: [".$limit."]\n" if $test; if ($loops > $limit) { # If we're in a web environment, print the HTML header. + print $THIS_FILE." ".__LINE__."; environment: [".$anvil->environment."]\n" if $test; if ($anvil->environment eq "html") { print "Content-type: text/html; charset=utf-8\n\n"; } - die "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + print "$THIS_FILE ".__LINE__."; Infinite loop detected while processing the string: [".$string."] from the key: [$key] in language: [$language], exiting.\n"; + $anvil->nice_exit({exit_code => 1}); } + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; if ($string !~ /!#[^\s]+?#!/) { $loop = 0; + print $THIS_FILE." ".__LINE__."; loop: [".$loop."]\n" if $test; } } } # In some multi-line strings, the last line will be '\t\t'. We clean this up. $string =~ s/\t\t$//; + print $THIS_FILE." ".__LINE__."; string: [".$string."]\n" if $test; #print $THIS_FILE." ".__LINE__."; [ Debug ] - string: [$string]\n"; return($string); diff --git a/scancore-agents/scan-drbd/scan-drbd b/scancore-agents/scan-drbd/scan-drbd index 060060f5..9776b3fc 100755 --- a/scancore-agents/scan-drbd/scan-drbd +++ b/scancore-agents/scan-drbd/scan-drbd @@ -336,7 +336,11 @@ sub process_resource "s5:new_scan_drbd_resource_xml" => $new_scan_drbd_resource_xml, }}); - die if not defined $old_scan_drbd_resource_xml; + if (not defined $old_scan_drbd_resource_xml) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_warning_0001"}); + $anvil->nice_exit({exit_code => 1}); + } my $update = 0; if ($scan_drbd_resource_name ne $old_scan_drbd_resource_name) @@ -759,7 +763,11 @@ WHERE scan_drbd_peer_scan_drbd_volume_uuid => $scan_drbd_peer_scan_drbd_volume_uuid, }}); - die if not $scan_drbd_peer_scan_drbd_volume_uuid; + if (not $scan_drbd_peer_scan_drbd_volume_uuid) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_drbd_warning_0002"}); + $anvil->nice_exit({exit_code => 1}); + } my $query = " INSERT INTO diff --git a/scancore-agents/scan-drbd/scan-drbd.xml b/scancore-agents/scan-drbd/scan-drbd.xml index c74aaa5c..f46d9b80 100644 --- a/scancore-agents/scan-drbd/scan-drbd.xml +++ b/scancore-agents/scan-drbd/scan-drbd.xml @@ -19,6 +19,10 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_server_log DRBD is not configured on this host, exiting. + + [ Warning ] - The variable 'old_scan_drbd_resource_xml' is undefined, which should never be the case. This is likely a program error. + [ Warning ] - The variable 'scan_drbd_peer_scan_drbd_volume_uuid' is empty, which should never be the case. This is likely a program error. + Starting The: [#!variable!program!#] DRBD resource agent. diff --git a/scancore-agents/scan-ipmitool/scan-ipmitool b/scancore-agents/scan-ipmitool/scan-ipmitool index 1b45e77d..8cb79f25 100755 --- a/scancore-agents/scan-ipmitool/scan-ipmitool +++ b/scancore-agents/scan-ipmitool/scan-ipmitool @@ -811,9 +811,16 @@ INSERT INTO next; } - ### TODO: Make this ia log entry - die "No IPMI units for sensor: [".$scan_ipmitool_sensor_name."]." if not $new_scan_ipmitool_sensor_units; - die "No IPMI value for sensor: [".$new_scan_ipmitool_value_sensor_value."]." if not $new_scan_ipmitool_value_sensor_value; + if (not $new_scan_ipmitool_sensor_units) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_ipmitool_warn_0001", variables => { sensor => $scan_ipmitool_sensor_name }}); + next; + } + if (not $new_scan_ipmitool_value_sensor_value) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_ipmitool_warn_0001", variables => { sensor => $new_scan_ipmitool_value_sensor_value }}); + next; + } # If the value is "" and it's a digit-based value, switch it to '0' if ((($new_scan_ipmitool_sensor_units eq "C") or ($new_scan_ipmitool_sensor_units eq "F") or ($new_scan_ipmitool_sensor_units eq "RPM")) && ($new_scan_ipmitool_value_sensor_value eq "")) diff --git a/scancore-agents/scan-ipmitool/scan-ipmitool.xml b/scancore-agents/scan-ipmitool/scan-ipmitool.xml index 9f512bdd..366da3ce 100644 --- a/scancore-agents/scan-ipmitool/scan-ipmitool.xml +++ b/scancore-agents/scan-ipmitool/scan-ipmitool.xml @@ -116,5 +116,8 @@ The new sensor: [#!variable!sensor_name!#] has been found on the machine: [#!var The sensor named: [#!variable!sensor_name!#] appears to have vanished, but this is the first scan that it vanished. This is generally harmless and just a sensor read issue. The sensor named: [#!variable!sensor_name!#] has returned. + + [ Warning ] - No IPMI units for sensor: [#!variable!sensor!#]. + diff --git a/scancore-agents/scan-lvm/scan-lvm b/scancore-agents/scan-lvm/scan-lvm index 9b41a252..8e17eb86 100755 --- a/scancore-agents/scan-lvm/scan-lvm +++ b/scancore-agents/scan-lvm/scan-lvm @@ -1088,14 +1088,27 @@ sub collect_pvs_data { my ($anvil) = @_; - my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{pvscan}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my $shell_call = $anvil->data->{path}{exe}{pvscan}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); - ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{pvs}." --noheadings --units b --reportformat json -o pv_uuid,pv_name,vg_name,pv_attr,pv_size,pv_free"}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); - my $json = JSON->new->allow_nonref; - my $pvs_data = $json->decode($output); + $shell_call = $anvil->data->{path}{exe}{pvs}." --noheadings --units b --reportformat json -o pv_uuid,pv_name,vg_name,pv_attr,pv_size,pv_free"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); + + ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); + + my $json = JSON->new->allow_nonref; + my $pvs_data = $json->decode($output); + my $default_sector_size = 512; foreach my $hash_ref (@{$pvs_data->{report}->[0]->{pv}}) { my $scan_lvm_pv_internal_uuid = $hash_ref->{pv_uuid}; @@ -1125,15 +1138,19 @@ sub collect_pvs_data my $sector_size = 0; until ($sector_size) { - chop $partition; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { partition => $partition }}); if (not $partition) { # Weird... Default to 512. - $sector_size = 512; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sector_size => $sector_size }}); - die; + $sector_size = $default_sector_size; + my $original_partition = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; + my $sector_path = $directory."/".$original_partition."/queue/hw_sector_size"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_warning_0001", variables => { + device => $original_partition, + sector_path => $sector_path, + sector_size => $sector_size, + }}); } my $sector_size_file = $directory."/".$partition."/queue/hw_sector_size"; @@ -1147,11 +1164,19 @@ sub collect_pvs_data if ((not $sector_size) or ($sector_size =~ /\D/)) { # Something went wrong, default to 512. - $sector_size = 512; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sector_size => $sector_size }}); - die; + $sector_size = $default_sector_size; + my $original_partition = $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{name}; + my $sector_path = $directory."/".$original_partition."/queue/hw_sector_size"; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_lvm_warning_0001", variables => { + device => $original_partition, + sector_path => $sector_path, + sector_size => $sector_size, + }}); } } + + # Take a number off and try again. + chop $partition; } $anvil->data->{lvm}{scan_lvm_pv_internal_uuid}{$scan_lvm_pv_internal_uuid}{sector_size} = $sector_size; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { @@ -1166,11 +1191,23 @@ sub collect_vgs_data { my ($anvil) = @_; - my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{vgscan}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my $shell_call = $anvil->data->{path}{exe}{vgscan}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); - ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{vgs}." --noheadings --units b --reportformat json -o vg_uuid,vg_name,vg_attr,vg_extent_size,vg_size,vg_free"}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); + + $shell_call = $anvil->data->{path}{exe}{vgs}." --noheadings --units b --reportformat json -o vg_uuid,vg_name,vg_attr,vg_extent_size,vg_size,vg_free"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); + + ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); my $json = JSON->new->allow_nonref; my $vgs_data = $json->decode($output); @@ -1198,11 +1235,23 @@ sub collect_lvs_data { my ($anvil) = @_; - my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{lvscan}}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my $shell_call = $anvil->data->{path}{exe}{lvscan}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); - ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $anvil->data->{path}{exe}{lvs}." --noheadings --units b --reportformat json -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,lv_path,devices"}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output, return_code => $return_code }}); + my ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); + + $shell_call = $anvil->data->{path}{exe}{lvs}." --noheadings --units b --reportformat json -o lv_name,vg_name,lv_attr,lv_size,lv_uuid,lv_path,devices"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); + + ($output, $return_code) = $anvil->System->call({timeout => 15, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + output => $output, + return_code => $return_code, + }}); my $json = JSON->new->allow_nonref; my $lvs_data = $json->decode($output); diff --git a/scancore-agents/scan-lvm/scan-lvm.xml b/scancore-agents/scan-lvm/scan-lvm.xml index eebdffae..9bb7cfea 100644 --- a/scancore-agents/scan-lvm/scan-lvm.xml +++ b/scancore-agents/scan-lvm/scan-lvm.xml @@ -223,6 +223,9 @@ The attribute bits are: Starting: [#!variable!program!#]. + + + [ Warning ] - Failed to find the sector size for: [#!variable!device!#] This should be in the path: [#!variable!sector_path!#]. Assuming the sector size of: [#!variable!sector_size!#], but this could be incorrect. diff --git a/scancore-agents/scan-network/scan-network b/scancore-agents/scan-network/scan-network index cac8ef99..adbce66d 100755 --- a/scancore-agents/scan-network/scan-network +++ b/scancore-agents/scan-network/scan-network @@ -931,22 +931,7 @@ sub collect_data closedir(DIRECTORY); # Find what interfaces are connected to which bridges - $anvil->Network->bridge_info({debug => 3}); - delete $anvil->data->{interface_to_bridge} if exists $anvil->data->{interface_to_bridge}; - foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{bridge}{$local_host}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { bridge_name => $bridge_name }}); - foreach my $interface_name (sort {$a cmp $b} @{$anvil->data->{bridge}{$local_host}{$bridge_name}{interfaces}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface_name => $interface_name }}); - - $anvil->data->{interface_to_bridge}{$interface_name} = $bridge_name; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - "interface_to_bridge::${interface_name}" => $anvil->data->{interface_to_bridge}{$interface_name}, - }}); - } - } - + $anvil->Network->bridge_info({debug => 2}); foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$local_host}{interface}}) { my $ip_address = $anvil->data->{network}{$local_host}{interface}{$interface}{ip}; @@ -4060,7 +4045,11 @@ sub check_bridges foreach my $bridge_uuid (keys %{$anvil->data->{old}{bridges}{bridge_uuid}}) { # Skip if already deleted. - die if not $bridge_uuid; + if (not $bridge_uuid) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_warning_0001"}); + $anvil->nice_exit({exit_code => 1}); + } my $bridge_name = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_name}; my $bridge_id = $anvil->data->{old}{bridges}{bridge_uuid}{$bridge_uuid}{bridge_id}; diff --git a/scancore-agents/scan-network/scan-network.xml b/scancore-agents/scan-network/scan-network.xml index c512841c..04908108 100644 --- a/scancore-agents/scan-network/scan-network.xml +++ b/scancore-agents/scan-network/scan-network.xml @@ -219,5 +219,7 @@ This mode is NOT supported by the Anvil! Intelligent Availability™ platform! The old bond: [#!variable!name!#] was marked as deleted more than: [#!variable!age!#] hours ago. Purging it from the database. The old bridge: [#!variable!name!#] was marked as deleted more than: [#!variable!age!#] hours ago. Purging it from the database. The old IP address: [#!variable!ip!#] was marked as deleted more than: [#!variable!age!#] hours ago. Purging it from the database. + + There was an empty bridge_uuid in the hash 'old::bridges::bridge_uuid' hash. This is a program error. diff --git a/tools/anvil-update-states b/tools/anvil-update-states index 7299aa38..85c55290 100755 --- a/tools/anvil-update-states +++ b/tools/anvil-update-states @@ -553,20 +553,6 @@ sub update_network # Find what interfaces are connected to which bridges $anvil->Network->bridge_info({debug => 2}); - delete $anvil->data->{interface_to_bridge} if exists $anvil->data->{interface_to_bridge}; - foreach my $bridge_name (sort {$a cmp $b} keys %{$anvil->data->{bridge}{$local_host}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { bridge_name => $bridge_name }}); - foreach my $interface_name (sort {$a cmp $b} @{$anvil->data->{bridge}{$local_host}{$bridge_name}{interfaces}}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { interface_name => $interface_name }}); - - $anvil->data->{interface_to_bridge}{$interface_name} = $bridge_name; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { - "interface_to_bridge::${interface_name}" => $anvil->data->{interface_to_bridge}{$interface_name}, - }}); - } - } # We need to record bridges first so we know their UUIDs when looking at bonds and interfaces that # might be connected to them. Then we need to look at bonds so that their UUIDs are available when