* Fixed a bug where deleting ports from a fence device in an Install Manifest would not cause the fence methods to be removed from the associated cluster.

* Created Get->anvil_from_switch and Get->server_from_switch() (both need testing) that takes a string that could be either a name or UUID, figures out which it is, finds the entry in the DB and started the X_uuid and X_name switch variables.
* Started work on a second attempt at anvil-manage-server.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 2 years ago
parent 9556915cac
commit bde0b2e7ec
  1. 50
      Anvil/Tools/Cluster.pm
  2. 139
      Anvil/Tools/Get.pm
  3. 75
      man/anvil-manage-server.8
  4. 1
      share/words.xml
  5. 123
      tools/anvil-manage-server
  6. 5
      tools/striker-initialize-host

@ -1272,6 +1272,7 @@ sub check_stonith_config
{
my $delete_old = 0;
my $create_entry = 0;
my $dont_create = 0;
my $old_switches = {};
my $fence_uuid = $anvil->data->{manifests}{manifest_uuid}{$manifest_uuid}{parsed}{fences}{$device}{uuid};
my $fence_name = $anvil->data->{fences}{fence_uuid}{$fence_uuid}{fence_name};
@ -1337,6 +1338,8 @@ sub check_stonith_config
"old_switches->{$argument}" => $old_switches->{$argument},
}});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { port => $port }});
if ($port)
{
$port =~ s/"/\\"/g;
@ -1347,6 +1350,30 @@ sub check_stonith_config
"old_switches->{port}" => $old_switches->{port},
}});
}
else
{
# If the port is required but not defined, remove this.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"fence_data::${fence_agent}::parameters::port::required" => $anvil->data->{fence_data}{$fence_agent}{parameters}{port}{required},
port => $port,
}});
if (($anvil->data->{fence_data}{$fence_agent}{parameters}{port}{required}) && (not $port))
{
if (exists $anvil->data->{cib}{parsed}{cib}{resources}{primitive}{$stonith_name})
{
$delete_old = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_old => $delete_old }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0430", variables => { device => $stonith_name }});
}
else
{
# Don't create it.
$dont_create = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { dont_create => $dont_create }});
}
}
}
$pcs_add_command .= "op monitor interval=\"60\"";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
pcs_add_command => $pcs_add_command =~ /passw/ ? $anvil->Log->is_secure($pcs_add_command) : $pcs_add_command,
@ -1367,16 +1394,27 @@ sub check_stonith_config
}});
if ($old_entry ne $new_entry)
{
# If the port was removed, delete his entry.
if (not $port)
{
$delete_old = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_old => $delete_old }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0430", variables => { device => $stonith_name }});
}
else
{
# Changed, delete and recreate.
$delete_old = 1;
$create_entry = 1;
$create_entry = 1 if not $dont_create;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
delete_old => $delete_old,
create_entry => $create_entry,
}});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0121", variables => { device => $stonith_name }});
}
last;
}
@ -1391,7 +1429,7 @@ sub check_stonith_config
{
# Delete and recreate.
$delete_old = 1;
$create_entry = 1;
$create_entry = 1 if not $dont_create;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
delete_old => $delete_old,
create_entry => $create_entry,
@ -1400,7 +1438,7 @@ sub check_stonith_config
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0121", variables => { device => $stonith_name }});
}
}
else
elsif ((not $delete_old) && (not $dont_create))
{
# No existing entry, add a new one.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0122", variables => { device => $stonith_name }});
@ -1437,10 +1475,10 @@ sub check_stonith_config
return(1);
}
$something_changed->{$node_name} = 1;
$something_changed->{$node_name} = 1 if not $delete_old;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
}
if ($create_entry)
if (($create_entry) && (not $dont_create))
{
# Create.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0120", variables => { device => $stonith_name }});
@ -1464,7 +1502,7 @@ sub check_stonith_config
return(1);
}
$something_changed->{$node_name} = 1;
$something_changed->{$node_name} = 1 if not $delete_old;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "something_changed->{$node_name}" => $something_changed->{$node_name} }});
}
}

