* Fixed a bug where Tools.pm->_anvil_version() and Get->host_uuid() were storing values in the wrong $anvil hash.

* Fixed a bug where Get->host_uuid() wasn't reading from the host.uuid file.
* Updated Remote->call() to record a target's fingerprint when needed.
* The ocf:alteeve:server resource agent now properly stopps a server and the corresponding DRBD resource.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent b56fbf923c
commit 7e4a170382
  1. 22
      Anvil/Tools.pm
  2. 62
      Anvil/Tools/Get.pm
  3. 18
      Anvil/Tools/Remote.pm
  4. 55
      ocf/alteeve/server
  5. 6
      share/words.xml

@ -178,14 +178,18 @@ sub new
if (ref($parameter) eq "HASH") if (ref($parameter) eq "HASH")
{ {
# Local parameters... # Local parameters...
if ($parameter->{debug}) if ($parameter->{log_level})
{ {
$debug = $parameter->{debug}; $anvil->Log->level({set => $parameter->{log_level}});
} }
if ($parameter->{log_secure}) if ($parameter->{log_secure})
{ {
$anvil->Log->secure({set => $parameter->{log_secure}}); $anvil->Log->secure({set => $parameter->{log_secure}});
} }
if ($parameter->{debug})
{
$debug = $parameter->{debug};
}
} }
elsif ($parameter) elsif ($parameter)
{ {
@ -194,12 +198,6 @@ sub new
exit(1); exit(1);
} }
# If the user passed a custom log level, sit it now.
if ($parameter->{log_level})
{
$anvil->Log->level({set => $parameter->{log_level}});
}
# This will help clean up if we catch a signal. # This will help clean up if we catch a signal.
$SIG{INT} = sub { $anvil->catch_sig({signal => "INT"}); }; $SIG{INT} = sub { $anvil->catch_sig({signal => "INT"}); };
$SIG{TERM} = sub { $anvil->catch_sig({signal => "TERM"}); }; $SIG{TERM} = sub { $anvil->catch_sig({signal => "TERM"}); };
@ -612,14 +610,14 @@ sub _anvil_version
my $self = shift; my $self = shift;
my $anvil = $self; my $anvil = $self;
$anvil->data->{HOST}{ANVIL_VERSION} = "" if not defined $anvil->data->{HOST}{ANVIL_VERSION}; $anvil->{HOST}{ANVIL_VERSION} = "" if not defined $anvil->{HOST}{ANVIL_VERSION};
if ($anvil->data->{HOST}{ANVIL_VERSION} eq "") if ($anvil->{HOST}{ANVIL_VERSION} eq "")
{ {
# Try to read the local Anvil! version. # Try to read the local Anvil! version.
$anvil->data->{HOST}{ANVIL_VERSION} = $anvil->Get->anvil_version(); $anvil->{HOST}{ANVIL_VERSION} = $anvil->Get->anvil_version();
} }
return($anvil->data->{HOST}{ANVIL_VERSION}); return($anvil->{HOST}{ANVIL_VERSION});
} }
=head2 _hostname =head2 _hostname

