Merge pull request #71 from ClusterLabs/anvil-safe-start-work
* Started work on anvil-safe-start. The enable/disable logic and how …main
commit
c745a13991
4 changed files with 281 additions and 0 deletions
@ -0,0 +1,258 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
# This does boot-time sanity checks on nodes and then, if all is well, joins the cluster and boots servers. |
||||
# |
||||
# NOTE: Unlike M2, this is controlled by scancore's start, but only if scancore starts up within ten minutes |
||||
# of the node itself booting. This way, stopping/starting scancore won't call us repeatedly. This tool |
||||
# is enabled or disabled via the 'tool::anvil-safe-start::enabled' variable tied to the 'hosts' -> |
||||
# 'host_uuid' table. |
||||
# |
||||
# Exit codes; |
||||
# 0 = Normal exit. |
||||
# 1 = Any problem that causes an early exit. |
||||
# |
||||
# TODO: |
||||
# - Make this work on DR hosts. |
||||
# |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use Anvil::Tools; |
||||
require POSIX; |
||||
|
||||
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||
{ |
||||
$running_directory =~ s/^\./$ENV{PWD}/; |
||||
} |
||||
|
||||
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||
$| = 1; |
||||
|
||||
my $anvil = Anvil::Tools->new(); |
||||
$anvil->Get->switches; |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); |
||||
|
||||
# Make sure we're running as 'root' |
||||
# $< == real UID, $> == effective UID |
||||
if (($< != 0) && ($> != 0)) |
||||
{ |
||||
# Not root |
||||
print $anvil->Words->string({key => "error_0005"})."\n"; |
||||
$anvil->nice_exit({exit_code => 1}); |
||||
} |
||||
|
||||
# Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks |
||||
# is to setup the database server. |
||||
$anvil->Database->connect(); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); |
||||
|
||||
$anvil->data->{switches}{disable} = ""; |
||||
$anvil->data->{switches}{enable} = ""; |
||||
$anvil->data->{switches}{force} = ""; |
||||
$anvil->data->{switches}{'local'} = ""; |
||||
$anvil->data->{switches}{status} = ""; |
||||
$anvil->Get->switches; |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); |
||||
|
||||
|
||||
# If I have no databases, sleep until I do |
||||
if (not $anvil->data->{sys}{database}{connections}) |
||||
{ |
||||
# If this is a dashboard, try to configure and then connect to the local database. If this isn't a |
||||
# Wait until we have one. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, secure => 0, key => "error_0075"}); |
||||
|
||||
until($anvil->data->{sys}{database}{connections}) |
||||
{ |
||||
sleep 10; |
||||
|
||||
$anvil->refresh(); |
||||
$anvil->Database->connect(); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"}); |
||||
if (not $anvil->data->{sys}{database}{connections}) |
||||
{ |
||||
# Keep waiting |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 0, level => 3, secure => 0, key => "log_0439"}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
# Check to see if we should run. Also checks/sets enable/disable requests. |
||||
prerun_checks($anvil); |
||||
|
||||
$anvil->nice_exit({exit_code => 0}); |
||||
|
||||
############################################################################################################# |
||||
# Functions # |
||||
############################################################################################################# |
||||
|
||||
# This checks to verify that we're a node, and if so, if this tool is enabled. If it's disabled or this isn't |
||||
# a node, this method will exit. |
||||
sub prerun_checks |
||||
{ |
||||
my ($anvil) = @_; |
||||
|
||||
$anvil->Database->get_hosts(); |
||||
$anvil->Database->get_anvils(); |
||||
|
||||
my $host_uuid = $anvil->Get->host_uuid(); |
||||
my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||
host_uuid => $host_uuid, |
||||
host_type => $host_type, |
||||
}}); |
||||
|
||||
if ($host_type ne "node") |
||||
{ |
||||
# We're done. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0598"}); |
||||
$anvil->nice_exit({exit_code => 0}); |
||||
} |
||||
|
||||
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid(); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); |
||||
|
||||
if (not $anvil_uuid) |
||||
{ |
||||
# This is a node, but not in an Anvil! yet. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0603"}); |
||||
$anvil->nice_exit({exit_code => 0}); |
||||
} |
||||
|
||||
my $node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; |
||||
my $node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; |
||||
my $peer_host_uuid = $host_uuid eq $node1_host_uuid ? $node2_host_uuid : $node1_host_uuid; |
||||
|
||||
# Are we being asked to enable or disable? |
||||
my $nodes = [$host_uuid]; |
||||
my $set_to = 1; |
||||
my $message = ""; |
||||
if ($anvil->data->{switches}{enable}) |
||||
{ |
||||
# We're enabling, which message will we use? |
||||
$message = $anvil->data->{switches}{'local'} ? "log_0599" : "log_0600"; |
||||
} |
||||
elsif ($anvil->data->{switches}{disable}) |
||||
{ |
||||
# We're disabling. Which message? |
||||
$set_to = 0; |
||||
$message = $anvil->data->{switches}{'local'} ? "log_0601" : "log_0602"; |
||||
} |
||||
|
||||
# If we're updating the settings, do so and then exit. |
||||
if ($message) |
||||
{ |
||||
if (not $anvil->data->{switches}{'local'}) |
||||
{ |
||||
# Add our peer as well. |
||||
push @{$nodes}, $peer_host_uuid; |
||||
} |
||||
foreach my $host_uuid (@{$nodes}) |
||||
{ |
||||
my ($variable_uuid) = $anvil->Database->insert_or_update_variables({ |
||||
debug => 2, |
||||
variable_name => "tool::anvil-safe-start::enabled", |
||||
variable_value => $set_to, |
||||
variable_default => 1, |
||||
variable_description => "striker_0286", |
||||
variable_section => "system", |
||||
variable_source_uuid => $host_uuid, |
||||
variable_source_table => "hosts", |
||||
}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); |
||||
} |
||||
|
||||
# Record that it's been enabled. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => $message}); |
||||
$anvil->nice_exit({exit_code => 0}); |
||||
} |
||||
|
||||
# Read my variables. |
||||
my ($local_enabled, $variable_uuid, $mtime, $modified_date) = $anvil->Database->read_variable({ |
||||
debug => 2, |
||||
variable_name => "tool::anvil-safe-start::enabled", |
||||
variable_source_table => "hosts", |
||||
variable_source_uuid => $host_uuid, |
||||
}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||
local_enabled => $local_enabled, |
||||
variable_uuid => $variable_uuid, |
||||
}}); |
||||
# No UUID means the value hasn't been recorded, so we default to 1. |
||||
if (not $variable_uuid) |
||||
{ |
||||
$local_enabled = 1; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_enabled => $local_enabled }}); |
||||
} |
||||
|
||||
# Have we just been asked for the status? |
||||
if ($anvil->data->{switches}{status}) |
||||
{ |
||||
# Yes, check our peer as well. |
||||
my ($peer_enabled, $variable_uuid, $mtime, $modified_date) = $anvil->Database->read_variable({ |
||||
variable_name => "tool::anvil-safe-start::enabled", |
||||
variable_source_table => "hosts", |
||||
variable_source_uuid => $peer_host_uuid, |
||||
}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||
peer_enabled => $peer_enabled, |
||||
variable_uuid => $variable_uuid, |
||||
}}); |
||||
# No UUID means the value hasn't been recorded, so we default to 1. |
||||
if (not $variable_uuid) |
||||
{ |
||||
$peer_enabled = 1; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_enabled => $peer_enabled }}); |
||||
} |
||||
|
||||
# What we tell the use slightly depends on which nodes are enabled. |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
||||
local_enabled => $local_enabled, |
||||
peer_enabled => $peer_enabled, |
||||
}}); |
||||
|
||||
my $message = ""; |
||||
if (($local_enabled) && ($peer_enabled)) |
||||
{ |
||||
# Both nodes are enabled. |
||||
$message = "message_0227"; |
||||
} |
||||
elsif ((not $local_enabled) && (not $peer_enabled)) |
||||
{ |
||||
# Both nodes are disabled |
||||
$message = "message_0228"; |
||||
} |
||||
elsif ($local_enabled) |
||||
{ |
||||
# We're enabled, the peer is disabled. |
||||
$message = "message_0229"; |
||||
} |
||||
else |
||||
{ |
||||
# We're disabled, the peer is enabled. |
||||
$message = "message_0230"; |
||||
} |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => $message}); |
||||
$anvil->nice_exit({exit_code => 0}); |
||||
} |
||||
|
||||
if (not $local_enabled) |
||||
{ |
||||
# Disabled. Forced? |
||||
if ($anvil->data->{switches}{force}) |
||||
{ |
||||
# Forced, run anyway. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0232"}); |
||||
} |
||||
else |
||||
{ |
||||
# Exit. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0231"}); |
||||
$anvil->nice_exit({exit_code => 0}); |
||||
} |
||||
} |
||||
|
||||
return(0); |
||||
} |
Loading…
Reference in new issue