@ -17,6 +17,7 @@ our $VERSION = "3.0.0";
my $THIS_FILE = "Get.pm";
### Methods;
# anvil_from_switch
# anvil_name_from_uuid
# anvil_version
# available_resources
@ -34,6 +35,7 @@ my $THIS_FILE = "Get.pm";
# kernel_release
# md5sum
# os_type
# server_from_switch
# server_uuid_from_name
# switches
# trusted_hosts
@ -107,6 +109,69 @@ sub parent
# Public methods #
#############################################################################################################
=head2 anvil_from_switch
This takes a C<< switches::anvil >> switch, which could be a name or UUID, and tries to find the associated Anvil!. If/when found, C<< switches::anvil_uuid >> and C<< switches::anvil_name >> are set accordingly.
If no match is found, two empty strings are returned. If it is found, the Anvil! name is returned first, and the Anvil! UUID is returned after. If there is a problemm C<< !!error!! >> is returned.
Parameters;
=head3 anvil (optional, required, optional if 'switches::anvil' used if set)
This is the Anvil! name or UUID that we're looking for.
=cut
sub anvil_from_switch
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Get->anvil_from_switch()" }});
my $anvil_string = defined $parameter->{anvil} ? $parameter->{anvil} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_string => $anvil_string,
}});
if ((not $anvil_string) && ($anvil->data->{switches}{'anvil'}))
{
$anvil_string = $anvil->data->{switches}{'anvil'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_string => $anvil_string }});
}
if (not $anvil_string)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Get->anvil_from_switch()", parameter => "anvil" }});
return("!!error!!", "");
}
$anvil->Database->get_anvils({debug => $debug});
$anvil->data->{switches}{anvil_name} = "" if not exists $anvil->data->{switches}{anvil_name};
$anvil->data->{switches}{anvil_uuid} = "" if not exists $anvil->data->{switches}{anvil_uuid};
if (exists $anvil->data->{anvils}{anvil_uuid}{$anvil_string})
{
# Found it by UUID.
$anvil->data->{switches}{anvil_name} = $anvil->data->{anvils}{anvil_uuid}{$anvil_string}{anvil_name};
$anvil->data->{switches}{anvil_uuid} = $anvil_string;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"switches::anvil_name" => $anvil->data->{switches}{anvil_name},
"switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid},
}});
}
elsif (exists $anvil->data->{anvils}{anvil_uuid}{$anvil_string})
{
$anvil->data->{switches}{anvil_name} = $anvil_string;
$anvil->data->{switches}{anvil_uuid} = $anvil->data->{anvils}{anvil_uuid}{$anvil_string}{anvil_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"switches::anvil_name" => $anvil->data->{switches}{anvil_name},
"switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid},
}});
}
return($anvil->data->{switches}{anvil_name}, $anvil->data->{switches}{anvil_uuid});
}
=head2 anvil_name_from_uuid
@ -129,7 +194,9 @@ sub anvil_name_from_uuid
my $anvil_name = "";
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { anvil_uuid => $anvil_uuid }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
}});
if (not $anvil_uuid)
{
@ -2032,6 +2099,76 @@ sub os_type
}
=head2 server_from_switch
This takes a C<< switches::server >> switch, which could be a name or UUID, and tries to find the associated server. If/when found, C<< switches::server_uuid >> and C<< switches::server_name >> are set accordingly.
If no match is found, two empty strings are returned. If it is found, the server's name is returned first, and the server's UUID is returned after. If there is a problemm C<< !!error!! >> is returned.
Parameters;
=head4 anvil_uuid (optional)
If specified, the server will be searched for on the specified Anvil! only. If not specified, all Anvil! nodes are searched, with the first match being returned. This should only be needed in the unlikely event that two or more servers share the same name across different Anvil! systems (something that should not be possible).
=head3 server (optional, required, optional if 'switches::server' used if set)
This is the server name or UUID that we're looking for.
=cut
sub server_from_switch
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Get->server_from_switch()" }});
my $server_string = defined $parameter->{server} ? $parameter->{server} : "";
my $anvil_uuid = defined $parameter->{anvil_uuid} ? $parameter->{anvil_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
anvil_uuid => $anvil_uuid,
server_string => $server_string,
}});
if ((not $server_string) && ($anvil->data->{switches}{'anvil'}))
{
$server_string = $anvil->data->{switches}{'anvil'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_string => $server_string }});
}
if (not $server_string)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Get->server_from_switch()", parameter => "server" }});
return("!!error!!", "");
}
$anvil->Database->get_servers({debug => $debug});
$anvil->data->{switches}{server_name} = "" if not exists $anvil->data->{switches}{server_name};
$anvil->data->{switches}{server_uuid} = "" if not exists $anvil->data->{switches}{server_uuid};
if (exists $anvil->data->{servers}{server_uuid}{$server_string}{server_name})
{
# Found it by UUID.
$anvil->data->{switches}{server_name} = $anvil->data->{anvils}{server_uuid}{$server_string}{server_name};
$anvil->data->{switches}{server_uuid} = $server_string;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"switches::server_name" => $anvil->data->{switches}{server_name},
"switches::server_uuid" => $anvil->data->{switches}{server_uuid},
}});
}
elsif (exists $anvil->data->{anvils}{server_uuid}{$server_string})
{
$anvil->data->{switches}{server_name} = $server_string;
$anvil->data->{switches}{server_uuid} = $anvil->data->{anvils}{server_uuid}{$server_string}{server_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"switches::server_name" => $anvil->data->{switches}{server_name},
"switches::server_uuid" => $anvil->data->{switches}{server_uuid},
}});
}
return($anvil->data->{switches}{server_name}, $anvil->data->{switches}{server_uuid});
}
=head2 server_uuid_from_name
This takes a server name and returns the server's uuid (as recorded in the C<< servers >> table). If the entry is not found, an empty string is returned. If there is a problem, C<< !!error!! >> will be returned.