@ -524,44 +524,52 @@ sub host_uuid
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $set = defined $parameter->{set} ? $parameter->{set} : ""; my $set = defined $parameter->{set} ? $parameter->{set} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { set => $set }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
set => $set,
'HOST::UUID' => $anvil->{HOST}{UUID},
}});
if ($set) if ($set)
{ {
$anvil->data->{HOST}{UUID} = $set; $anvil->{HOST}{UUID} = $set;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->data->{HOST}{UUID} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->{HOST}{UUID} }});
} }
elsif (not $anvil->data->{HOST}{UUID}) elsif (not $anvil->{HOST}{UUID})
{ {
# Read dmidecode if I am root, otherwise, read the cache. # Read /etc/anvil/host.uuid if it exists. If not, and if we're root, we'll create that file
# using the UUID from dmidecode.
my $uuid = ""; my $uuid = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { '$<' => $<, '$>' => $> }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
if (($< == 0) or ($> == 0)) '$<' => $<,
'$>' => $>,
'path::data::host_uuid' => $anvil->data->{path}{data}{host_uuid},
}});
if (-e $anvil->data->{path}{data}{host_uuid})
{
# Read the UUID in
$uuid = $anvil->Storage->read_file({debug => $debug, file => $anvil->data->{path}{data}{host_uuid}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
}
elsif (($< == 0) or ($> == 0))
{ {
# Create the UUID file.
($uuid, my $return_code) = lc($anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{dmidecode}." --string system-uuid"})); ($uuid, my $return_code) = lc($anvil->System->call({debug => $debug, shell_call => $anvil->data->{path}{exe}{dmidecode}." --string system-uuid"}));
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid, return_code => $return_code }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
uuid => $uuid,
return_code => $return_code,
}});
} }
else else
{ {
# Not running as root, so I have to rely on the cache file, or die if it doesn't # Host UUID file doesn't exist and I'm Not running as root, I'm done.
# exist.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'path::data::host_uuid' => $anvil->data->{path}{data}{host_uuid} }});
if (not -e $anvil->data->{path}{data}{host_uuid})
{
# We're done. # We're done.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0187"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0187"});
return("#!error!#"); return("#!error!#");
} }
else
{
$uuid = $anvil->Storage->read_file({debug => $debug, file => $anvil->data->{path}{data}{host_uuid}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
}
}
if ($anvil->Validate->is_uuid({uuid => $uuid})) if ($anvil->Validate->is_uuid({uuid => $uuid}))
{ {
$anvil->data->{HOST}{UUID} = $uuid; $anvil->{HOST}{UUID} = $uuid;
if (not -e $anvil->data->{path}{data}{host_uuid}) if (not -e $anvil->data->{path}{data}{host_uuid})
{ {
### TODO: This will need to set the proper SELinux context. ### TODO: This will need to set the proper SELinux context.
@ -582,21 +590,23 @@ sub host_uuid
else else
{ {
# Bad UUID. # Bad UUID.
$anvil->{HOST}{UUID} = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->{HOST}{UUID} }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0134", variables => { uuid => $uuid }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0134", variables => { uuid => $uuid }});
$anvil->data->{HOST}{UUID} = ""; return("#!error!#");
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->data->{HOST}{UUID} }});
} }
} }
# We'll also store the host UUID in a variable. # We'll also store the host UUID in a variable.
if ((not $anvil->data->{sys}{host_uuid}) && ($anvil->data->{HOST}{UUID})) if ((not $anvil->data->{sys}{host_uuid}) && ($anvil->{HOST}{UUID}))
{ {
$anvil->data->{sys}{host_uuid} = $anvil->data->{HOST}{UUID}; $anvil->data->{sys}{host_uuid} = $anvil->{HOST}{UUID};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::host_uuid" => $anvil->data->{sys}{host_uuid} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::host_uuid" => $anvil->data->{sys}{host_uuid} }});
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->data->{HOST}{UUID} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "HOST::UUID" => $anvil->{HOST}{UUID} }});
return($anvil->data->{HOST}{UUID}); return($anvil->{HOST}{UUID});
} }
=head2 md5sum =head2 md5sum

