Merge pull request #191 from ClusterLabs/anvil-tools-dev

Anvil tools dev
main
Digimer 3 years ago committed by GitHub
commit e23e495151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Anvil/Tools/Database.pm
  2. 9
      Anvil/Tools/Network.pm
  3. 21
      notes
  4. 2
      ocf/alteeve/server
  5. 113
      scancore-agents/scan-apc-pdu/scan-apc-pdu
  6. 3
      scancore-agents/scan-apc-pdu/scan-apc-pdu.xml
  7. 167
      scancore-agents/scan-network/scan-network
  8. 2
      scancore-agents/scan-storcli/scan-storcli
  9. 2
      share/words.xml
  10. 16
      tools/anvil-daemon
  11. 63
      tools/anvil-update-states

@ -1332,7 +1332,7 @@ sub connect
# This method just returns if nothing is needed.
if (($local_host_type eq "striker") && ($check_if_configured) && ($< == 0) && ($> == 0))
{
$anvil->Database->configure_pgsql({debug => 2, uuid => $local_host_uuid});
$anvil->Database->configure_pgsql({debug => $debug, uuid => $local_host_uuid});
}
# Now setup or however-many connections

@ -2178,13 +2178,8 @@ then
elif [ -e "/proc/net/bonding/${IFACE}" ];
then
echo bond;
elif [ -e "/sys/class/net/${IFACE}/bonding_slave/perm_hwaddr" ];
then
echo -n mac:
cat /sys/class/net/${IFACE}/bonding_slave/perm_hwaddr;
else
echo -n mac:
cat /sys/class/net/${IFACE}/address;
ethtool -P ${IFACE}
fi';
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }});
if ($is_local)
@ -2216,7 +2211,7 @@ fi';
foreach my $line (split/\n/, $output)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if ($line =~ /^mac:(.*)$/)
if ($line =~ /^.*: (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)$/)
{
my $real_mac = $1;
$anvil->data->{network}{$host}{interface}{$in_iface}{mac_address} = $real_mac;

21
notes

@ -1119,7 +1119,21 @@ The stack auto-forms.
console#configure terminal
console(config)#interface out-of-band
console(config-if)#ip address 10.201.1.1 255.255.0.0
console(config-if)#exit
console(config-if)#exit
# Connect the Management interface of the stack ID 1 switch to one of the BCN ports.
console#ping 10.201.4.1
Pinging 10.201.4.1 with 0 bytes of data:
Reply From 10.201.4.1: icmp_seq = 0. time= 640 usec.
Reply From 10.201.4.1: icmp_seq = 1. time= 558 usec.
Reply From 10.201.4.1: icmp_seq = 2. time= 224 usec.
Reply From 10.201.4.1: icmp_seq = 3. time= 192 usec.
----10.201.4.1 PING statistics----
4 packets transmitted, 4 packets received, 0% packet loss
round-trip (msec) min/avg/max = 0/0/0
# Set a web user and password (obviously, use a better password)
console(config)#no passwords min-length
@ -1202,14 +1216,14 @@ oob Out-Of-Band Up
# Configure VLANs
rs-striker03(config)#vlan 100
rs-striker03(config-vlan100)#name BCN1
rs-striker03(config-vlan100)#interface range gi1/0/1-12,gi2/0/1-12
rs-striker03(config-vlan100)#interface range gi1/0/1-14,gi2/0/1-14
rs-striker03(config-if)#switchport access vlan 100
rs-striker03(config-if)#no shutdown
rs-striker03(config-if)#exit
rs-striker03(config)#interface vlan 300
rs-striker03(config)#name IFN
rs-striker03(config-if-vlan300)#interface range gigabitethernet1/0/13-24,gigabitethernet2/0/13-24
rs-striker03(config-if-vlan300)#interface range gigabitethernet1/0/15-24,gigabitethernet2/0/15-24
rs-striker03(config-if)#switchport access vlan 300
rs-striker03(config-if)#no shutdown
rs-striker03(config-if)#exit
@ -1240,6 +1254,7 @@ rs-striker03#
# Firmware update
# Copy .stk file to striker's /var/lib/tftpboot/ directory
console#copy tftp://10.201.4.1/N2200v6.6.3.10.stk backup
====

@ -1265,7 +1265,7 @@ sub migrate_server
# for migration.
my $test_target = $target;
$test_target =~ s/\..*$//;
$test_target .= "mn1"; # Might want to make this a loop to support MN2+ later
$test_target .= ".mn1"; # Might want to make this a loop to support MN2+ later
my $test_ip = $anvil->Convert->host_name_to_ip({debug => 2, host_name => $test_target});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
test_target => $test_target,

@ -237,7 +237,7 @@ SELECT
FROM
scan_apc_pdus
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
@ -325,7 +325,7 @@ SELECT
FROM
scan_apc_pdu_phases
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
# Do the query against the source DB and loop through the results.
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
@ -378,7 +378,7 @@ SELECT
FROM
scan_apc_pdu_outlets
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
$count = @{$results};
@ -406,7 +406,7 @@ FROM
# Which serial number does this phase belong to?
my $scan_apc_pdu_serial_number = $anvil->data->{uuid_to_serial}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_serial_number => $scan_apc_pdu_serial_number }});
$anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_uuid} = $scan_apc_pdu_outlet_uuid;
$anvil->data->{sql}{scan_apc_pdu_uuid}{$scan_apc_pdu_outlet_scan_apc_pdu_uuid}{scan_apc_pdu_outlets}{$scan_apc_pdu_outlet_number}{scan_apc_pdu_outlet_scan_apc_pdu_uuid} = $scan_apc_pdu_outlet_scan_apc_pdu_uuid;
@ -434,7 +434,7 @@ SELECT
FROM
scan_apc_pdu_variables
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
$count = @{$results};
@ -2590,10 +2590,12 @@ FROM
fences
WHERE
fence_agent LIKE 'fence_apc_%'
AND
fence_arguments != 'DELETED'
ORDER BY
fence_name ASC
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
@ -2623,6 +2625,90 @@ ORDER BY
"fences::fence_uuid::${fence_uuid}::name" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{name},
"fences::fence_uuid::${fence_uuid}::ip_address" => $anvil->data->{fences}{fence_uuid}{$fence_uuid}{ip_address},
}});
# If there are two or more entries in scan_apc_pdu for this fence UUID, remove the extras.
my $query = "
SELECT
scan_apc_pdu_uuid,
scan_apc_pdu_model_number
FROM
scan_apc_pdus
WHERE
scan_apc_pdu_fence_uuid = ".$anvil->Database->quote($fence_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
results => $results,
count => $count,
}});
if ($count > 1)
{
# Duplicate! Is one of them marked as DELETED?
foreach my $row (@{$results})
{
# Is this one deleted?
my $scan_apc_pdu_uuid = $row->[0];
my $scan_apc_pdu_model_number = $row->[1];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
scan_apc_pdu_uuid => $scan_apc_pdu_uuid,
scan_apc_pdu_model_number => $scan_apc_pdu_model_number,
}});
if ($scan_apc_pdu_model_number eq "DELETED")
{
# Take this one out.
my $variables = {
name => $fence_name,
uuid => $scan_apc_pdu_uuid,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_log_0002", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_apc_pdu_log_0002",
variables => $variables,
set_by => $THIS_FILE,
sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++,
});
delete_pdu($anvil, $scan_apc_pdu_uuid);
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
# If count is still > 1, we need to arbitrarily delete an interface.
if ($count > 1)
{
foreach my $row (@{$results})
{
# Is this one deleted?
my $scan_apc_pdu_uuid = $row->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_pdu_uuid => $scan_apc_pdu_uuid }});
my $variables = {
name => $fence_name,
uuid => $scan_apc_pdu_uuid,
};
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_pdu_log_0002", variables => $variables});
$anvil->Alert->register({
alert_level => "notice",
message => "scan_apc_pdu_log_0002",
variables => $variables,
set_by => $THIS_FILE,
sort_position => $anvil->data->{'scan-apc-pdu'}{alert_sort}++,
});
delete_pdu($anvil, $scan_apc_pdu_uuid);
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
}
}
}
@ -2630,3 +2716,18 @@ ORDER BY
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { pdu_count => $pdu_count }});
return($pdu_count);
}
sub delete_pdu
{
my ($anvil, $scan_apc_pdu_uuid) = @_;
my $queries = [
"DELETE FROM scan_apc_pdu_variables WHERE scan_apc_pdu_variable_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";",
"DELETE FROM scan_apc_pdu_phases WHERE scan_apc_pdu_phase_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";",
"DELETE FROM scan_apc_pdu_outlets WHERE scan_apc_pdu_outlet_scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";",
"DELETE FROM scan_apc_pdus WHERE scan_apc_pdu_uuid = ".$anvil->Database->quote($scan_apc_pdu_uuid).";"
];
$anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__});
return(0);
}

