741bcfa908
Signed-off-by: digimer <mkelly@alteeve.ca>
870 lines
31 KiB
Perl
Executable File
870 lines
31 KiB
Perl
Executable File
#!/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 = <STDIN>;
|
|
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 = <STDIN>;
|
|
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);
|
|
}
|