@ -358,7 +358,7 @@ sub call
else else
{ {
# In case the user is using ports in /etc/ssh/ssh_config, we'll want to check for an entry. # In case the user is using ports in /etc/ssh/ssh_config, we'll want to check for an entry.
$anvil->System->read_ssh_config(); $anvil->System->read_ssh_config({deubg => $debug});
$anvil->data->{hosts}{$target}{port} = "" if not defined $anvil->data->{hosts}{$target}{port}; $anvil->data->{hosts}{$target}{port} = "" if not defined $anvil->data->{hosts}{$target}{port};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "hosts::${target}::port" => $anvil->data->{hosts}{$target}{port} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "hosts::${target}::port" => $anvil->data->{hosts}{$target}{port} }});
@ -389,7 +389,7 @@ sub call
# If the target is a host name, convert it to an IP. # If the target is a host name, convert it to an IP.
if (not $anvil->Validate->is_ipv4({ip => $target})) if (not $anvil->Validate->is_ipv4({ip => $target}))
{ {
my $new_target = $anvil->Convert->hostname_to_ip({host_name => $target}); my $new_target = $anvil->Convert->hostname_to_ip({hostname => $target});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_target => $new_target }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_target => $new_target }});
if ($new_target) if ($new_target)
{ {
@ -465,6 +465,20 @@ sub call
$message_key = "message_0003"; $message_key = "message_0003";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { i => $i, message_key => $message_key }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { i => $i, message_key => $message_key }});
} }
elsif ($connect_output =~ /Host key verification failed/i)
{
# Need to accept the fingerprint
$message_key = "message_0135";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { i => $i, message_key => $message_key }});
# Make sure we know the fingerprint of the remote machine
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0158", variables => { target => $target, user => $< }});
$anvil->Remote->add_target_to_known_hosts({
debug => $debug,
target => $target,
user => $<,
});
}
elsif ($connect_output =~ /Connection refused/i) elsif ($connect_output =~ /Connection refused/i)
{ {
$i = $last_loop; $i = $last_loop;

@ -422,7 +422,8 @@ sub stop_server
{ {
my ($anvil) = @_; my ($anvil) = @_;
# Stopping the server is simply a question of "is the server running?" and, if so, stop it. # Stopping the server is simply a question of "is the server running?" and, if so, stop it. Once
# stopped, we stop the DRBD resource on both nodes.
my $server = $anvil->data->{environment}{OCF_RESKEY_name}; my $server = $anvil->data->{environment}{OCF_RESKEY_name};
my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." list"}); my ($output, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{virsh}." list"});
if ($return_code) if ($return_code)
@ -609,8 +610,9 @@ sub stop_server
{ {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0329", variables => { server => $server }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "log_0329", variables => { server => $server }});
# Stop DRBD resources now. # Stop DRBD resources now. We don't worry if it actually stops or not (let ScanCore
stop_storage($anvil); # handle that). We only care that the server has stopped.
manage_drbd_resource($anvil, "down");
$anvil->nice_exit({exit_code => 0}); $anvil->nice_exit({exit_code => 0});
} }
@ -1219,8 +1221,8 @@ sub validate_storage_drbd
{ {
my $protocol = $connection_ref->{section}->{net}->{option}->{protocol}->{value}; my $protocol = $connection_ref->{section}->{net}->{option}->{protocol}->{value};
my $fencing = $connection_ref->{section}->{net}->{option}->{fencing}->{value}; my $fencing = $connection_ref->{section}->{net}->{option}->{fencing}->{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
protocol => $resource, protocol => $protocol,
fencing => $fencing, fencing => $fencing,
}}); }});
@ -1345,6 +1347,12 @@ sub validate_storage_drbd
} }
} }
# If we're in a stop operation, we're done.
if ($anvil->data->{switches}{stop})
{
return(0);
}
# Now read in the status of the drbd devices # Now read in the status of the drbd devices
$return_code = undef; $return_code = undef;
(my $status_json, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{drbdsetup}." status --json"}); (my $status_json, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{drbdsetup}." status --json"});
@ -1783,12 +1791,43 @@ sub validate_ram
} }
# This stops (drbdadm down <server>) the storage for a given server on both nodes. # This stops (drbdadm down <server>) the storage for a given server on both nodes.
sub stop_storage sub manage_drbd_resource
{ {
my ($anvil) = @_; my ($anvil, $task) = @_;
read_server_definition($anvil); read_server_definition($anvil);
validate_storage($anvil); validate_storage_drbd($anvil);
# Stop the resource on the peer, then stop it here.
my $server = $anvil->data->{environment}{OCF_RESKEY_name};
my $peer_hostname = $anvil->data->{server}{drbd}{peer}{hostname};
my $peer_address = $anvil->data->{server}{drbd}{peer}{address};
my $shell_call = $anvil->data->{path}{exe}{drbdadm}." ".$task." ".$server;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
server => $server,
peer_hostname => $peer_hostname,
peer_address => $peer_address,
shell_call => $shell_call,
}});
my ($output, $error, $return_code) = $anvil->Remote->call({
debug => 2,
shell_call => $shell_call,
target => $peer_hostname,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
output => $output,
error => $error,
return_code => $return_code,
}});
# Now call it locally
$output = undef;
$return_code = undef;
($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); return(0);
} }

