#!/usr/bin/perl # # This provisions a new virtual machine server. It handles creating the logical volumes, DRBD resources, # verifies the needed files are ready, creates the provision script, begins the installation, and adds the # new server to pacemaker. # # Exit codes; # 0 = Normal exit. # 1 = Any problem that causes an early exit. # use strict; use warnings; use Anvil::Tools; require POSIX; use Term::Cap; 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(); # 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 => [ "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 }}); $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, secure => 0, key => "log_0132"}); if (not $anvil->data->{sys}{database}{connections}) { # No databases, update the job, sleep for a bit and then exit. The daemon will pick it up and try # again after we exit. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, 'print' => 1, level => 0, priority => "err", key => "error_0218"}); sleep 10; $anvil->nice_exit({exit_code => 1}); } ### NOTE: This must be run on a Node or DR host and will only delete servers on the same Anvil!. # This job is loaded on the node hosting the VM, or the primary node is the server isn't running. The first # node to get this job will shut the server down and remove it from the cluster using 'pcs'. Once off and # removed from the cluster, the server is marked as 'DELETED' and then a job is registered with the peer node # and, if available, the DR host. At this point, the job acts the same regardless of the host. The DRBD # resource will stopped and then have it's metadata wiped, The LV backing the device will be deleted next. $anvil->data->{sys}{anvil_uuid} = $anvil->Cluster->get_anvil_uuid(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'sys::anvil_uuid' => $anvil->data->{sys}{anvil_uuid} }}); # If we still don't have a job-uuit, go into interactive mode. if ($anvil->data->{switches}{'job-uuid'}) { # Load the job data. $anvil->Job->clear(); $anvil->Job->get_job_details(); $anvil->Job->update_progress({ progress => 1, job_picked_up_by => $$, job_picked_up_at => time, message => "message_0217", }); # Are we in an Anvil! system or are we a DR host? my $host_type = $anvil->Get->host_type(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); if ((not $anvil->data->{sys}{anvil_uuid}) && ($host_type ne "dr")) { # We're not in an Anvil!. if ($anvil->data->{switches}{'job-uuid'}) { # Mark the job as failed. $anvil->Job->update_progress({ progress => 100, message => "error_0217", job_status => "failed", }); } # Log an exit. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, 'print' => 1, level => 0, priority => 'err', key => "error_0217"}); $anvil->nice_exit({exit_code => 1}); } # 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}) { # We can't do anything, exit. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, 'print' => 1, level => 0, priority => 'err', key => "error_0217"}); $anvil->nice_exit({exit_code => 1}); } # Interactive! ask_for_server($anvil); } $anvil->nice_exit({exit_code => 0}); ############################################################################################################# # Functions # ############################################################################################################# # This actually provisions a VM. sub run_jobs { my ($anvil) = @_; # This parses the jobs::job_data intp variables. parse_job_data($anvil); my $host_type = $anvil->Get->host_type(); my $server_uuid = $anvil->data->{job}{server_uuid}; my $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type, server_uuid => $server_uuid, server_name => $server_name, }}); # Before we start, we need to know if this server is on DR hosts. To do this, we'll parse the DRBD # config file and look for DR hosts. $anvil->Database->get_hosts({debug => 2}); $anvil->DRBD->gather_data({debug => 2}); foreach my $peer (sort {$a cmp $b} keys %{$anvil->data->{new}{resource}{$server_name}{peer}}) { my $peer_host_uuid = $anvil->Database->get_host_uuid_from_string({debug => 2, string => $peer}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer => $peer, peer_host_uuid => $peer_host_uuid, }}); if (($peer_host_uuid) && (exists $anvil->data->{hosts}{host_uuid}{$peer_host_uuid})) { my $host_type = $anvil->data->{hosts}{host_uuid}{$peer_host_uuid}{host_type}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); if ($host_type eq "dr") { $anvil->data->{dr_hosts}{$peer_host_uuid} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "dr_hosts::${peer_host_uuid}" => $anvil->data->{dr_hosts}{$peer_host_uuid}, }}); } } } if (not $anvil->data->{job}{peer_mode}) { # Remove the server from pacemaker (stopping it, if necessary). remove_from_pacemaker($anvil); } $anvil->Job->update_progress({ progress => 25, message => "job_0222,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0222", variables => { server_name => $server_name }}); $anvil->Job->update_progress({ progress => 50, message => "job_0213", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0213"}); ### NOTE: If we're a DR host, and the server wasn't used here, this is expected to fail # Delete the DRBD resource and backing storage my $problem = $anvil->DRBD->delete_resource({debug => 2, resource => $server_name}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if (($problem) && ($host_type eq "node")) { # Something went wrong $anvil->Job->update_progress({ progress => 100, message => "error_0228,!!resource!".$server_name."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0228", variables => { resource => $server_name }}); } $anvil->Job->update_progress({ progress => 60, message => "job_0214", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0214"}); # Make sure the server is flagged as DELETEd. $anvil->Database->get_servers(); my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_state => $server_state }}); if ($server_state ne "DELETED") { my $query = " UPDATE servers SET server_state = 'DELETED', modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE server_uuid = ".$anvil->Database->quote($server_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); $anvil->Job->update_progress({ progress => 70, message => "job_0215", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0215"}); } # Delete the XML definition file. my $resource_file = $anvil->data->{path}{directories}{shared}{definitions}."/".$server_name.".xml"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { resource_file => $resource_file }}); if (-f $resource_file) { # Remove it. $anvil->Job->update_progress({ progress => 80, message => "job_0220,!!file!".$resource_file."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0220", variables => { file => $resource_file }}); unlink $resource_file; } # Call scan-cluster, scan-network and scan-server to make sure the databases are updated. $anvil->Job->update_progress({ progress => 90, message => "job_0464", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0464"}); foreach my $agent ("scan-cluster", "scan-network", "scan-server") { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0740", variables => { agent => $agent }}); my $shell_call = $anvil->data->{path}{directories}{scan_agents}."/".$agent."/".$agent.$anvil->Log->switches(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); } # Make sure drbd-fence attributes are deleted for this server. clear_cib($anvil); # We're done $anvil->Job->update_progress({ progress => 100, message => "job_0216", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0216"}); return(0); } # Make sure drbd-fence attributes are deleted for this server. sub clear_cib { my ($anvil) = @_; my $problem = $anvil->Cluster->parse_cib({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if ($problem) { # Not in a cluster return(0); } my $server_uuid = $anvil->data->{job}{server_uuid}; my $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; my $host_name = $anvil->Get->host_name; my $short_host_name = $anvil->Get->short_host_name; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_uuid => $server_uuid, server_name => $server_name, host_name => $host_name, short_host_name => $short_host_name, }}); # Find attributes foreach my $node_id (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{cib}{node_state}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { node_id => $node_id }}); foreach my $attribute_id (sort {$a cmp $b} keys %{$anvil->data->{cib}{parsed}{cib}{node_state}{$node_id}}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { attribute_id => $attribute_id }}); if ($attribute_id =~ /^drbd-fenced_(.*)$/) { my $this_server_name = $1; my $state = $anvil->data->{cib}{parsed}{cib}{node_state}{$node_id}{$attribute_id}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { this_server_name => $server_name, 'state' => $state, }}); if ($this_server_name eq $server_name) { # Stale attribute, remove it! my $node_name = $anvil->data->{cib}{parsed}{configuration}{nodes}{$node_id}{uname}; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0329", variables => { attribute => $attribute_id, node_name => $node_name, node_id => $node_id, }}); my $shell_call = $anvil->data->{path}{exe}{pcs}." node attribute ".$node_name." ".$attribute_id."="; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output, return_code => $return_code, }}); } } } } return(0); } # This checks to see if the server is running and, if so, stops it. Once stopped, the resource is deleted. sub remove_from_pacemaker { my ($anvil) = @_; my $server_uuid = $anvil->data->{job}{server_uuid}; my $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_uuid => $server_uuid, server_name => $server_name, }}); # Sanity checks passed $anvil->Job->update_progress({ progress => 10, message => "job_0210,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0210", variables => { server_name => $server_name }}); if (not $anvil->data->{cib}{parsed}{data}{server}{$server_name}) { # Server is already out of the cluster. $anvil->Job->update_progress({ progress => 20, message => "job_0221,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0211", variables => { server_name => $server_name }}); # Force the server off now, just in case it's running outside the cluster $anvil->Job->update_progress({ progress => 25, message => "job_0223,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0223", variables => { server_name => $server_name }}); my $success = $anvil->Server->shutdown_virsh({ debug => 2, force => 1, server => $server_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { success => $success }}); if (not $success) { # Failed to stop $anvil->Job->update_progress({ progress => 100, message => "error_0223,!!server_name!".$server_name."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0223", variables => { server_name => $server_name }}); $anvil->nice_exit({exit_code => 1}); } } else { # As we're going to delete the server, we won't wait. We'll come back here and destroy the # server if it's still running. if ($anvil->data->{cib}{parsed}{data}{server}{$server_name}{status} ne "off") { my $problem = $anvil->Cluster->shutdown_server({ debug => 2, server => $server_name, 'wait' => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if ($problem) { # Failed to stop. $anvil->Job->update_progress({ progress => 100, message => "error_0223,!!server_name!".$server_name."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0223", variables => { server_name => $server_name }}); $anvil->nice_exit({exit_code => 1}); } # Force the server off now. $anvil->Job->update_progress({ progress => 20, message => "job_0223,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0223", variables => { server_name => $server_name }}); my $success = $anvil->Server->shutdown_virsh({ debug => 2, force => 1, server => $server_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { success => $success }}); if (not $success) { # Failed to stop $anvil->Job->update_progress({ progress => 100, message => "error_0223,!!server_name!".$server_name."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0223", variables => { server_name => $server_name }}); $anvil->nice_exit({exit_code => 1}); } # Server is off now. $anvil->Job->update_progress({ progress => 25, message => "job_0211,!!server_name!".$server_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0211", variables => { server_name => $server_name }}); } # Delete the resource. my $problem = $anvil->Cluster->delete_server({debug => 2, server_name => $server_name}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if ($problem) { # Something went wrong $anvil->Job->update_progress({ progress => 100, message => "error_0227,!!server_name!".$server_name."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0227", variables => { server_name => $server_name }}); $anvil->nice_exit({exit_code => 1}); } } # Register the job with the peers. my $anvil_uuid = $anvil->data->{sys}{anvil_uuid}; my $peers = []; if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid} eq $anvil->Get->host_uuid) { # We're node 1 push @{$peers}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid} } else { # We're node 2 push @{$peers}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid} } if (exists $anvil->data->{dr_hosts}) { foreach my $peer_host_uuid (keys %{$anvil->data->{dr_hosts}}) { push @{$peers}, $peer_host_uuid; } } my $progress = 30; foreach my $host_uuid (@{$peers}) { 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=".$server_uuid."\npeer_mode=true", job_name => "server::delete", job_title => "job_0208", job_description => "job_0209", job_progress => 0, job_host_uuid => $host_uuid, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); my $host_name = $anvil->Get->host_name_from_uuid({host_uuid => $host_uuid}); $anvil->Job->update_progress({ progress => $progress, message => "job_0212,!!host_name!".$host_name."!!", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "job_0212", variables => { host_name => $host_name }}); $progress += 10; } return(0); } # This parses and verifies the job data sub parse_job_data { my ($anvil) = @_; $anvil->data->{job}{server_uuid} = ""; $anvil->data->{job}{peer_mode} = 0; foreach my $line (split/\n/, $anvil->data->{jobs}{job_data}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); if ($line =~ /server_uuid=(.*)$/) { $anvil->data->{job}{server_uuid} = $1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::server_uuid' => $anvil->data->{job}{server_uuid} }}); } if ($line =~ /peer_mode=true/) { $anvil->data->{job}{peer_mode} = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'job::peer_mode' => $anvil->data->{job}{peer_mode} }}); } } # Did we get a server UUID? if (not $anvil->data->{job}{server_uuid}) { $anvil->Job->update_progress({ progress => 100, message => "error_0219,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0219", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); $anvil->nice_exit({exit_code => 1}); } # Does the server UUID match to a server? $anvil->Database->get_servers(); my $server_uuid = $anvil->data->{job}{server_uuid}; if (not exists $anvil->data->{servers}{server_uuid}{$server_uuid}) { # Server UUID is invalid $anvil->Job->update_progress({ progress => 100, message => "error_0220,!!server_uuid!".$server_uuid."!!", job_status => "failed", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0220", variables => { server_uuid => $server_uuid }}); $anvil->nice_exit({exit_code => 1}); } my $host_type = $anvil->Get->host_type(); if ($host_type eq "node") { my $problem = $anvil->Cluster->parse_cib({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); if ($problem) { # The cluster isn't running, sleep and exit. $anvil->Job->update_progress({ progress => 10, message => "error_0222", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0222"}); sleep 10; $anvil->nice_exit({exit_code => 1}); } elsif (not $anvil->data->{cib}{parsed}{'local'}{ready}) { # We're not a full member (yet) $anvil->Job->update_progress({ progress => 10, message => "error_0238", }); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => 'err', key => "error_0238"}); sleep 10; $anvil->nice_exit({exit_code => 1}); } } 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 { my ($anvil) = @_; my $termios = new POSIX::Termios; $termios->getattr; my $ospeed = $termios->getospeed; my $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed }; $terminal->Trequire(qw/ce ku kd/); my $anvil_uuid = $anvil->data->{sys}{anvil_uuid}; my $anvil_name = $anvil->Cluster->get_anvil_name({anvil_uuid => $anvil_uuid}); my $retry = 0; my $delete_uuid = ""; while(1) { print $terminal->Tputs('cl'); $anvil->Database->get_servers(); my $servers = []; my $position = 0; my $server_list = ""; print $anvil->Words->string({key => "message_0208", variables => { anvil_name => $anvil_name }})."\n"; foreach my $server_name (sort {$a cmp $b} keys %{$anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}}) { my $server_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$server_name}{server_uuid}; my $server_state = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 's1:server_name' => $server_name, 's2:server_uuid' => $server_uuid, 's3:server_state' => $server_state, }}); next if $server_state eq "DELETED"; # We want to start the list at '1', so we'll bump the position before generating an entry, # and subtract 1 from the user's answer later. $servers->[$position] = $server_uuid; $position++; $server_list .= $position.") ".$server_name."\n"; } if (not $position) { # No servers on this Anvil!. print $anvil->Words->string({key => "message_0209"})."\n"; $anvil->nice_exit({exit_code => 0}); } print $server_list."\n";; if ($retry) { print $anvil->Words->string({key => "message_0211"})."\n\n"; } print $anvil->Words->string({key => "message_0210"})." "; my $answer = ; chomp $answer; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); if ($answer =~ /\D/) { # Did the user type the name? if ((exists $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}) && ($anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}{server_uuid})) { # Specified by name. $delete_uuid = $anvil->data->{servers}{anvil_uuid}{$anvil_uuid}{server_name}{$answer}{server_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { delete_uuid => $delete_uuid }}); } } elsif ($answer =~ /^\d+$/) { my $index = $answer - 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'index' => $index }}); if ((exists $servers->[$index]) && ($servers->[$index])) { $delete_uuid = $servers->[$index]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { delete_uuid => $delete_uuid }}); } } if ($delete_uuid) { last; } else { $retry = 1; } } $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, server_name => $server_name, }}); print "\n".$anvil->Words->string({key => "message_0212", variables => { server_name => $server_name }})." "; my $answer = ; chomp $answer; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { answer => $answer }}); if ($answer eq "Yes") { ### Save the job! 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; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid, server_name => $server_name, server_uuid => $server_uuid, delete_uuid => $delete_uuid, }}); if ((not $server_name) && (exists $anvil->data->{servers}{server_uuid}{$server_uuid}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{server_name})) { $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_name => $server_name }}); } # Find the server on hosts. my $server_host_name = $anvil->Server->locate({ debug => 2, server_name => $server_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_name => $server_host_name }}); foreach my $short_host_name (sort {$a cmp $b} keys %{$anvil->data->{server_location}{host}}) { my $host_uuid = $anvil->Database->get_host_uuid_from_string({string => $short_host_name}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { short_host_name => $short_host_name, host_uuid => $host_uuid, }}); my $exists = 0; if (($anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{file_definition}) or ($anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{drbd_config})) { $exists = 1; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'exists' => $exists }}); if (($exists) or ($host_uuid eq $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}) or ($host_uuid eq $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid})) { push @{$hosts}, $host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); } } # If the server was found to be running, the host will be returned. my $server_host_uuid = ""; if ($server_host_name) { $server_host_uuid = $anvil->Get->host_uuid_from_name({host_name => $server_host_name}); } # Now, we'll do the delete, unless we see the server running elsewhere. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_uuid => $server_host_uuid }}); my $job_host_uuid = ""; if ($server_host_uuid) { $job_host_uuid = $server_host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); if ($server_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 => $server_host_name }})."\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"; } 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); }