@ -0,0 +1,75 @@
.\" Manpage for the Alteeve! anvil-manage-server tool
.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions.
.TH anvil-manage-server "8" "October 19 2022" "Anvil! Intelligent Availability™ Platform"
.SH NAME
anvil-manage-server \- Tool used to manage a server running on an Anvil! cluster.
.SH SYNOPSIS
.B anvil-manage-server
\fI\,<command> \/\fR[\fI\,options\/\fR]
.SH DESCRIPTION
anvil-manage-server \- This tool allow the management of a server's hardware.
.TP
.SH OPTIONS
.TP
\-?, \-h, \fB\-\-help\fR
Show this man page.
.TP
\-d, \fB\-\-job-uuid\fR
This is the jobs -> job_uuid of the job to run, if it exists.
.TP
\fB\-\-log-secure\fR
When logging, record sensitive data, like passwords.
.TP
\fB\-v\fR, \fB\-vv\fR, \fB\-vvv\fR
Set the log level for this run to 1, 2 or 3 (higher == more verbose).
.TP
.SS "Commands:"
.TP
\-k, \fB\-\-anvil\fR <name or uuid>
If specified, and \fBserver\fR is not specified, this will list the servers running on the Anvil! system currently. If, in the unlikely event that two servers exist on different Anvil! systems but with the same name, this will help identify which server you want to work on.
.TP
\-k, \fB\-\-server\fR <name or uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
.TP
\-k, \fB\-\-\fR <uuid>
$anvil->data->{switches}{boot} = ""; # This is a comma-separated list of ordered boot devices
$anvil->data->{switches}{cores} = ""; # This sets the server to use this number of CPU cores.
$anvil->data->{switches}{drive} = ""; # drive being modified (insert/eject ISO, growing drive)
$anvil->data->{switches}{eject} = ""; # This will eject whatever ISO (if any) in the '--drive'.
$anvil->data->{switches}{'expand-to'} = ""; # When the drive is a disk (backed by a DRBD resource), this is the new desired size to grow to.
$anvil->data->{switches}{insert} = ""; # This is the ISO to insert into the --drive
$anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{ram} = ""; # This is the amount of RAM to set the server to use.
$anvil->data->{switches}{server} = ""; # server name or uuid
$anvil->data->{switches}{y} = ""; # Don't prompt for confirmation. Only useful when there isn't a job UUID.
.IP
.SH AUTHOR
Written by Madison Kelly, Alteeve staff and the Anvil! project contributors.
.SH "REPORTING BUGS"
Report bugs to users@clusterlabs.org

