From 8925dabb9db03dd9a773376f3a85fe4fd2301f75 Mon Sep 17 00:00:00 2001 From: digimer Date: Thu, 21 Sep 2023 18:56:12 -0400 Subject: [PATCH] * Updated anvil-shutdown-server to take the new '--immediate' switch which forces a server to shut down immediately (akin to pulling the power on a traditional machine). This is needed to allow a user to recover a crash or hung server. Signed-off-by: digimer --- Anvil/Tools/Server.pm | 5 +++- man/anvil-shutdown-server.8 | 6 +++++ share/words.xml | 2 ++ tools/anvil-shutdown-server | 53 ++++++++++++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index 39866588..78b2c895 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -2145,8 +2145,11 @@ sub shutdown_virsh elsif ($status eq "pmsuspended") { # The server is suspended. Resume it, wait a few, then proceed with the shutdown. + my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." dompmwakeup ".$server; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0317", variables => { server => $server }}); - my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." dompmwakeup $server"}); + my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); if ($return_code) { # Looks like virsh isn't running. diff --git a/man/anvil-shutdown-server.8 b/man/anvil-shutdown-server.8 index e822676e..0294303d 100644 --- a/man/anvil-shutdown-server.8 +++ b/man/anvil-shutdown-server.8 @@ -19,6 +19,10 @@ When logging, record sensitive data, like passwords. 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\-\-immediate\fR +.TP +This causes the server to be forced off, equivalent to pulling the power cord out of a traditional server. This doesn't work with '\fB\-\-server all\fR', a specific server must be specified. +.TP \fB\-\-no\-db\fR .TP This tells the program to run without connecting to any databases. This is used mainly when the host is being taken down as part of a cluster-wise upgrade. @@ -38,6 +42,8 @@ This is the server UUID of the server to shut down. NOTE: This can not be used w \fB\-\-wait\fR .TP This tells the program to wait for the server(s) to stop before returning. By default, when '\fB\-\-server all\fR' is used,, the shutdown will NOT wait. This makes the shutdowns sequential. +.TP +Note: When \fB\-\-immediate\fR is used, \fB\-\-wait\fR is ignored. .IP .SH AUTHOR Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. diff --git a/share/words.xml b/share/words.xml index 666e444a..71383796 100644 --- a/share/words.xml +++ b/share/words.xml @@ -725,6 +725,7 @@ The creation of the new replicatedd disk is incomplete, manual intervention is r #!variable!error!# ==================== The creation of the new replicated disk is incomplete, manual intervention is required!]]> + @@ -1684,6 +1685,7 @@ Note: This is a permanent action! If you protect this server again later, a full Exiting. Server Storage Management This job manages the storage on a given hosted server. It can grow an existing disk, add a new disk, insert an ISO into an optical disc, or eject a disc. + The server: [#!variable!server!#] will now be forced off! Starting: [#!variable!program!#]. diff --git a/tools/anvil-shutdown-server b/tools/anvil-shutdown-server index 0fcce6ea..8623d68f 100755 --- a/tools/anvil-shutdown-server +++ b/tools/anvil-shutdown-server @@ -29,6 +29,7 @@ my $anvil = Anvil::Tools->new(); # Read switches (target ([user@]host[:port]) and the file with the target's password. $anvil->Get->switches({list => [ + "immediate", "no-db", "no-wait", "server", @@ -142,6 +143,15 @@ if (not $anvil->data->{switches}{'server'}) $anvil->nice_exit({exit_code => 1}); } +# If we're forcing off a server, make sure '--server' isn't 'all'. +if (($anvil->data->{switches}{'server'} =~ /all/i) && ($anvil->data->{switches}{immediate})) +{ + # Unable to proceed. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0462"}); + $anvil->Job->update_progress({progress => 100, message => "error_0462"}); + $anvil->nice_exit({exit_code => 1}); +} + # Are we a node or DR host? $anvil->data->{sys}{host_type} = $anvil->Get->host_type(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { @@ -252,6 +262,12 @@ sub shutdown_server progress => $progress, }}); + if (($wait) && ($anvil->data->{switches}{immediate})) + { + $wait = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'wait' => $wait }}); + } + # Is the server in the cluster? if (not exists $anvil->data->{cib}{parsed}{data}{server}{$server}) { @@ -271,20 +287,34 @@ sub shutdown_server return(0); } - # Now shut down. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0289", variables => { server => $server }}); - $anvil->Job->update_progress({progress => $progress, message => "job_0289,!!server!".$server."!!"}) if $anvil->data->{switches}{'job-uuid'}; + # Now shut down. Forcibly? + if ($anvil->data->{switches}{immediate}) + { + # Kill it! + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0474", variables => { server => $server }}); + $anvil->Job->update_progress({progress => $progress, message => "job_0474,!!server!".$server."!!"}) if $anvil->data->{switches}{'job-uuid'}; + } + else + { + # Lets be gentle + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0289", variables => { server => $server }}); + $anvil->Job->update_progress({progress => $progress, message => "job_0289,!!server!".$server."!!"}) if $anvil->data->{switches}{'job-uuid'}; + } my $problem = 0; if ($anvil->Get->host_type eq "dr") { # Shut down using virsh. Invert the return. + my $force = $anvil->data->{switches}{immediate} ? 1 : 0; my $success = $anvil->Server->shutdown_virsh({ debug => 2, + server => $server, + force => $force, wait_time => $wait ? 0 : 1, }); $problem = $success ? 0 : 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + force => $force, success => $success, problem => $problem, }}); @@ -297,7 +327,24 @@ sub shutdown_server 'wait' => $wait, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + + # If we're being asked to force the server off, do it now regardless of what pacemaker returned. + if ($anvil->data->{switches}{immediate}) + { + my $success = $anvil->Server->shutdown_virsh({ + debug => 2, + server => $server, + force => 1, + wait_time => 0, + }); + $problem = $success ? 0 : 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + success => $success, + problem => $problem, + }}); + } } + if ($problem) { # Failed, abort.