@ -239,7 +239,7 @@ About to try to download aproximately: [#!variable!packages!#] packages needed t
<key name="message_0132">Storage Network ##!variable!number!# - Used for DRBD communication between nodes and DR hosts. Should be VLAN-isolated from the IFN and, thus, trusted.</key> <key name="message_0132">Storage Network ##!variable!number!# - Used for DRBD communication between nodes and DR hosts. Should be VLAN-isolated from the IFN and, thus, trusted.</key>
<key name="message_0133">Internet/Intranet-Facing Network ##!variable!number!# - Used for all client/user facing traffic. Likely connected to a semi-trusted network only.</key> <key name="message_0133">Internet/Intranet-Facing Network ##!variable!number!# - Used for all client/user facing traffic. Likely connected to a semi-trusted network only.</key>
<key name="message_0134">Updating / configuring the firewall.</key> <key name="message_0134">Updating / configuring the firewall.</key>
<key name="message_0135">#!free!#</key> <key name="message_0135">It appears like we need to accept the fingerprint. Will do so now and then try to conenct again.</key>
<key name="message_0136">The zone: [#!variable!zone!#] file: [#!variable!file!#] needs to be updated.</key> <key name="message_0136">The zone: [#!variable!zone!#] file: [#!variable!file!#] needs to be updated.</key>
<key name="message_0137">The zone: [#!variable!zone!#] file: [#!variable!file!#] doesn't exist, it will now be created.</key> <key name="message_0137">The zone: [#!variable!zone!#] file: [#!variable!file!#] doesn't exist, it will now be created.</key>
<key name="message_0138">The interface: [#!variable!interface!#] will be added to the zone: [#!variable!zone!#].</key> <key name="message_0138">The interface: [#!variable!interface!#] will be added to the zone: [#!variable!zone!#].</key>
@ -416,7 +416,7 @@ The database connection error was:
<key name="log_0131">Entering function: [#!variable!function!#]</key> <key name="log_0131">Entering function: [#!variable!function!#]</key>
<key name="log_0132">Connected to: [#!data!sys::database::connections!#] database(s).</key> <key name="log_0132">Connected to: [#!data!sys::database::connections!#] database(s).</key>
<key name="log_0133">Failed to read the system UUID. Received a non-UUID string: [#!variable!uuid!#]. Is the user: [#!variable!user!#] in the 'kmem' group?</key> <key name="log_0133">Failed to read the system UUID. Received a non-UUID string: [#!variable!uuid!#]. Is the user: [#!variable!user!#] in the 'kmem' group?</key>
<key name="log_0134">The read host UUID: [#!variable!uuid!#] does not appear to be a valid UUID.</key> <key name="log_0134">The host UUID: [#!variable!uuid!#] does not appear to be a valid UUID. Please check the contents of: [#!data!path::data::host_uuid!#] or the output from: [dmidecode --string system-uuid]. Note that some mainboards will report their UUID as all-0. If this is the case, manually create the 'host.uuid' file with a UUID created by 'uuidgen'.</key>
<key name="log_0135">- #!variable!caller!# runtime was approximately: [#!variable!runtime!#] seconds.</key> <key name="log_0135">- #!variable!caller!# runtime was approximately: [#!variable!runtime!#] seconds.</key>
<key name="log_0136"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with either 'job_uuid': [#!variable!job_uuid!#] not being passed (or was not a valid UUID), or 'job_name': [#!variable!job_name!#] not being passed.]]></key> <key name="log_0136"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with either 'job_uuid': [#!variable!job_uuid!#] not being passed (or was not a valid UUID), or 'job_name': [#!variable!job_name!#] not being passed.]]></key>
<key name="log_0137"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with an invalid value for: [#!variable!variable_name!#]: -> [#!variable!variable_value!#]. See 'perldoc Anvil::Tools::#!variable!module!#' for valid options.]]></key> <key name="log_0137"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with an invalid value for: [#!variable!variable_name!#]: -> [#!variable!variable_value!#]. See 'perldoc Anvil::Tools::#!variable!module!#' for valid options.]]></key>
@ -469,7 +469,7 @@ The database connection error was:
<key name="log_0184">Theew was a failed login attempt from: [#!variable!user_agent!#], trying to log in as: [#!variable!user!#]. log in rejected.</key> <key name="log_0184">Theew was a failed login attempt from: [#!variable!user_agent!#], trying to log in as: [#!variable!user!#]. log in rejected.</key>
<key name="log_0185"><![CDATA[<unknown>]]></key> <!-- Used in some cases when a variable isn't known --> <key name="log_0185"><![CDATA[<unknown>]]></key> <!-- Used in some cases when a variable isn't known -->
<key name="log_0186"><![CDATA[<suppressed>]]></key> <!-- Used in some cases when a variable isn't known --> <key name="log_0186"><![CDATA[<suppressed>]]></key> <!-- Used in some cases when a variable isn't known -->
<key name="log_0187">UUID cache file: [#!data!path::data::host_uuid!#] doesn't exists and we're not running as root. Unable to proceed.</key> <key name="log_0187">Host UUID cache file: [#!data!path::data::host_uuid!#] doesn't exists and we're not running as root so we can't read dmidecode. Unable to proceed.</key>
<key name="log_0188">Database archive check skipped, not running as root.</key> <key name="log_0188">Database archive check skipped, not running as root.</key>
<key name="log_0189">Database archiving is disabled, skipping archive checks.</key> <key name="log_0189">Database archiving is disabled, skipping archive checks.</key>
<key name="log_0190">Peer: [#!variable!peer!#], database: [#!variable!name!#], password: [#!variable!password!#], host UUID: [#!variable!uuid!#]</key> <key name="log_0190">Peer: [#!variable!peer!#], database: [#!variable!name!#], password: [#!variable!password!#], host UUID: [#!variable!uuid!#]</key>

Loading…
Cancel
Save