@ -21,6 +21,7 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_apc_pdu_lo
<!-- Log entries -->
<key name="scan_apc_pdu_log_0001">Starting: [#!variable!program!#].</key>
<key name="scan_apc_pdu_log_0002">[ Note ] - The APC PDU associated with the fence device: [#!variable!name!#] with 'scan_apc_pdu_uuid': [#!variable!uuid!#] is a duplicate, removing it from the database(s).</key>
<!-- Message entries (usually meant to be alerts) -->
<key name="scan_apc_pdu_message_0001">No APC PDUs found as configured fence devices, nothing to do.</key>
@ -44,7 +45,7 @@ NOTE: All string keys MUST be prefixed with the agent name! ie: 'scan_apc_pdu_lo
<key name="scan_apc_pdu_message_0019">The PDU: [#!variable!name!#] appears to have rebooted. The uptime changed from; [#!variable!old_uptime!#] to: [#!variable!new_uptime!#]. Was the power restored after a power outage?</key>
<key name="scan_apc_pdu_message_0020">The wattage draw through the PDU: [#!variable!name!#] has changed from: [#!variable!old_total_wattage_draw!#] to: [#!variable!new_total_wattage_draw!#].</key>
<key name="scan_apc_pdu_message_0021">The phase number: [#!variable!phase!#] on the PDU: [#!variable!name!#] has returned.</key>
<key name="scan_apc_pdu_message_0022">The maximum amperage threshold on the phase: [#!variable!phase!#] of the PDU: [#!variable!name!#] has changed from: [#!variable!old_phase_max_amperage#] to: [#!variable!new_phase_max_amperage!#].</key>
<key name="scan_apc_pdu_message_0022">The maximum amperage threshold on the phase: [#!variable!phase!#] of the PDU: [#!variable!name!#] has changed from: [#!variable!old_phase_max_amperage!#] to: [#!variable!new_phase_max_amperage!#].</key>
<key name="scan_apc_pdu_message_0023">The amperage draw on phase: [#!variable!phase!#] of the PDU: [#!variable!name!#] has changed from: [#!variable!old_phase_current_amperage!#] to: [#!variable!new_phase_current_amperage!#].</key>
<key name="scan_apc_pdu_message_0024">The amperage drawing through the phase: [#!variable!phase!#] of the PDU: [#!variable!name!#] is below the low-warning threshold. This is not a concern for the Anvil!, but would only happen if a user configured a low draw alert. So this could be a concern to a user of this Anvil! system.</key>
<key name="scan_apc_pdu_message_0025">The amperage drawing through the phase: [#!variable!phase!#] of the PDU: [#!variable!name!#] has rised over the high critical alert threshold!</key>

@ -108,19 +108,19 @@ sub clear_old_variables
# Read in all interfaces and for each, delete historical records over the age-out time.
my $age = $anvil->data->{scancore}{database}{age_out};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }});
if ($age =~ /\D/)
{
# Age is not valid, set it to defaults.
$age = 24;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { age => $age }});
}
# Get the timestamp to delete thermal and power records older than $age hours.
my $query = "SELECT now() - '".$age."h'::interval;";
my $old_timestamp = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
query => $query,
old_timestamp => $old_timestamp,
}});
@ -128,7 +128,7 @@ sub clear_old_variables
# Read in all interface RX and TX variables.
foreach my $uuid (keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
uuid => $uuid,
db_host => $anvil->Get->host_name_from_uuid({host_uuid => $uuid}),
}});
@ -146,7 +146,7 @@ OR
;";
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
results => $results,
count => $count,
}});
@ -154,18 +154,18 @@ OR
{
my $variable_uuid = $row->[0];
my $variable_name = $row->[1];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
's1:variable_name' => $variable_name,
's2:variable_uuid' => $variable_uuid,
}});
# Find out of there are any records to remove at all.
my $query = "SELECT history_id FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date <= '".$old_timestamp."';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
results => $results,
count => $count,
}});
@ -174,11 +174,11 @@ OR
{
# Find how many records will be left. If it's 0, we'll use an OFFSET 1.
my $query = "SELECT history_id FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date > '".$old_timestamp."';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
my $results = $anvil->Database->query({uuid => $uuid, query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
results => $results,
count => $count,
}});
@ -186,7 +186,7 @@ OR
{
# At least one record will be left, we can do a simple delete.
my $query = "DELETE FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND modified_date <= '".$old_timestamp."';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
push @{$queries}, $query;
}
else
@ -195,10 +195,10 @@ OR
foreach my $row (@{$results})
{
my $history_id = $row->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { history_id => $history_id }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { history_id => $history_id }});
my $query = "DELETE FROM history.variables WHERE variable_uuid = ".$anvil->Database->quote($variable_uuid)." AND history_id = '".$history_id."';";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
push @{$queries}, $query;
}
}
@ -206,7 +206,7 @@ OR
}
my $commits = @{$queries};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { commits => $commits }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { commits => $commits }});
if ($commits)
{
# Commit the DELETEs.
@ -215,7 +215,7 @@ OR
records => $commits,
host => $anvil->Get->host_name_from_uuid({host_uuid => $uuid}),
}});
$anvil->Database->write({debug => 2, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__});
$anvil->Database->write({debug => 3, uuid => $uuid, query => $queries, source => $THIS_FILE, line => __LINE__});
undef $queries;
}
}
@ -469,8 +469,8 @@ sub collect_data
my $target = readlink($full_path."/master");
$bond_master = ($target =~ /^.*\/(.*)$/)[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
target => $target,
bond_master => $bond_master
target => $target,
bond_master => $bond_master,
}});
}
elsif (-d $full_path."/bridge")
@ -625,11 +625,6 @@ sub collect_data
"cache::new_file" => $anvil->data->{cache}{new_file},
}});
}
if (($interface =~ /^vnet/) && ($operational ne "up"))
{
#die;
}
}
}
closedir(DIRECTORY);
@ -785,7 +780,7 @@ sub read_last_scan
### NOTE: There is a bug somewhere where interfaces are periodically being added twice per host. This
### checks for / cleans those up. Remove this when the core issue is resolved.
clear_duplicate_nics($anvil);
clear_duplicates($anvil);
# Read in the old bridge data.
load_bridge_data($anvil);
@ -796,9 +791,9 @@ sub read_last_scan
return(0);
}
# There is a bug somewhere where interfaces are periodically being added twice per host. This checks
# for / cleans those up. Remove this when the core issue is resolved.
sub clear_duplicate_nics
# There is a bug somewhere where interfaces and ip addresses are periodically being added twice per host.
# This checks for / cleans those up. Remove this when the core issue is resolved.
sub clear_duplicates
{
my ($anvil) = @_;
@ -911,6 +906,107 @@ ORDER BY
delete $anvil->data->{duplicate_nics};
$query = "
SELECT
ip_address_uuid,
ip_address_address,
ip_address_note
FROM
ip_addresses
WHERE
ip_address_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)."
ORDER BY
ip_address_address ASC
;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { query => $query }});
$results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
$count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $ip_address_uuid = $row->[0];
my $ip_address_address = $row->[1];
my $ip_address_note = $row->[2];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
ip_address_uuid => $ip_address_uuid,
ip_address_address => $ip_address_address,
ip_address_note => $ip_address_note,
}});
if (not exists $anvil->data->{duplicate_ips}{seen}{$ip_address_address})
{
$anvil->data->{duplicate_ips}{seen}{$ip_address_address} = [];
}
push @{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}}, $ip_address_uuid;
$anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_address} = $ip_address_address;
$anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note} = $ip_address_note;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"duplicate_ips::ip_address_uuid::${ip_address_uuid}::ip_address_address" => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_address},
"duplicate_ips::ip_address_uuid::${ip_address_uuid}::ip_address_note" => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note},
}});
}
foreach my $ip_address_address (sort {$a cmp $b} keys %{$anvil->data->{duplicate_ips}{seen}})
{
my $count = @{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:ip_address_address' => $ip_address_address,
's2:count' => $count,
}});
if ($count > 1)
{
# Duplicate! Is one of them marked as DELETED?
foreach my $ip_address_uuid (@{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}})
{
# Is this one deleted?
my $ip_address_note = $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
ip_address_uuid => $ip_address_uuid,
ip_address_note => $anvil->data->{duplicate_ips}{ip_address_uuid}{$ip_address_uuid}{ip_address_note},
}});
if ($ip_address_note eq "DELETED")
{
# Take this one out.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0664", variables => {
ip => $ip_address_address,
uuid => $ip_address_uuid,
}});
my $query = "DELETE FROM ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
# If count is still > 1, we need to arbitrarily delete an interface.
if ($count > 1)
{
foreach my $ip_address_uuid (@{$anvil->data->{duplicate_ips}{seen}{$ip_address_address}})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0664", variables => {
ip => $ip_address_address,
uuid => $ip_address_uuid,
}});
my $query = "DELETE FROM ip_addresses WHERE ip_address_uuid = ".$anvil->Database->quote($ip_address_uuid).";";
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
$count--;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }});
}
last if $count == 1;
}
}
}
return(0);
}
@ -3313,7 +3409,18 @@ AND
### TODO: Don't set / clear interfaces that appear down but aren't named ifn/bcn/sn as they're probably unconfigured/unusued interfaces.
my $problem = 0;
if ((not $new_link_state) or ($new_operational eq "down") or ($new_duplex ne "full"))
my $check = 0;
if (($network_interface_name =~ /ifn/i) or
($network_interface_name =~ /sn/i) or
($network_interface_name =~ /bcn/i) or
($network_interface_name =~ /mn/i))
{
# One we monitor
$check = 1;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { check => $check }});
if (($check) && ((not $new_link_state) or ($new_operational eq "down") or ($new_duplex ne "full")))
{
$problem = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
@ -3325,14 +3432,14 @@ AND
}
else
{
# Has the interface been down for at least a minute?
my $age = $anvil->Alert->check_condition_age({
debug => 2,
name => $source_name,
host_uuid => $anvil->Get->host_uuid,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { age => $age }});
if ($age > 300)
if ($age > 60)
{
# New, save.
my ($health_uuid) = $anvil->Database->insert_or_update_health({
@ -3347,7 +3454,7 @@ AND
}
else
{
# Clear any old condition.
# Clear any old conditions.
my $age = $anvil->Alert->check_condition_age({
debug => 2,
clear => 1,

@ -317,7 +317,7 @@ sub pre_process_health
}});
my $value = $anvil->data->{controller}{serial_number}{$serial_number}{variable}{$variable};
if (($variable eq "alarm_state") && (lc($value) ne "missing") && (lc($value) ne "off"))
if (($variable eq "alarm_state") && (lc($value) ne "missing") && (lc($value) ne "off") && (lc($value) ne "absent"))
{
my $health_source_name = "controller:".$variable;
$anvil->data->{health}{new}{$health_source_name} = 1;

@ -2054,6 +2054,8 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0661">Our most recent database dump is newer than any from our peers. As such, we'll just start the database without a load.</key>
<key name="log_0662">Retrying to connect to the database.</key>
<key name="log_0663">The target can be reached on the dedicated migration network: [#!variable!target!#] via the IP address: [#!variable!ip!#], switching to use that for the RAM copy.</key>
<key name="log_0664">[ Note ] - The IP address: [#!variable!ip!#] with 'ip_address_uuid': [#!variable!uuid!#] is a duplicate, removing it from the database(s).</key>
<key name="log_0665">The database dump file: [#!variable!file!#] exists, skipping database setup.</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>

@ -1156,13 +1156,17 @@ sub prep_database
my ($anvil) = @_;
# If there's a backup file, we're configured and possibly just off.
my $dump_file = $anvil->data->{path}{directories}{pgsql}."/".$anvil->data->{sys}{database}{name}."_db_dump.".$anvil->Get->host_uuid().".out";
$dump_file =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { dump_file => $dump_file }});
if (-e $dump_file)
foreach my $uuid (keys %{$anvil->data->{database}})
{
# No need to prepare.
return(0);
my $dump_file = $anvil->data->{path}{directories}{pgsql}."/".$anvil->data->{sys}{database}{name}."_db_dump.".$uuid.".sql";
$dump_file =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dump_file => $dump_file }});
if (-e $dump_file)
{
# No need to prepare.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0665", variables => { file => $dump_file }});
return(0);
}
}
# Only run this if we're a dashboard.

@ -198,7 +198,6 @@ sub update_network
{
# Pull out the data I want. Note that some of these don't exist with virtio-net interfaces.
my $interface = $file;
my $mac_address = -e $full_path."/address" ? $anvil->Storage->read_file({file => $full_path."/address"}) : "";
my $link_state = -e $full_path."/carrier" ? $anvil->Storage->read_file({file => $full_path."/carrier"}) : 0;
my $mtu = -e $full_path."/mtu" ? $anvil->Storage->read_file({file => $full_path."/mtu"}) : 0;
my $duplex = -e $full_path."/duplex" ? $anvil->Storage->read_file({file => $full_path."/duplex"}) : "unknown"; # full or half?
@ -207,14 +206,7 @@ sub update_network
my $media = "unknown";
my $type = "interface";
# If the NIC is a bond member, the MAC address could be virtual.
if (-e $full_path."/bonding_slave/perm_hwaddr")
{
$mac_address = $anvil->Storage->read_file({file => $full_path."/bonding_slave/perm_hwaddr"});
}
# Clean up some newlines.
$mac_address =~ s/\n$//;
$link_state =~ s/\n$//;
$mtu =~ s/\n$//;
$duplex =~ s/\n$//;
@ -222,7 +214,6 @@ sub update_network
$speed =~ s/\n$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
interface => $interface,
mac_address => $mac_address,
link_state => $link_state,
mtu => $mtu,
duplex => $duplex,
@ -230,11 +221,35 @@ sub update_network
speed => $speed,
}});
# If this a vnet device, set 'operational' to 'up'.
if (($interface =~ /^vnet/) && ($operational ne "up"))
# The MAC address can faked by a number of ways, so we make an explicit call to 'ethtool' to get the permanent mac address.
my $mac_address = "";
my $shell_call = $anvil->data->{path}{exe}{ethtool}." -P ".$interface;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
return_code => $return_code,
}});
if ($output =~ /(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)$/)
{
$operational = "up";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { operational => $operational }});
$mac_address = lc($1);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
else
{
# Get it by reading the address file.
if (-e $full_path."/bonding_slave/perm_hwaddr")
{
$mac_address = $anvil->Storage->read_file({file => $full_path."/bonding_slave/perm_hwaddr"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
elsif (-e $full_path."/address")
{
$mac_address = $anvil->Storage->read_file({file => $full_path."/address"});
$mac_address =~ s/\n//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mac_address => $mac_address }});
}
}
# These are variables that will be needed if this is a bond interface.
@ -369,6 +384,17 @@ sub update_network
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { bridge_stp_enabled => $bridge_stp_enabled }});
}
# If this a vnet device, set 'operational' to 'up'.
if ($interface =~ /^vnet/)
{
$operational = "up";
$media = "virtual";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
operational => $operational,
media => $media,
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
active_interface => $active_interface,
bond_master => $bond_master,
@ -393,11 +419,16 @@ sub update_network
# If the MAC address starts with '52:54:00', we've got a virtio NIC.
if ((not defined $speed) or ($speed eq ""))
{
die $THIS_FILE." ".__LINE__."; No speed for: [".$full_path."/speed]\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0001", variables => { file => $full_path."/speed" }});
next;
}
if ($speed =~ /\D/)
{
die $THIS_FILE." ".__LINE__."; Speed: [$speed] isn't numeric for: [".$full_path."/speed]\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_network_error_0002", variables => {
file => $full_path."/speed",
speed => $speed,
}});
next;
}
if ($speed > 100000)
{
@ -408,7 +439,7 @@ sub update_network
}
# Find the media, if possible.
my ($ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ethtool}." $interface"});
(my $ethtool, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{ethtool}." $interface"});
foreach my $line (split/\n/, $ethtool)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }});

Loading…
Cancel
Save