From 5bb1c631cffb27c94eaaef7063f0cfed012e7db8 Mon Sep 17 00:00:00 2001 From: digimer Date: Tue, 6 Jun 2023 16:23:28 -0400 Subject: [PATCH] * Updated anvil-delete-server to accept '--server' and '--force' to allow direct deletion of a server without interacting with the menu system. This partially addresses issue #321. Signed-off-by: digimer --- man/anvil-delete-server.8 | 14 ++- tools/anvil-delete-server | 236 ++++++++++++++++++++++++-------------- 2 files changed, 163 insertions(+), 87 deletions(-) diff --git a/man/anvil-delete-server.8 b/man/anvil-delete-server.8 index 37d11263..93350b09 100644 --- a/man/anvil-delete-server.8 +++ b/man/anvil-delete-server.8 @@ -1,13 +1,13 @@ .\" Manpage for the Anvil! server removal tool .\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. -.TH anvil-delete-server "8" "August 02 2022" "Anvil! Intelligent Availability™ Platform" +.TH anvil-delete-server "8" "June 06 2023" "Anvil! Intelligent Availability™ Platform" .SH NAME anvil-delete-server \- This program deletes a server from an Anvil! sub-cluster. .SH SYNOPSIS .B anvil-delete-server \fI\, \/\fR[\fI\,options\/\fR] .SH DESCRIPTION -This deletes a server, running or stopped, from an Anvil! subcluster. The resource allocated to this server are removed and returned to the resource pool as well. +This deletes a server, running or stopped, from an Anvil! sub-cluster. The resource allocated to this server are removed and returned to the resource pool as well. .TP This action is permanent! .TP @@ -23,9 +23,17 @@ 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\-\-job-uuid\fR +\fB\-\-job-uuid\fR The program is normally run as a job, with data on how to configure the host defined in the job. This switch allows the running of a specific job. If this is not set, the program will search for a job that has not yet been picked up by another process. If found, that job UUID is used automatically. .IP +.SS "Commands:" +.TP +\fB\-\-force\fR +When used with \fB\-\-server\fR, no confirmation prompt will be shown. Use this with caution! +.TP +\fB\-\-server\fR +This is the server to be deleted. It can either be the name or UUID. If not provided, a list of servers on the Anvil! node this command is run from will be shown where you can select the one to delete. +.TP .SH AUTHOR Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. .SH "REPORTING BUGS" diff --git a/tools/anvil-delete-server b/tools/anvil-delete-server index 4f756eb3..c066c6f4 100755 --- a/tools/anvil-delete-server +++ b/tools/anvil-delete-server @@ -29,7 +29,10 @@ my $anvil = Anvil::Tools->new(); # Read switches (target ([user@]host[:port]) and the file with the target's password. If the password is # passed directly, it will be used. Otherwise, the password will be read from the database. -$anvil->Get->switches({list => ["job-uuid"], man => $THIS_FILE}); +$anvil->Get->switches({list => [ + "force", + "server", + "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 }}); @@ -91,6 +94,11 @@ if ($anvil->data->{switches}{'job-uuid'}) # Job data will be in $anvil->data->{jobs}{job_data} run_jobs($anvil); } +elsif ($anvil->data->{switches}{server}) +{ + # User specified what they want deleted. + confirm_server_delete($anvil); +} else { if (not $anvil->data->{sys}{anvil_uuid}) @@ -111,7 +119,6 @@ $anvil->nice_exit({exit_code => 0}); # Functions # ############################################################################################################# - # This actually provisions a VM. sub run_jobs { @@ -496,6 +503,38 @@ sub parse_job_data return(0); } +# This allows a user to specify the server they want deleted without going through the meny system. +sub confirm_server_delete +{ + my ($anvil) = @_; + + $anvil->Get->server_from_switch({ + debug => 2, + server => $anvil->data->{switches}{server}, + anvil_uuid => $anvil->data->{sys}{anvil_uuid}, + }); + + if (not $anvil->data->{switches}{server_name}) + { + # Not found. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0277", variables => { server => $anvil->data->{switches}{server} }}); + $anvil->nice_exit({exit_code => 1}); + + } + + # Ask the user to confirm, if needed. Note that this method requires '--force', not '-y' or '--Yes'. + if (not $anvil->data->{switches}{force}) + { + get_confirmation($anvil); + } + else + { + # They're forcing, save. + save_job($anvil); + } + + return(0); +} # This will ask the user to select a server. sub ask_for_server @@ -588,7 +627,23 @@ sub ask_for_server } } + $anvil->Get->server_from_switch({ + debug => 2, + server => $delete_uuid, + anvil_uuid => $anvil->data->{sys}{anvil_uuid}, + }); + # Ask the user to confirm. + get_confirmation($anvil); + + return(0); +} + +sub get_confirmation +{ + my ($anvil) = @_; + + my $delete_uuid = $anvil->data->{switches}{server_uuid}; my $server_name = $anvil->data->{servers}{server_uuid}{$delete_uuid}{server_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { delete_uuid => $delete_uuid, @@ -600,104 +655,117 @@ sub ask_for_server chomp $answer; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); - if (lc($answer) eq "yes") + if ($answer eq "Yes") { ### Save the job! - # Is the server running? - print $anvil->Words->string({key => "message_0213"})."\n"; - - $anvil->Database->get_anvils(); - my $hosts = []; - my $password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password}; - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; - if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}) + save_job($anvil); + } + else + { + # Abort. + print $anvil->Words->string({key => "message_0022"})."\n"; + $anvil->nice_exit({exit_code => 0}); + } + + return(0); +} + +sub save_job +{ + my ($anvil) = @_; + + # Is the server running? + print $anvil->Words->string({key => "message_0213"})."\n"; + + $anvil->Database->get_anvils(); + my $hosts = []; + my $anvil_uuid = $anvil->data->{sys}{anvil_uuid};; + my $password = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_password}; + my $server_name = $anvil->data->{switches}{server_name}; + my $server_uuid = $anvil->data->{switches}{server_uuid}; + my $delete_uuid = $server_uuid; + push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; + push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; + if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}) + { + push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; + } + my $server_host = ""; + foreach my $host_uuid (@{$hosts}) + { + if ($host_uuid eq $anvil->Get->host_uuid) { - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; + # This is us. + $anvil->Server->find({refresh => 0}); } - my $server_host = ""; - foreach my $host_uuid (@{$hosts}) + else { - if ($host_uuid eq $anvil->Get->host_uuid) - { - # This is us. - $anvil->Server->find({refresh => 0}); - } - else - { - # This is another machine. - my $target_ip = $anvil->Network->find_target_ip({host_uuid => $host_uuid}); - $anvil->Server->find({ - refresh => 0, - target => $target_ip, - password => $password, - }); - } + # This is another machine. + my $target_ip = $anvil->Network->find_target_ip({host_uuid => $host_uuid}); + $anvil->Server->find({ + refresh => 0, + target => $target_ip, + password => $password, + }); } - - my $host_name = ""; - my $host_uuid = ""; - if (exists $anvil->data->{server}{location}{$server_name}) + } + + my $host_name = ""; + my $host_uuid = ""; + if (exists $anvil->data->{server}{location}{$server_name}) + { + my $status = $anvil->data->{server}{location}{$server_name}{status}; + $host_name = $anvil->data->{server}{location}{$server_name}{host_name}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + status => $status, + host_name => $host_name, + }}); + if ($status eq "running") { - my $status = $anvil->data->{server}{location}{$server_name}{status}; - $host_name = $anvil->data->{server}{location}{$server_name}{host_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - status => $status, - host_name => $host_name, - }}); - if ($status eq "running") - { - $host_uuid = $anvil->Get->host_uuid_from_name({host_name => $host_name}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); - } + $host_uuid = $anvil->Get->host_uuid_from_name({host_name => $host_name}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); } - - # Now, we'll do the delete, unless we see the server running elsewhere. - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); - - my $job_host_uuid = ""; - if ($host_uuid) + } + + # Now, we'll do the delete, unless we see the server running elsewhere. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); + + my $job_host_uuid = ""; + if ($host_uuid) + { + $job_host_uuid = $host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); + if ($host_uuid eq $anvil->Get->host_uuid) { - $job_host_uuid = $host_uuid; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); - if ($host_uuid eq $anvil->Get->host_uuid) - { - # Running here - print $anvil->Words->string({key => "message_0216"})."\n"; - } - else - { - # Running on a peer. - print $anvil->Words->string({key => "message_0214", variables => { host_name => $host_name }})."\n"; - } + # Running here + print $anvil->Words->string({key => "message_0216"})."\n"; } else { - $job_host_uuid = $anvil->Get->host_uuid(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); - print $anvil->Words->string({key => "message_0215"})."\n"; + # Running on a peer. + print $anvil->Words->string({key => "message_0214", variables => { host_name => $host_name }})."\n"; } - - my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ - debug => 2, - job_command => $anvil->data->{path}{exe}{'anvil-delete-server'}.$anvil->Log->switches, - job_data => "server_uuid=".$delete_uuid, - job_name => "server::delete", - job_title => "job_0208", - job_description => "job_0209", - job_progress => 0, - job_host_uuid => $job_host_uuid, - }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); - - $anvil->nice_exit({exit_code => 0}); } else { - # Abort. - print $anvil->Words->string({key => "message_0022"})."\n"; - $anvil->nice_exit({exit_code => 0}); + $job_host_uuid = $anvil->Get->host_uuid(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); + print $anvil->Words->string({key => "message_0215"})."\n"; } - + + my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ + debug => 2, + job_command => $anvil->data->{path}{exe}{'anvil-delete-server'}.$anvil->Log->switches, + job_data => "server_uuid=".$delete_uuid, + job_name => "server::delete", + job_title => "job_0208", + job_description => "job_0209", + job_progress => 0, + job_host_uuid => $job_host_uuid, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); + + $anvil->nice_exit({exit_code => 0}); + return(0); }