@ -1417,6 +1417,7 @@ Note: This is a permanent action! If you protect this server again later, a full
<key name="job_0419">The server: [#!variable!server!#] was found to be running outside the cluster. Asking it to shut down now.</key>
<key name="job_0428">The server: [#!variable!server!#] is still running two minutes after asking it to stop. It might have woken up on the first press and ignored the shutdown request (Hi Windows). Pressing the poewr button again.</key>
<key name="job_0429">Copying the Long-throw (drbd proxy) license file: [#!variable!file!#] into place.</key>
<key name="job_0430">The fence device: [#!variable!device!#] no longer has a port associated with it, will remove it.</key>
<!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key>

@ -29,31 +29,15 @@ $| = 1;
my $anvil = Anvil::Tools->new();
$anvil->data->{switches}{anvil} = ""; # This is the Anvil! Name or UUID being worked on.
$anvil->data->{switches}{boot} = ""; # This is a comma-separated list of ordered boot devices
$anvil->data->{switches}{cores} = ""; # This sets the server to use this number of CPU cores.
$anvil->data->{switches}{drive} = ""; # drive being modified (insert/eject ISO, growing drive)
$anvil->data->{switches}{eject} = ""; # This will eject whatever ISO (if any) in the '--drive'.
$anvil->data->{switches}{'expand-to'} = ""; # When the drive is a disk (backed by a DRBD resource), this is the new desired size to grow to.
$anvil->data->{switches}{insert} = ""; # This is the ISO to insert into the --drive
$anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{ram} = ""; # This is the amount of RAM to set the server to use.
$anvil->data->{switches}{server} = ""; # server name or uuid
$anvil->data->{switches}{y} = ""; # Don't prompt for confirmation. Only useful when there isn't a job UUID.
$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::boot' => $anvil->data->{switches}{boot},
'switches::cores' => $anvil->data->{switches}{cores},
'switches::drive' => $anvil->data->{switches}{drive},
'switches::eject' => $anvil->data->{switches}{eject},
'switches::expand-to' => $anvil->data->{switches}{'expand-to'},
'switches::insert' => $anvil->data->{switches}{insert},
'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'},
'switches::ram' => $anvil->data->{switches}{ram},
'switches::server' => $anvil->data->{switches}{server},
'switches::y' => $anvil->data->{switches}{y},
}});
### TODO: Remove this before final release
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
##########################################
# Read switches (target ([user@]host[:port]) and the file with the target's password.
$anvil->Get->switches({list => ["anvil", "boot", "cores", "drive", "eject", "expand-to", "insert", "ram", "server", "y"], 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__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }});
# Connect to the database(s). If we have no connections, we'll proceed anyway as one of the 'run_once' tasks
# is to setup the database server.
@ -94,12 +78,16 @@ if ($anvil->data->{switches}{'job-uuid'})
}
else
{
process_interactive($anvil);
### TODO: Old way
# Interactive!
$anvil->data->{new_config}{cpu}{sockets} = "";
$anvil->data->{new_config}{cpu}{cores} = "";
$anvil->data->{new_config}{ram}{'bytes'} = "";
$anvil->data->{old_config}{ram}{'bytes'} = "";
interactive_question($anvil);
# $anvil->data->{new_config}{cpu}{sockets} = "";
# $anvil->data->{new_config}{cpu}{cores} = "";
# $anvil->data->{new_config}{ram}{'bytes'} = "";
# $anvil->data->{old_config}{ram}{'bytes'} = "";
# interactive_question($anvil);
}
$anvil->nice_exit({exit_code => 0});
@ -109,6 +97,81 @@ $anvil->nice_exit({exit_code => 0});
# Functions #
#############################################################################################################
sub process_interactive
{
my ($anvil) = @_;
# Preset values.
$anvil->data->{target_server}{anvil_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid};
$anvil->data->{target_server}{anvil_name} = "" if not exists $anvil->data->{target_server}{anvil_uuid};
$anvil->data->{target_server}{server_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid};
$anvil->data->{target_server}{server_uuid} = "" if not exists $anvil->data->{target_server}{anvil_uuid};
$anvil->data->{target_server}{server_state} = "" if not exists $anvil->data->{target_server}{server_state};
$anvil->data->{target_server}{anvil_description} = "" if not exists $anvil->data->{target_server}{anvil_description};
$anvil->data->{target_server}{anvil_node1_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_node1_host_uuid};
$anvil->data->{target_server}{anvil_node1_host_name} = "" if not exists $anvil->data->{target_server}{anvil_node1_host_name};
$anvil->data->{target_server}{anvil_node2_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_node2_host_uuid};
$anvil->data->{target_server}{anvil_node2_host_name} = "" if not exists $anvil->data->{target_server}{anvil_node2_host_name};
$anvil->data->{target_server}{anvil_dr1_host_uuid} = "" if not exists $anvil->data->{target_server}{anvil_dr1_host_uuid};
$anvil->data->{target_server}{anvil_dr1_host_name} = "" if not exists $anvil->data->{target_server}{anvil_dr1_host_name};
$anvil->data->{new_config}{cpu}{sockets} = "";
$anvil->data->{new_config}{cpu}{cores} = "";
$anvil->data->{new_config}{ram}{'bytes'} = "";
$anvil->data->{old_config}{ram}{'bytes'} = "";
# Did they specify an Anvil! system?
if ($anvil->data->{switches}{anvil})
{
$anvil->Get->anvil_from_switch({anvil => $anvil->data->{switches}{anvil}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"switches::anvil_name" => $anvil->data->{switches}{anvil_name},
"switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid},
}});
}
# Did they specify a server?
if ($anvil->data->{switches}{server})
{
$anvil->Get->server_from_switch({server => $anvil->data->{switches}{server}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"switches::anvil_name" => $anvil->data->{switches}{anvil_name},
"switches::anvil_uuid" => $anvil->data->{switches}{anvil_uuid},
}});
}
if (not $anvil->data->{target_server}{anvil_uuid})
{
}
return(0);
}
### NOTE: Old functions, likely to be removed ###
sub run_jobs
{
my ($anvil) = @_;

@ -30,11 +30,6 @@ $| = 1;
my $anvil = Anvil::Tools->new();
### TODO: Remove this before final release
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
##########################################
# Read switches (target ([user@]host[:port]) and the file with the target's password.
$anvil->Get->switches({list => ["enterprise-uuid", "host-ip-address", "password", "rh-password", "rh-user", "ssh-port", "target", "type"], man => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});

Loading…
Cancel
Save