Updated striker-boot-machine to support booting all machines.

* Wrote the man page for striker-boot-machine, changing --host-name to
  --host, and adding the '--host all' support.
* Updated anvil-manage-host to support checking/enabling/disabling
  network mapping mode.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 1 year ago
parent c14615bbc7
commit 4398ffe70c
  1. 2
      cgi-bin/set_power
  2. 57
      man/anvil-manage-host.8
  3. 38
      man/striker-boot-machine.8
  4. 4
      share/words.xml
  5. 117
      tools/anvil-manage-host
  6. 147
      tools/striker-boot-machine

@ -107,7 +107,7 @@ sub set_host_power
elsif (not $is_host_on && $on)
{
$anvil->Database->insert_or_update_jobs({
job_command => $anvil->data->{path}{directories}{tools}."/striker-boot-machine --host-uuid ".$host_uuid,
job_command => $anvil->data->{path}{directories}{tools}."/striker-boot-machine --host ".$host_uuid,
job_description => "job_0335",
job_name => "cgi-bin::set_power::on",
job_progress => 0,

@ -0,0 +1,57 @@
.\" Manpage for the Anvil! server boot program
.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions.
.TH anvil-manage-host "8" "Octobober 12 2023" "Anvil! Intelligent Availability™ Platform"
.SH NAME
anvil-manage-host \- Tool used to check or set various configuration options for a host.
.SH SYNOPSIS
.B anvil-manage-host
\fI\,<command> \/\fR[\fI\,options\/\fR]
.SH DESCRIPTION
.TP
.SH OPTIONS
.TP
\-?, \-h, \fB\-\-help\fR
Show this man page.
.TP
\fB\-\-log-secure\fR
When logging, record sensitive data, like passwords.
.TP
\-v, \-vv, \-vvv
Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data.
.SS "Commands:"
.TP
\fB\-\-age\-out\-database\fR
This requests the database check for records that are too old and purge them.
.TP
\fB\-\-check\-configured\fR
Check to see if the host is marked as configured or yet.
.TP
\fB\-\-check\-database\fR
This checks to see if the database is enabled or not.
.TP
\fB\-\-check\-network\-mapping\fR
This reports if the host is currently in network mapping (this disables several features and watches the network states much more frequently)
.TP
\fB\-\-database\-active\fR
This enables the database on the local Striker dashboard.
.TP
\fB\-\-database\-inactive\fR
This disables the database on the local Striker dashboard.
.TP
\fB\-\-disable\-network\-mapping\fR
This disables the network mapping mode.
.TP
\fB\-\-enable\-network\-mapping\fR
This enables the network mapping mode.
.TP
\fB\-\-mark\-configured\fR
This marks the host as having been configured.
.TP
\fB\-\-resync\-database\fR
This forces a database resync if two or more strikers are online.
.IP
.SH AUTHOR
Written by Madison Kelly, Alteeve staff and the Anvil! project contributors.
.SH "REPORTING BUGS"
Report bugs to users@clusterlabs.org

@ -0,0 +1,38 @@
.\" Manpage for the Anvil! server boot program
.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions.
.TH striker-boot-machine "8" "Octobober 12 2023" "Anvil! Intelligent Availability™ Platform"
.SH NAME
striker-boot-machine \- Tool used to boot physical machines that have IPMI configuration information.
.SH SYNOPSIS
.B striker-boot-machine
\fI\,<command> \/\fR[\fI\,options\/\fR]
.SH DESCRIPTION
This tool is used to power up any machine in the cluster with IPMI configuration in the database. Typically this is subnodes and DR hosts, but could also be Striker dashboards if they have an IPMI BMC. If the server is found to already be om, it will NOT be booted again.
.TP
.SH OPTIONS
.TP
\-?, \-h, \fB\-\-help\fR
Show this man page.
.TP
\fB\-\-log-secure\fR
When logging, record sensitive data, like passwords.
.TP
\-v, \-vv, \-vvv
Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data.
.SS "Commands:"
.TP
\fB\-\-host\fR <name, UUID or 'all'>
This is the host name or UUID of the server to power on. If this is set to 'all', all machines that have IPMI configuration information will be checked, and if it's found to be off, it will be booted.
.TP
\fB\-\-host-uuid\fR <UUID>
This is effectively the same as \fB\-\-host\fR, but provides backwards compatibility. It's use is discouraged.
.TP
\fB\-\-job\-uuid\fR <uuid>
If this is set, the job will be processed.
.TP
Be aware that when this is used, if a server fails to boot, no further servers will be started.
.IP
.SH AUTHOR
Written by Madison Kelly, Alteeve staff and the Anvil! project contributors.
.SH "REPORTING BUGS"
Report bugs to users@clusterlabs.org

@ -3172,6 +3172,10 @@ Proceed? [y/N]</key>
<key name="message_0350">Preparing to managing storage for a server.</key>
<key name="message_0351">Running checks before processing power request...</key>
<key name="message_0352">The job to: [#!variable!task!#] this host has been picked up.</key>
<key name="message_0353">This host is already configured to map the network.</key>
<key name="message_0354">This host is now configured to map the network.</key>
<key name="message_0355">This host is already NOT configured to map the network.</key>
<key name="message_0356">This host is no longer configured to map the network.</key>
<!-- Translate names (protocols, etc) -->
<key name="name_0001">Normal Password</key> <!-- none in mail-server -->

@ -28,8 +28,11 @@ $anvil->Get->switches({list => [
"age-out-database",
"check-configured",
"check-database",
"check-network-mapping",
"database-active",
"database-inactive",
"disable-network-mapping",
"enable-network-mapping",
"mark-configured",
"mark-unconfigured",
"resync-database"], man => $THIS_FILE});
@ -53,6 +56,10 @@ elsif (($anvil->data->{switches}{'database-active'}) or ($anvil->data->{switches
{
update_database($anvil);
}
elsif (($anvil->data->{switches}{'enable-network-mapping'}) or ($anvil->data->{switches}{'disable-network-mapping'}) or ($anvil->data->{switches}{'check-network-mapping'}))
{
update_network_mapping($anvil);
}
elsif ($anvil->data->{switches}{'age-out-database'})
{
age_out_data($anvil);
@ -156,7 +163,6 @@ sub update_database
variable_name => $variable_name,
}});
# Read if it's active or inactive yet.
my ($active_value, undef, undef) = $anvil->Database->read_variable({variable_name => "database::".$host_uuid."::active"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { active_value => $active_value }});
@ -224,6 +230,114 @@ sub update_database
return(0);
}
sub update_network_mapping
{
my ($anvil) = @_;
my $variable_name = "config::map_network";
my ($map_network_value, $map_network_uuid, $map_network_mtime, $map_network_modified_date) = $anvil->Database->read_variable({
variable_name => $variable_name,
variable_source_table => "hosts",
variable_source_uuid => $anvil->data->{sys}{host_uuid},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:variable_name' => $variable_name,
's2:map_network_value' => $map_network_value,
's3:map_network_mtime' => $map_network_mtime,
's4:map_network_modified_date' => $map_network_modified_date,
's5:map_network_uuid' => $map_network_uuid,
}});
if ($anvil->data->{switches}{'check-configured'})
{
# We'll run for a day (should be cancelled by the program when the user's done, so this
# shouldn't fire in practice).
my $expire_age = 86400;
my $map_network_age = 0;
if ($map_network_uuid)
{
$map_network_age = time - $map_network_mtime;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { map_network_age => $map_network_age }});
}
if ($map_network_value)
{
# How long ago was it set?
$anvil->data->{switches}{'clear-mapping'} = "" if not defined $anvil->data->{switches}{'clear-mapping'};
if (($map_network_age >= $expire_age) or ($anvil->data->{switches}{'clear-mapping'}))
{
# Clear it.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0470"});
$anvil->Database->insert_or_update_variables({
debug => 3,
variable_value => 0,
variable_uuid => $map_network_uuid,
update_value_only => 1,
});
}
else
{
# Mark it so we only track the network.
my $say_age = $anvil->Convert->add_commas({number => $expire_age});
my $timeout = $anvil->Convert->add_commas({number => ($expire_age - $map_network_age)});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0471", variables => {
age => $say_age,
timeout => $timeout,
}});
}
}
return(0);
}
if ($anvil->data->{switches}{'enable-network-mapping'})
{
if ($map_network_value)
{
# Nothing to do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0353"});
}
else
{
# Enable network configuring.
my $variable_uuid = $anvil->Database->insert_or_update_variables({
variable_name => $variable_name,
variable_value => 1,
variable_default => "",
variable_description => "striker_0202",
variable_section => "config",
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->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0354"});
}
}
if ($anvil->data->{switches}{'disable-network-mapping'})
{
if ($map_network_value)
{
# Disable network configuring.
my $variable_uuid = $anvil->Database->insert_or_update_variables({
variable_name => $variable_name,
variable_value => 0,
variable_default => "",
variable_description => "striker_0202",
variable_section => "config",
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->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0356"});
}
else
{
# Nothing to do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0355"});
}
}
return(0);
}
sub update_config
{
my ($anvil) = @_;
@ -292,6 +406,5 @@ sub update_config
}
}
return(0);
}

@ -26,16 +26,12 @@ $| = 1;
my $anvil = Anvil::Tools->new();
$anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{'host-uuid'} = "";
$anvil->data->{switches}{'host-name'} = "";
$anvil->Get->switches;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'},
'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'},
'switches::host-name' => $anvil->data->{switches}{'host-name'},
}});
$anvil->Get->switches({list => [
"host",
"host-uuid",
"job-uuid"], man => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
$anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
@ -70,23 +66,34 @@ if ($anvil->data->{switches}{'job-uuid'})
'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'},
}});
}
if ($line =~ /host-name=(.*?)$/)
if ($line =~ /host=(.*?)$/)
{
$anvil->data->{switches}{'host-name'} = $1;
$anvil->data->{switches}{host} = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::host-name' => $anvil->data->{switches}{'host-name'},
'switches::host' => $anvil->data->{switches}{host},
}});
}
}
}
# If we have a host name, but not a host-uuid, look up the host UUID.
if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{'host-name'}))
# Get the host info (copy host-uuid to host)
$anvil->data->{switches}{'host-name'} = "" if not defined $anvil->data->{switches}{'host-name'};
if ((not $anvil->data->{switches}{host}) && ($anvil->data->{switches}{'host-uuid'}))
{
$anvil->data->{switches}{host} = $anvil->data->{switches}{'host-uuid'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::host' => $anvil->data->{switches}{host},
}});
}
# If the host is 'all', don't translate to the host_uuid. Otherwise, look for the host_uuid from the host string
if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{host} ne "all"))
{
$anvil->data->{switches}{'host-uuid'} = $anvil->Get->host_uuid_from_name({host_name => $anvil->data->{switches}{'host-name'}});
$anvil->data->{switches}{'host-uuid'} = $anvil->Database->get_host_uuid_from_string({string => $anvil->data->{switches}{host}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'},
}});
# host name not found
if (not $anvil->data->{switches}{'host-uuid'})
{
@ -94,14 +101,11 @@ if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{'ho
$anvil->Job->update_progress({progress => 100, message => "error_0291,!!host_name!".$anvil->data->{switches}{'host-name'}."!!"});
$anvil->nice_exit({exit_code => 1});
}
}
# If we still don't have a host_uuid, we can't proceed.
if (not $anvil->data->{switches}{'host-uuid'})
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0290"});
$anvil->Job->update_progress({progress => 100, message => "error_0290"});
$anvil->nice_exit({exit_code => 1});
$anvil->data->{switches}{'host-name'} = $anvil->Get->host_name_from_uuid({host_uuid => $anvil->data->{switches}{'host-uuid'}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
'switches::host-name' => $anvil->data->{switches}{'host-name'},
}});
}
find_boot_method($anvil);
@ -121,33 +125,73 @@ sub find_boot_method
$anvil->Database->get_hosts_info({debug => 2});
my $host_uuid = $anvil->data->{switches}{'host-uuid'};
my $host_name = $anvil->data->{machine}{host_uuid}{$host_uuid}{hosts}{host_name};
my $host_ipmi = $anvil->data->{machine}{host_uuid}{$host_uuid}{hosts}{host_ipmi};
my $hosts = [];
if ($anvil->data->{switches}{'host-uuid'})
{
push @{$hosts}, $anvil->data->{switches}{'host-name'};
}
elsif ($anvil->data->{switches}{host} eq "all")
{
$anvil->Database->get_hosts({debug => 2});
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}})
{
my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name};
my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi};
my $host_key = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:host_name' => $host_name,
's2:host_uuid' => $host_uuid,
's3:host_ipmi' => $anvil->Log->is_secure($host_ipmi),
}});
next if $host_key eq "DELETED";
next if not $host_ipmi;
push @{$hosts}, $host_name;
}
}
my $host_count = @{$hosts};
my $steps = int((80 / $host_count) / 3);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_count => $host_count,
steps => $steps,
}});
$anvil->data->{sys}{progress} = 5;
foreach my $host_name (sort {$a cmp $b} @{$hosts})
{
my $host_uuid = $anvil->Database->get_host_uuid_from_string({string => $host_name});
my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi};
my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host_uuid => $host_uuid,
host_name => $host_name,
host_ipmi => $anvil->Log->is_secure($host_ipmi),
host_type => $host_type,
}});
$anvil->data->{sys}{progress} = 10;
$anvil->data->{sys}{progress} += $steps;
# If we have IPMI, that's the easiest method.
if ($host_ipmi)
{
# Got it.
$anvil->data->{sys}{progress} += $steps;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "job_0327", variables => { host_name => $host_name }});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}+=10, message => "job_0327,!!host_name!".$host_name."!!"});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "job_0327,!!host_name!".$host_name."!!"});
# First, is the node already on?
my $shell_call = $host_ipmi." -o status";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { shell_call => $shell_call }});
call_fence_agent($anvil, $shell_call);
}
$anvil->data->{sys}{progress} += $steps;
my $problem = call_fence_agent($anvil, $shell_call, $anvil->data->{sys}{progress});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { problem => $problem }});
# If I am here, either there is no IPMI. Can we boot it using another fence method?
# Is the machine in an Anvil! system?
$anvil->data->{sys}{progress} += $steps;
if ($problem)
{
# If I am here, there is no IPMI. Can we boot it using another fence method?
# The machine would have to be in an Anvil! for this to work.
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 }});
if ($anvil_uuid)
@ -158,7 +202,7 @@ sub find_boot_method
host_name => $host_name,
anvil_name => $anvil_name,
}});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}+=10, message => "job_0331,!!host_name!".$host_name."!!,!!anvil_name!".$anvil_name."!!"});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "job_0331,!!host_name!".$host_name."!!,!!anvil_name!".$anvil_name."!!"});
$anvil->Cluster->get_fence_methods({host_uuid => $host_uuid});
foreach my $target_host_name (sort {$a cmp $b} keys %{$anvil->data->{fence_method}})
@ -175,23 +219,32 @@ sub find_boot_method
method => $method,
shell_call => $anvil->Log->is_secure($shell_call),
}});
call_fence_agent($anvil, $shell_call);
my $problem = call_fence_agent($anvil, $shell_call, $anvil->data->{sys}{progress});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }});
if ($problem)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0297"});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "error_0297"});
}
}
}
}
# If I hit here, we ran out of fence options and can't boot the machine.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0297"});
$anvil->Job->update_progress({progress => 100, message => "error_0297"});
$anvil->nice_exit({exit_code => 1});
}
else
{
# Nothing we can do to boot this machine.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0294"});
$anvil->Job->update_progress({progress => 100, message => "error_0294"});
$anvil->nice_exit({exit_code => 1});
$anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "error_0294"});
}
}
}
}
# Done.
$anvil->Job->update_progress({progress => 100, message => "message_0025"});
$anvil->nice_exit({exit_code => 0});
return(0);
}
@ -199,7 +252,7 @@ sub find_boot_method
# This calls a fence agent and exits if it successfully boots the target
sub call_fence_agent
{
my ($anvil, $shell_call) = @_;
my ($anvil, $shell_call, $progress) = @_;
my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, secure => 1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
@ -212,14 +265,14 @@ sub call_fence_agent
# The machine is already on
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0328"});
$anvil->Job->update_progress({progress => 100, message => "job_0328"});
$anvil->nice_exit({exit_code => 0});
return(0);
}
elsif ($return_code eq "1")
{
# Unable to connect to the fence device.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0293", variables => { output => $output }});
$anvil->Job->update_progress({progress => 100, message => "error_0293,!!output!".$output."!!"});
$anvil->nice_exit({exit_code => 1});
return(1);
}
elsif ($return_code eq "2")
{
@ -249,14 +302,14 @@ sub call_fence_agent
host_uuid => $anvil->data->{switches}{'host-uuid'},
host_status => "booting",
});
$anvil->nice_exit({exit_code => 0});
return(0);
}
else
{
# Failed.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0292", variables => { output => $output }});
$anvil->Job->update_progress({progress => 100, message => "error_0292,!!output!".$output."!!"});
$anvil->nice_exit({exit_code => 1});
return(1);
}
}

Loading…
Cancel
Save