diff --git a/Anvil/Tools/Cluster.pm b/Anvil/Tools/Cluster.pm index 7db566f6..ba8d290d 100644 --- a/Anvil/Tools/Cluster.pm +++ b/Anvil/Tools/Cluster.pm @@ -6,9 +6,10 @@ package Anvil::Tools::Cluster; use strict; use warnings; use Data::Dumper; -use XML::Simple qw(:strict); -use XML::LibXML; use Scalar::Util qw(weaken isweak); +use String::ShellQuote; +use XML::LibXML; +use XML::Simple qw(:strict); our $VERSION = "3.0.0"; my $THIS_FILE = "Cluster.pm"; @@ -18,6 +19,7 @@ my $THIS_FILE = "Cluster.pm"; # assemble_storage_groups # boot_server # check_node_status +# check_stonith_config # delete_server # get_fence_methods # get_anvil_name @@ -193,7 +195,7 @@ sub add_server my $server_state = $anvil->data->{server}{location}{$server_name}{status}; my $server_host = $anvil->data->{server}{location}{$server_name}{host_name}; my $target_role = $server_state eq "running" ? "started" : "stopped"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_name => $host_name, server_state => $server_state, server_host => $server_host, @@ -208,7 +210,7 @@ sub add_server $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { resource_command => $resource_command }}); my ($output, $return_code) = $anvil->System->call({shell_call => $resource_command}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code, }}); @@ -229,7 +231,7 @@ sub add_server undef $output; undef $return_code; ($output, $return_code) = $anvil->System->call({shell_call => $constraint_command}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output, return_code => $return_code, }}); @@ -627,7 +629,7 @@ sub boot_server # Nothing to do. if ((not $node) or ($host eq $node)) { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0548", variables => { server => $server }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0548", variables => { server => $server }}); return(0); } else @@ -675,7 +677,7 @@ sub boot_server host_name => $host_name, }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0552", variables => { server => $server }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0552", variables => { server => $server }}); if ($status eq "running") { # It's up. @@ -747,6 +749,715 @@ sub check_node_status } +=head2 check_stonith_config + +This loads the running CIB and compares the fence (stonith) configuration against the records in the database. If a method needs to be updated, added or removed, this method will make those changes. As such, this method must be called on an active Anvil! node in order to work. + +This method will return C<< !!error!! >> if called on a node that is not in a cluster, or called on a machine that isn't a node. Otherwise it returns C<< 1 >> if something was changed, and returns C<< 0 >> if no changes were made. + +This method takes no parameters. + +=cut +sub check_stonith_config +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Cluster->check_stonith_config()" }}); + + # Are we a node? + my $host_type = $anvil->Get->host_type({debug => $debug}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_type => $host_type }}); + if ($host_type ne "node") + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0298", variables => { host_type => $host_type }}); + return('!!error!!'); + } + + # See if we already have a parsed CIB. Generally we're called by scan-cluster, so we should. + if (not exists $anvil->data->{cib}{parsed}) + { + my $problem = $anvil->Cluster->parse_cib({debug => $debug}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); + if (($problem) or (not $anvil->data->{cib}{parsed}{'local'}{ready})) + { + # We're not in a cluster or we're not ready + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0299"}); + return('!!error!!'); + } + } + + # Get the list of fence methods for my peer and I and make sure their configs are valid. + my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => $debug}); + my $anvil_name = $anvil->Get->anvil_name_from_uuid({debug => $debug, anvil_uuid => $anvil_uuid }); + my $local_node_name = $anvil->data->{cib}{parsed}{'local'}{name}; + my $local_host_uuid = $anvil->Get->host_uuid(); + my $peer_node_name = $anvil->data->{cib}{parsed}{peer}{name}; + my $peer_host_uuid = $anvil->data->{cib}{parsed}{peer}{host_uuid}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + anvil_uuid => $anvil_uuid, + anvil_name => $anvil_name, + local_node_name => $local_node_name, + local_host_uuid => $local_host_uuid, + peer_node_name => $peer_node_name, + peer_host_uuid => $peer_host_uuid, + }}); + + # Load host information so that we can check for IPMI configs, if needed. + $anvil->Database->get_hosts({debug => $debug}); + $anvil->Database->get_anvils({debug => $debug}); + $anvil->Database->get_manifests({debug => $debug}); + + # Parse the manifest for the Anvil! so that we know what fence methods should be used. + my $manifest_uuid = exists $anvil->data->{manifests}{manifest_name}{$anvil_name}{manifest_uuid} ? $anvil->data->{manifests}{manifest_name}{$anvil_name}{manifest_uuid} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { manifest_uuid => $manifest_uuid }}); + + # If we don't have a manifest_uuid, abort. + if (not $manifest_uuid) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0300", variables => { anvil_name => $anvil_name }}); + return('!!error!!'); + } + my $problem = $anvil->Striker->load_manifest({debug => $debug, manifest_uuid => $manifest_uuid}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); + if ($problem) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0301", variables => { manifest_uuid => $manifest_uuid }}); + return('!!error!!'); + } + + # If we have a local host_IPMI, test it. + my $check_ipmi_config = 1; + if ($anvil->data->{hosts}{host_uuid}{$local_host_uuid}{host_ipmi}) + { + my $shell_call = $anvil->data->{hosts}{host_uuid}{$local_host_uuid}{host_ipmi}." -o status"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, secure => 1}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + + if ($return_code eq "0") + { + # IPMI is fine. + $check_ipmi_config = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { check_ipmi_config => $check_ipmi_config }}); + } + + } + if ($check_ipmi_config) + { + # See if it needs to be configured or updated. + $anvil->System->configure_ipmi({debug => $debug, manifest_uuid => $manifest_uuid}); + } + + # now lets check the stonith config. + $anvil->Cluster->get_peers({debug => $debug}); + my $local_node_is = $anvil->data->{sys}{anvil}{i_am}; + my $peer_node_is = $anvil->data->{sys}{anvil}{peer_is}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + local_node_is => $local_node_is, + peer_node_is => $peer_node_is, + }}); + + # Collecting fence data is expensive, so lets only load if needed. + my $update_fence_data = 1; + if ((exists $anvil->data->{fence_data}{updated}) && ($anvil->data->{fence_data}{updated})) + { + my $age = time - $anvil->data->{fence_data}{updated}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { age => $age }}); + if ($age < 86400) + { + # Only refresh daily. + $update_fence_data = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { update_fence_data => $update_fence_data }}); + } + } + if ($update_fence_data) + { + $anvil->Striker->get_fence_data({debug => ($debug + 1)}); + } + + ### NOTE: This was copied from 'anvil-join-anvil' and modified. + # Now I know what I have, lets see what I should have. + my $host_name = $anvil->Get->host_name; + my $new_password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password}; + my $escaped_password = shell_quote($new_password); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + host_name => $host_name, + new_password => $anvil->Log->is_secure($new_password), + escaped_password => $anvil->Log->is_secure($escaped_password), + }}); + + $anvil->data->{machine}{node1}{host_name} = ""; + $anvil->data->{machine}{node1}{host_uuid} = ""; + $anvil->data->{machine}{node1}{use_delay} = 0; + $anvil->data->{machine}{node2}{host_name} = ""; + $anvil->data->{machine}{node2}{host_uuid} = ""; + $anvil->data->{machine}{node2}{use_delay} = 0; + if ($local_node_is eq "node1") + { + # We're node 1 + $anvil->data->{machine}{node1}{host_name} = $local_node_name; + $anvil->data->{machine}{node1}{host_uuid} = $local_host_uuid; + $anvil->data->{machine}{node2}{host_name} = $peer_node_name; + $anvil->data->{machine}{node2}{host_uuid} = $peer_host_uuid; + } + else + { + # Our peer is node 1 + $anvil->data->{machine}{node1}{host_name} = $peer_node_name; + $anvil->data->{machine}{node1}{host_uuid} = $peer_host_uuid; + $anvil->data->{machine}{node2}{host_name} = $local_node_name; + $anvil->data->{machine}{node2}{host_uuid} = $local_host_uuid; + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "machine::node1::host_name" => $anvil->data->{machine}{node1}{host_name}, + "machine::node1::host_uuid" => $anvil->data->{machine}{node1}{host_uuid}, + "machine::node2::host_name" => $anvil->data->{machine}{node2}{host_name}, + "machine::node2::host_uuid" => $anvil->data->{machine}{node2}{host_uuid}, + }}); + + my $something_changed = {}; + my $fence_order = {}; + my $fence_devices = {}; + foreach my $node ("node1", "node2") + { + my $node_name = $anvil->data->{machine}{$node}{host_name}; + my $host_uuid = $anvil->data->{machine}{$node}{host_uuid}; + my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}; + my $ipmi_stonith_name = "ipmilan_".$node; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + node_name => $node_name, + host_uuid => $host_uuid, + host_ipmi => $host_ipmi =~ /passw/ ? $anvil->Log->is_secure($host_ipmi) : $host_ipmi, + ipmi_stonith_name => $ipmi_stonith_name, + }}); + + # This will store the fence level order. If something changes + $fence_order->{$node_name} = []; + + # This will switch to '1' if something changed, triggering a reconfig of the fencing levels. + $something_changed->{$node_name} = 0; + + # Does this stonith method already exist? + my $create_entry = 0; + my $delete_old = 0; + my $pcs_add_command = ""; + if ($host_ipmi) + { + push @{$fence_order->{$node_name}}, "fence_ipmilan"; + $fence_devices->{$node_name}{fence_ipmilan} = [$ipmi_stonith_name]; + + # The --action switch needs to be 'pcmk_off_action' in pcs, so we convert it here. + $host_ipmi =~ s/--action status//; + $host_ipmi =~ s/--action/--pcmk_off_action/; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + host_ipmi => $host_ipmi =~ /passw/ ? $anvil->Log->is_secure($host_ipmi) : $host_ipmi, + }}); + + # We have IPMI, so we also want fence_delay for this node. + $anvil->data->{machine}{$node}{use_delay} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "machine::${node}::use_delay" => $anvil->data->{machine}{$node}{use_delay}, + }}); + + # If we're here, break up the command and turn it into the pcs call. + my $old_switches = {}; + my ($fence_agent, $arguments) = ($host_ipmi =~ /^\/.*\/(.*?)\s+(.*)$/); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + fence_agent => $fence_agent, + arguments => $arguments =~ /passw/ ? $anvil->Log->is_secure($arguments) : $arguments, + }}); + + $pcs_add_command = $anvil->data->{path}{exe}{pcs}." stonith create ".$ipmi_stonith_name." ".$fence_agent." pcmk_host_list=\"".$node_name."\" "; + my $switches = $anvil->System->parse_arguments({arguments => $arguments}); + foreach my $switch (sort {$a cmp $b} keys %{$switches}) + { + # Ignore 'delay', we handle that in Cluster->set_delay(); Also, + # convert '#!SET!#' to 'true'. + my $value = $switches->{$switch}; + $value =~ s/"/\\"/g; + $value =~ s/#!SET!#/true/g; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + switch => $switch, + value => $value, + }}); + next if $anvil->data->{fence_data}{$fence_agent}{switch}{$switch}{name} eq "delay"; + next if $anvil->data->{fence_data}{$fence_agent}{switch}{$switch}{name} eq "action"; + + # Find the argument=value version. + my $argument = $anvil->data->{fence_data}{$fence_agent}{switch}{$switch}{name}; + $pcs_add_command .= $argument."=\"".$value."\" "; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + argument => $argument, + value => $argument =~ /passw/ ? $anvil->Log->is_secure($value) : $value, + pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, + }}); + + # Store this to see if it's different from what's already in the CIB. + $old_switches->{$argument} = $value; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "old_switches->{$argument}" => $old_switches->{$argument}, + }}); + } + $pcs_add_command .= "op monitor interval=\"60\""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, + }}); + + # If there's an entry in the CIB, so if it's different somehow + if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$ipmi_stonith_name}) + { + foreach my $argument (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$ipmi_stonith_name}{argument}}) + { + next if $argument eq "delay"; + next if $argument eq "action"; + my $old_entry = $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$ipmi_stonith_name}{argument}{$argument}{value}; + my $new_entry = exists $old_switches->{$argument} ? $old_switches->{$argument} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:argument' => $argument, + 's2:old_entry' => $old_entry, + 's3:new_entry' => $new_entry, + }}); + + if ($old_entry ne $new_entry) + { + # Changed, delete and recreate. + $delete_old = 1; + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0117"}); + last; + } + + # Delete the old switch. + delete $old_switches->{$argument}; + } + + # Are there any old switches left? + my $old_switch_count = keys %{$old_switches}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + old_switch_count => $old_switch_count, + }}); + if ((not $delete_old) && ($old_switch_count)) + { + # Delete and recreate. + $delete_old = 1; + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0117"}); + } + } + else + { + # No existing entry, add a new one. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0116"}); + + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { create_entry => $create_entry }}); + } + } + elsif (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$ipmi_stonith_name}) + { + # There was an existing fence config, but there's no entry in 'host_ipmi'. + # Remove the stonith entry. + $delete_old = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_old => $delete_old }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0118"}); + } + + # Process the IPMI entry. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + if ($delete_old) + { + # Delete + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0119", variables => { device => $ipmi_stonith_name }}); + + my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith delete ".$ipmi_stonith_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + + $something_changed->{$node_name} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); + } + if ($create_entry) + { + # Create. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0120", variables => { device => $ipmi_stonith_name }}); + + my $shell_call = $pcs_add_command; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + + $something_changed->{$node_name} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); + } + + + ### Now any other fence devices. + foreach my $device (sort {$a cmp $b} keys %{$anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$node}{fence}}) + { + my $delete_old = 0; + my $create_entry = 0; + my $old_switches = {}; + my $fence_uuid = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{fences}{$device}{uuid}; + my $fence_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_name}; + my $fence_arguments = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_arguments}; + my $fence_agent = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_agent}; + my $stonith_name = ($fence_agent =~ /^fence_(.*)$/)[0]."_".$node."_".$fence_name; + my $port = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{machine}{$node}{fence}{$device}{port}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + device => $device, + fence_uuid => $fence_uuid, + fence_name => $fence_name, + fence_arguments => $fence_arguments =~ /passw/ ? $anvil->Log->is_secure($fence_arguments) : $fence_arguments, + stonith_name => $stonith_name, + port => $port, + }}); + + # We use this to tell if there are two or more entries per agent. If there + # are, we link them later when setting up the fence levels. + if (not exists $fence_devices->{$node_name}{$fence_agent}) + { + push @{$fence_order->{$node_name}}, $fence_agent; + $fence_devices->{$node_name}{$fence_agent} = []; + } + push @{$fence_devices->{$node_name}{$fence_agent}}, $stonith_name; + + # Fence arguments use 'action', but pcs deprecated it in favour of 'pcmk_off_action', so rename it. + $fence_arguments =~ s/action=/pcmk_off_action=/; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + fence_arguments => $fence_arguments =~ /passw/ ? $anvil->Log->is_secure($fence_arguments) : $fence_arguments, + }}); + + # Build the pcs command + my $pcs_add_command = $anvil->data->{path}{exe}{pcs}." stonith create ".$stonith_name." ".$fence_agent." pcmk_host_list=\"".$node_name."\" ".$fence_arguments." "; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, + }}); + while ($fence_arguments =~ /=/) + { + # Ignore 'delay', we handle that in Cluster->set_delay(); + my $pair = ($fence_arguments =~ /(\S*?=".*?")/)[0]; + $fence_arguments =~ s/$pair//; + $fence_arguments =~ s/^\s+//; + $fence_arguments =~ s/\s+$//; + my ($argument, $value) = ($pair =~ /(.*)="(.*)"/); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:fence_arguments' => $fence_arguments, + 's2:pair' => $pair =~ /passw/ ? $anvil->Log->is_secure($pair) : $pair, + 's3:argument' => $argument, + 's4:value' => $argument =~ /passw/ ? $anvil->Log->is_secure($value) : $value, + }}); + + # Ignore 'delay', we handle that in Cluster->set_delay(); + if (($argument ne "pcmk_off_action") && + (exists $anvil->data->{fence_data}{$fence_agent}{switch}{$argument}{name}) && + ($anvil->data->{fence_data}{$fence_agent}{switch}{$argument}{name} eq "delay")) + { + next; + } + + # Store this to see if it's different from what's already in the CIB. + $old_switches->{$argument} = $value; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "old_switches->{$argument}" => $old_switches->{$argument}, + }}); + } + if ($port) + { + $port =~ s/"/\\"/g; + $pcs_add_command .= "port=\"".$port."\" "; + $old_switches->{port} = $port; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, + "old_switches->{port}" => $old_switches->{port}, + }}); + } + $pcs_add_command .= "op monitor interval=\"60\""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command, + }}); + + # Does this device exist already? + if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$stonith_name}) + { + foreach my $argument (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$stonith_name}{argument}}) + { + next if $argument eq "delay"; + my $old_entry = $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$stonith_name}{argument}{$argument}{value}; + my $new_entry = exists $old_switches->{$argument} ? $old_switches->{$argument} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:argument' => $argument, + 's2:old_entry' => $old_entry, + 's3:new_entry' => $new_entry, + }}); + + if ($old_entry ne $new_entry) + { + # Changed, delete and recreate. + $delete_old = 1; + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0121", variables => { device => $stonith_name }}); + last; + } + + # Delete the old switch. + delete $old_switches->{$argument}; + } + + # Are there any old switches left? + my $old_switch_count = keys %{$old_switches}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { old_switch_count => $old_switch_count }}); + if ((not $delete_old) && ($old_switch_count)) + { + # Delete and recreate. + $delete_old = 1; + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0121", variables => { device => $stonith_name }}); + } + } + else + { + # No existing entry, add a new one. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0122", variables => { device => $stonith_name }}); + + $create_entry = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { create_entry => $create_entry }}); + } + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + delete_old => $delete_old, + create_entry => $create_entry, + }}); + if ($delete_old) + { + # Delete + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0119", variables => { device => $stonith_name }}); + + my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith delete ".$stonith_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + + $something_changed->{$node_name} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); + } + if ($create_entry) + { + # Create. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0120", variables => { device => $stonith_name }}); + + my $shell_call = $pcs_add_command; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + + $something_changed->{$node_name} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); + } + } + + + ### If we had a fence_ipmilan entry, add a 'fence_delay' entry, if needed. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "machine::${node}::use_delay" => $anvil->data->{machine}{$node}{use_delay}, + }}); + if ($anvil->data->{machine}{$node}{use_delay}) + { + my $stonith_name = "delay_".$node; + push @{$fence_order->{$node_name}}, "fence_delay"; + $fence_devices->{$node_name}{fence_delay} = [$stonith_name]; + + # Add the fence delay if it doesn't exist yet. + if (not exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{device}{$stonith_name}) + { + my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith create ".$stonith_name." fence_delay pcmk_host_list=\"".$node_name."\" wait=\"60\" op monitor interval=\"60\""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + } + } + } + + # Setup fence levels. + foreach my $node_name (sort {$a cmp $b} keys %{$fence_order}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }}); + if ($something_changed->{$node_name}) + { + # Update our view of the cluster. + my $problem = $anvil->Cluster->parse_cib({debug => 2}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); + + # Delete any existing fence levels + if (exists $anvil->data->{cib}{parsed}{data}{node}{$node_name}) + { + foreach my $index (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{data}{node}{$node_name}{fencing}{order}}) + { + # pcs stonith level delete + my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith level delete ".$index." ".$node_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + } + } + + # Create the new fence levels + my $i = 1; + foreach my $fence_agent (@{$fence_order->{$node_name}}) + { + my $devices = ""; + foreach my $device (sort {$a cmp $b} @{$fence_devices->{$node_name}{$fence_agent}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { device => $device }}); + $devices .= $device.","; + } + $devices =~ s/,$//; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { devices => $devices }}); + + my $shell_call = $anvil->data->{path}{exe}{pcs}." stonith level add ".$i." ".$node_name." ".$devices; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + output => $output, + return_code => $return_code, + }}); + if ($return_code) + { + # Something went wrong. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0138", variables => { + shell_call => $shell_call, + output => $output, + return_code => $return_code, + }}); + return(1); + } + + $i++; + } + } + } + + + return(0); +} + + =head2 delete_server This takes a server (resource) name and deletes it from pacemaker. If there is a problem, C<< !!error!! >> is returned. Otherwise, C<< 0 >> is removed either once the resource is deleted, or if the resource didn't exist in the first place. @@ -884,11 +1595,11 @@ sub get_fence_methods my $short_host_name = $host_name; $short_host_name =~ s/\..*$//; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { short_host_name => $short_host_name }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { short_host_name => $short_host_name }}); # Find the Anvil! UUID. my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({host_uuid => $host_uuid}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_uuid => $anvil_uuid }}); if (not $anvil_uuid) { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0295", variables => { host_name => $host_name }}); @@ -900,7 +1611,7 @@ sub get_fence_methods debug => $debug, anvil_uuid => $anvil_uuid, }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_name => $anvil_name }}); ### NOTE: This probably won't work with fence methods that require multiple calls be run in parallel. ### As this is PDUs usually, and we skip them anyway, this shouldn't be an issue. @@ -1722,7 +2433,7 @@ sub migrate_server elsif (($status eq "running") && ($host eq $node)) { # Already running on the target. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0549", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0549", variables => { server => $server, requested_node => $node, }}); @@ -1785,7 +2496,7 @@ sub migrate_server host_name => $host_name, }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0550", variables => { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0550", variables => { server => $server, requested_node => $node, }}); @@ -2524,7 +3235,7 @@ sub parse_cib $anvil->data->{cib}{parsed}{data}{server}{$server}{failed} = $failed; $anvil->data->{cib}{parsed}{data}{server}{$server}{managed} = $managed; $anvil->data->{cib}{parsed}{data}{server}{$server}{orphaned} = $orphaned; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "cib::parsed::data::server::${server}::status" => $anvil->data->{cib}{parsed}{data}{server}{$server}{status}, "cib::parsed::data::server::${server}::host_name" => $anvil->data->{cib}{parsed}{data}{server}{$server}{host_name}, "cib::parsed::data::server::${server}::host_id" => $anvil->data->{cib}{parsed}{data}{server}{$server}{host_id}, @@ -2544,7 +3255,7 @@ sub parse_cib my $host_name = $anvil->data->{cib}{parsed}{data}{server}{$server}{host_name}; my $role = $anvil->data->{cib}{parsed}{data}{server}{$server}{role}; my $active = $anvil->data->{cib}{parsed}{data}{server}{$server}{active}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 's1:server' => $server, 's2:status' => $status, 's2:host_name' => $host_name, @@ -2892,7 +3603,7 @@ sub shutdown_server if (($status eq "off") or ($status eq "stopped")) { # Already off. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0548", variables => { server => $server }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0548", variables => { server => $server }}); return(0); } elsif ($status ne "running") @@ -2931,7 +3642,7 @@ sub shutdown_server host => $host, }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0554", variables => { server => $server }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0554", variables => { server => $server }}); if ($status eq "running") { # Wait a bit and check again. @@ -2941,7 +3652,7 @@ sub shutdown_server { # It's down. $waiting = 0; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0555", variables => { server => $server }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0555", variables => { server => $server }}); } } diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index d258054d..132b64d4 100644 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -1750,7 +1750,7 @@ LIMIT 1 $manufacturer = "Fujitsu"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { manufacturer => $manufacturer }}); } - elsif ($manufacturer =~ /dekk/i) + elsif ($manufacturer =~ /dell/i) { $manufacturer = "Dell"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { manufacturer => $manufacturer }}); @@ -2017,7 +2017,18 @@ LIMIT 1 { # We're good! $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0511"}); - + + # Update the database, in case needed. + my $host_uuid = $anvil->Get->host_uuid(); + $anvil->Database->insert_or_update_hosts({ + host_ipmi => $host_ipmi, + host_key => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}, + host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}, + host_type => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}, + host_uuid => $host_uuid, + host_status => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_status}, + }); + $try_again = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { try_again => $try_again }}); } @@ -2039,6 +2050,17 @@ LIMIT 1 { # We're good! $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0512"}); + + # Update the database, in case needed. + my $host_uuid = $anvil->Get->host_uuid(); + $anvil->Database->insert_or_update_hosts({ + host_ipmi => $host_ipmi, + host_key => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}, + host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}, + host_type => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}, + host_uuid => $host_uuid, + host_status => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_status}, + }); $try_again = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { try_again => $try_again }}); @@ -2139,6 +2161,17 @@ LIMIT 1 { # We're good, password was changed! $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0511"}); + + # Update the database, in case needed. + my $host_uuid = $anvil->Get->host_uuid(); + $anvil->Database->insert_or_update_hosts({ + host_ipmi => $host_ipmi, + host_key => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}, + host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}, + host_type => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}, + host_uuid => $host_uuid, + host_status => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_status}, + }); } else { @@ -2158,6 +2191,17 @@ LIMIT 1 { # We're good! $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0511"}); + + # Update the database, in case needed. + my $host_uuid = $anvil->Get->host_uuid(); + $anvil->Database->insert_or_update_hosts({ + host_ipmi => $host_ipmi, + host_key => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}, + host_name => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_name}, + host_type => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}, + host_uuid => $host_uuid, + host_status => $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_status}, + }); } else { diff --git a/cgi-bin/set_power b/cgi-bin/set_power index e69de29b..765590a6 100755 --- a/cgi-bin/set_power +++ b/cgi-bin/set_power @@ -0,0 +1,82 @@ +#!/usr/bin/perl +# +# This prints JSON formated data reporting the status of an Anvil! system and it's member hosts. +# + +use strict; +use warnings; +use Anvil::Tools; +use Data::Dumper; +use JSON; + +$| = 1; + +my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; +my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; +if (($running_directory =~ /^\./) && ($ENV{PWD})) +{ + $running_directory =~ s/^\./$ENV{PWD}/; +} + +my $anvil = Anvil::Tools->new(); + +$anvil->Get->switches; + +$anvil->Database->connect; +$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); +if (not $anvil->data->{sys}{database}{connections}) +{ + # No databases, exit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"}); + $anvil->nice_exit({exit_code => 1}); +} + +# Read in any CGI variables, if needed. +$anvil->Get->cgi(); + +$anvil->Database->get_hosts(); +$anvil->Database->get_anvils(); + +print $anvil->Template->get({file => "shared.html", name => "json_headers", show_name => 0})."\n"; + +my $hash = {}; +my $anvil_uuid = exists $anvil->data->{cgi}{anvil_uuid}{value} ? $anvil->data->{cgi}{anvil_uuid}{value} : ""; +my $host_uuid = exists $anvil->data->{cgi}{host_uuid}{value} ? $anvil->data->{cgi}{host_uuid}{value} : ""; +if (($anvil_uuid) && (not exists $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid})) +{ + $anvil->data->{anvil_status}{anvil_name} = "!!invalid!anvil_uuid!!"; +} +elsif (($host_uuid) && (not exists $anvil->data->{hosts}{host_uuid}{$anvil_uuid})) +{ + $anvil->data->{anvil_status}{anvil_name} = "!!invalid!host_uuid!!"; +} +elsif ((not $host_uuid) && (not $anvil_uuid)) +{ + $anvil->data->{anvil_status}{anvil_name} = "!!invalid!no_target!!"; +} +else +{ + # Are we managing the power of a node or an Anvil! system? If the later, we're controlling both. + +# $anvil->data->{anvil_status}{anvil_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_name}; +# $anvil->data->{anvil_status}{anvil_description} = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_description}; +# $anvil->data->{anvil_status}{timestamp} = time; +# +# my $node1_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; +# my $node2_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; +# my $node2_status = $anvil->data->{hosts}{host_uuid}{$node2_uuid}{host_status} eq "online" ? 1 : 0; +# +# $anvil->data->{anvil_status}{nodes}{node1}{host_name} = $anvil->data->{hosts}{host_uuid}{$node1_uuid}{host_name}; +# $anvil->data->{anvil_status}{nodes}{node1}{host_uuid} = $node1_uuid; +# $anvil->data->{anvil_status}{nodes}{node1}{host_status} = $anvil->data->{hosts}{host_uuid}{$node1_uuid}{host_status} eq "online" ? 1 : 0; +# $anvil->data->{anvil_status}{nodes}{node2}{host_name} = $anvil->data->{hosts}{host_uuid}{$node2_uuid}{host_name}; +# $anvil->data->{anvil_status}{nodes}{node2}{host_uuid} = $node2_uuid; +# $anvil->data->{anvil_status}{nodes}{node2}{host_status} = $anvil->data->{hosts}{host_uuid}{$node2_uuid}{host_status} eq "online" ? 1 : 0; +# +# $hash->{timestamp} = time; +# $hash->{nodes} = []; +# push @{$hash->{nodes}}, { on => $anvil->data->{anvil_status}{nodes}{node1}{host_status} }; +# push @{$hash->{nodes}}, { on => $anvil->data->{anvil_status}{nodes}{node2}{host_status} }; +} + +print JSON->new->utf8->encode($hash)."\n"; diff --git a/notes b/notes index 4a56dbb2..071a9f1e 100644 --- a/notes +++ b/notes @@ -1005,3 +1005,14 @@ OS10(conf-range-eth1/1/15-1/1/24)# exit 10.201.10.2 Could not get property: Refusing activation, D-Bus is shutting down Could not get property: Refusing activation, D-Bus is shutting down. Could not get property: Refusing activation, D-Bus is shutting down.bcn1 192.168.122.12 Could not get property: Refusing activation, D-Bus is shutting down.ifn1 10.101.10.2 Could not get property: Refusing activation, D-Bus is shutting down.sn1 + + +ausearch -c 'drbdsetup' --raw | audit2allow -M my-drbdsetup && semodule -X 300 -i my-drbdsetup.pp + + +May 02 13:35:21 zo-a01n02.zennioptical.com setroubleshoot[5333]: SELinux is preventing /usr/sbin/drbdsetup from create access on the netlink_generic_socket labeled drbd_t. For complete SELinux messages run: sealert -l 4079c288-db4a-4f44-a588-94f1dbfff269 +May 02 13:35:21 zo-a01n02.zennioptical.com setroubleshoot[5333]: SELinux is preventing /usr/sbin/drbdsetup from create access on the netlink_generic_socket labeled drbd_t. + If you believe that drbdsetup should be allowed create access on netlink_generic_socket labeled drbd_t by default. + # ausearch -c 'drbdsetup' --raw | audit2allow -M my-drbdsetup + # semodule -X 300 -i my-drbdsetup.pp + diff --git a/ocf/alteeve/server b/ocf/alteeve/server index 83fe03ea..58564508 100755 --- a/ocf/alteeve/server +++ b/ocf/alteeve/server @@ -157,8 +157,6 @@ $anvil->data->{switches}{migrate_from} = ""; # Sets 'meta_migrate_source' When s $anvil->data->{switches}{server} = ""; # Sets 'name'. $anvil->Get->switches({debug => 2}); -$anvil->Log->level({set => 2}); -$anvil->Log->secure({set => 1}); if ($anvil->data->{switches}{stop_drbd_resources}) { $anvil->data->{environment}{OCF_RESKEY_CRM_meta_migrate_source} = 1; diff --git a/scancore-agents/scan-cluster/scan-cluster b/scancore-agents/scan-cluster/scan-cluster index c705d2ba..c28eb9cc 100755 --- a/scancore-agents/scan-cluster/scan-cluster +++ b/scancore-agents/scan-cluster/scan-cluster @@ -120,12 +120,8 @@ sub check_config if ($manifest_uuid) { - my ($host_ipmi) = $anvil->System->configure_ipmi({ - debug => 2, - manifest_uuid => $manifest_uuid, - }); - - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_ipmi => $host_ipmi }}); + # Check to see if the stonith config needs to be updated. + $anvil->Cluster->check_stonith_config({debug => 2}); } return(0); diff --git a/share/words.xml b/share/words.xml index bc10f8aa..51876571 100644 --- a/share/words.xml +++ b/share/words.xml @@ -409,6 +409,10 @@ The attempt to start the servers appears to have failed. The return code '0' was The host: [#!variable!host_name!#] is not in an Anvil!, unable to parse fence methods. The Anvil!: [#!variable!anvil_name!#] does not have a recored CIB in the database, unable to parse fence methods. Either we failed to find a fence method, or all fence methods failed to boot this machine, unable to proceed. + check_stonith_config() only runs on nodes, and this host is a: [#!variable!host_type!#].]]> + This host is not in a cluster, or it's in the cluster but not ready yet. Either way, unable to check the config. + Failed to find the install manifest for the: [#!variable!anvil_name!#] Anvil! system. Unable to check or update the fence configuration. + Failed to parse the install manifest with UUID: [#!variable!manifest_uuid!#]. Unable to check or update the fence configuration. diff --git a/tools/scancore b/tools/scancore index 016d2542..8e7b6121 100755 --- a/tools/scancore +++ b/tools/scancore @@ -341,24 +341,29 @@ sub startup_tasks variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => 'hosts', }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { variable_uuid => $variable_uuid }}); - # If we've been up for less than ten minutes, call anvil-safe-start as a background process. It will - # exit if it is disabled. - my $uptime = $anvil->Get->uptime; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }}); - if ($uptime < 600) + # If this is a node and we've been up for less than ten minutes, call anvil-safe-start as a + # background process. It will exit if it is disabled. + my $host_type = $anvil->Get->host_type(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { host_type => $host_type }}); + if ($host_type eq "node") { - # Run it as a background task - my $shell_call = $anvil->data->{path}{exe}{'anvil-safe-start'}; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0210", variables => { command => $shell_call }}); - $anvil->System->call({shell_call => $shell_call, background => 1}); - } - else - { - # Log that we've been up too long to auto-start the cluster. - my $say_uptime = $anvil->Convert->time({'time' => $uptime}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0620", variables => { uptime => $say_uptime }}); + my $uptime = $anvil->Get->uptime; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }}); + if ($uptime < 600) + { + # Run it as a background task + my $shell_call = $anvil->data->{path}{exe}{'anvil-safe-start'}; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0210", variables => { command => $shell_call }}); + $anvil->System->call({shell_call => $shell_call, background => 1}); + } + else + { + # Log that we've been up too long to auto-start the cluster. + my $say_uptime = $anvil->Convert->time({'time' => $uptime}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0620", variables => { uptime => $say_uptime }}); + } } return(0);