* This commit moves taking screenshots of hosted servers onto the strikers using the Sys::Virt module. This was needed because the screenshots were being taken by scan-server, and that was causing it to take a long time to run. It should never have been handled by the scan agent anyway. This update requires a WebUI fix to use the new screenshot tool. This tool also adds holding multiple screenshots to allow users to "scrub" through screenshots up to 10 hours in the past.

Signed-off-by: digimer <mkelly@alteeve.ca>
main
digimer 1 year ago
parent 3a84b5c0d7
commit c039c58128
  1. 4
      Anvil/Tools.pm
  2. 14
      Anvil/Tools/Storage.pm
  3. 23
      share/words.xml
  4. 28
      tools/anvil-daemon
  5. 108
      tools/anvil-get-server-screenshot

@ -1118,6 +1118,7 @@ sub _set_paths
pgsql => "/var/lib/pgsql/", pgsql => "/var/lib/pgsql/",
resource_status => "/sys/kernel/debug/drbd/resources", resource_status => "/sys/kernel/debug/drbd/resources",
scan_agents => "/usr/sbin/scancore-agents", scan_agents => "/usr/sbin/scancore-agents",
screenshots => "/opt/alteeve/screenshots",
shared => { shared => {
archives => "/mnt/shared/archives", archives => "/mnt/shared/archives",
base => "/mnt/shared", base => "/mnt/shared",
@ -1263,6 +1264,8 @@ sub _set_paths
pgrep => "/usr/bin/pgrep", pgrep => "/usr/bin/pgrep",
ps => "/usr/bin/ps", ps => "/usr/bin/ps",
psql => "/usr/bin/psql", psql => "/usr/bin/psql",
pamtopng => "/usr/bin/pamtopng",
pnmtojpeg => "/usr/bin/pnmtojpeg",
'postgresql-setup' => "/usr/bin/postgresql-setup", 'postgresql-setup' => "/usr/bin/postgresql-setup",
postmap => "/usr/sbin/postmap", postmap => "/usr/sbin/postmap",
postqueue => "/usr/sbin/postqueue", postqueue => "/usr/sbin/postqueue",
@ -1285,6 +1288,7 @@ sub _set_paths
storcli64 => "/opt/MegaRAID/storcli/storcli64", storcli64 => "/opt/MegaRAID/storcli/storcli64",
strings => "/usr/bin/strings", strings => "/usr/bin/strings",
'striker-auto-initialize-all' => "/usr/sbin/striker-auto-initialize-all", 'striker-auto-initialize-all' => "/usr/sbin/striker-auto-initialize-all",
'striker-get-screenshots' => "/usr/sbin/striker-get-screenshots",
'striker-get-peer-data' => "/usr/sbin/striker-get-peer-data", 'striker-get-peer-data' => "/usr/sbin/striker-get-peer-data",
'striker-initialize-host' => "/usr/sbin/striker-initialize-host", 'striker-initialize-host' => "/usr/sbin/striker-initialize-host",
'striker-manage-install-target' => "/usr/sbin/striker-manage-install-target", 'striker-manage-install-target' => "/usr/sbin/striker-manage-install-target",

@ -5175,6 +5175,10 @@ Parameters;
When writing to a file that already exists, and C<< overwrite >> is true, the existing backup will be backed up prior to being rewritten. When writing to a file that already exists, and C<< overwrite >> is true, the existing backup will be backed up prior to being rewritten.
=head3 binary (optional, default '0')
When set to '1', this indicates that the body is binary data, which prevents logging of the file body.
=head3 body (optional) =head3 body (optional)
This is the contents of the file. If it is blank, an empty file will be created (similar to using 'C<< touch >>' on the command line). This is the contents of the file. If it is blank, an empty file will be created (similar to using 'C<< touch >>' on the command line).
@ -5233,6 +5237,7 @@ sub write_file
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->write_file()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->write_file()" }});
my $backup = defined $parameter->{backup} ? $parameter->{backup} : 1; my $backup = defined $parameter->{backup} ? $parameter->{backup} : 1;
my $binary = defined $parameter->{binary} ? $parameter->{binary} : 0;
my $body = defined $parameter->{body} ? $parameter->{body} : ""; my $body = defined $parameter->{body} ? $parameter->{body} : "";
my $file = defined $parameter->{file} ? $parameter->{file} : ""; my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $group = defined $parameter->{group} ? $parameter->{group} : getgrgid($(); my $group = defined $parameter->{group} ? $parameter->{group} : getgrgid($();
@ -5247,7 +5252,7 @@ sub write_file
my $error = 0; my $error = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
backup => $backup, backup => $backup,
body => (not $secure) ? $body : $anvil->Log->is_secure($body), binary => $binary,
file => $file, file => $file,
group => $group, group => $group,
mode => $mode, mode => $mode,
@ -5259,6 +5264,12 @@ sub write_file
user => $user, user => $user,
remote_user => $remote_user, remote_user => $remote_user,
}}); }});
if (not $binary)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
body => (not $secure) ? $body : $anvil->Log->is_secure($body),
}});
}
# Make sure the user and group and just one digit or word. # Make sure the user and group and just one digit or word.
$user =~ s/^(\S+)\s.*$/$1/; $user =~ s/^(\S+)\s.*$/$1/;
@ -5480,6 +5491,7 @@ fi";
$temp_file .= ".".$anvil->Get->uuid({debug => $debug, short => 1}); $temp_file .= ".".$anvil->Get->uuid({debug => $debug, short => 1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }});
$anvil->Storage->write_file({ $anvil->Storage->write_file({
binary => $binary,
body => $body, body => $body,
debug => $debug, debug => $debug,
file => $temp_file, file => $temp_file,

@ -2596,6 +2596,16 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
<key name="log_0800">- Ejecting: [#!variable!device_path!#] from: [#!variable!device_target!#].</key> <key name="log_0800">- Ejecting: [#!variable!device_path!#] from: [#!variable!device_target!#].</key>
<key name="log_0801">Updating the stored definition and undefining the server now:</key> <key name="log_0801">Updating the stored definition and undefining the server now:</key>
<key name="log_0802">Working with the server: [#!variable!server_name!#], UUID: [#!variable!server_uuid!#]</key> <key name="log_0802">Working with the server: [#!variable!server_name!#], UUID: [#!variable!server_uuid!#]</key>
<key name="log_0803">Looking for access to: [#!variable!host_name!#]</key>
<key name="log_0804">Connecting: [#!variable!host_name!#] via: [#!variable!target_ip!#]</key>
<key name="log_0805">Getting a screenshot from: [#!variable!server_name!#] (uuid: [#!variable!server_uuid!#]) from the host: [#!variable!host_name!#].</key>
<key name="log_0806">- Saving the screenshot: [#!variable!ppm_file!#].</key>
<key name="log_0807">- Converting: [#!variable!ppm_file!#] to:
[#!variable!new_file!#]</key>
<key name="log_0808">Deleting screenshots older than: [#!variable!maximum_age!#].</key>
<key name="log_0809">- Deleting the server: [#!variable!server_name!#]'s screenshot: [#!variable!file!#].</key>
<key name="log_0810">- No access to: [#!variable!host_name!#] found.</key>
<key name="log_0811">- The host: [#!variable!host_name!#] is not configured, skipping it.</key>
<!-- Messages for users (less technical than log entries), though sometimes used for logs, too. --> <!-- Messages for users (less technical than log entries), though sometimes used for logs, too. -->
<key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key> <key name="message_0001">The host name: [#!variable!target!#] does not resolve to an IP address.</key>
@ -3636,6 +3646,14 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="unit_0038">%</key> <key name="unit_0038">%</key>
<key name="unit_0039">Amps</key> <key name="unit_0039">Amps</key>
<key name="unit_0040">Going Back</key> <!-- Bond state --> <key name="unit_0040">Going Back</key> <!-- Bond state -->
<key name="unit_0041">- Server is running.</key>
<key name="unit_0042">- Server is blocked (IO contention?).</key>
<key name="unit_0043">- Server is paused (migration target?).</key>
<key name="unit_0044">- Server is shutting down.</key>
<key name="unit_0045">- Server is shut off.</key>
<key name="unit_0046">- Server is crashed!</key>
<key name="unit_0047">- Server is suspended.</key>
<key name="unit_0048">- Server is in an unknown state (int: [#!variable!state!#]).</key>
<!-- These are special. These are used to describe the UPSes that ScanCore supports. These <!-- These are special. These are used to describe the UPSes that ScanCore supports. These
are used when adding UPSes to the system for use in Install Manifests. are used when adding UPSes to the system for use in Install Manifests.
@ -3899,6 +3917,11 @@ We will try to proceed anyway.</key>
#!variable!error!# #!variable!error!#
==================== ====================
We will try to proceed anyway.</key> We will try to proceed anyway.</key>
<key name="warning_0162">Failed to connect to libvirtd on: [#!variable!host_name!#] via the URI: [#!variable!uri!#]. The error, if any, was:
====
#!variable!error!#
====
</key>
</language> </language>
<!-- 日本語 --> <!-- 日本語 -->

@ -552,8 +552,13 @@ sub handle_periodic_tasks
}}); }});
# Even when this runs, it should finish in under ten seconds so we don't need to background it. # Even when this runs, it should finish in under ten seconds so we don't need to background it.
my ($parse_output, $return_code) = $anvil->System->call({debug => 3, shell_call => $anvil->data->{path}{exe}{'anvil-parse-fence-agents'}.$anvil->Log->switches, source => $THIS_FILE, line => __LINE__}); my $shell_call = $anvil->data->{path}{exe}{'anvil-parse-fence-agents'}.$anvil->Log->switches;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { parse_output => $parse_output }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }});
my ($parse_output, $return_code) = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
parse_output => $parse_output,
return_code => $return_code,
}});
# Scan the local network. # Scan the local network.
update_state_file($anvil); update_state_file($anvil);
@ -570,6 +575,25 @@ sub handle_periodic_tasks
# Check for stale db_in_use states. # Check for stale db_in_use states.
check_db_in_use_states($anvil); check_db_in_use_states($anvil);
# Do Striker-specific minute tasks
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { host_type => $host_type }});
if ($host_type eq "striker")
{
# This can take a while, but it's been optimized to minimize how long it takes to
# run. To be safe, we'll still background it.
my $shell_call = $anvil->data->{path}{exe}{'striker-get-screenshots'}.$anvil->Log->switches;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => { shell_call => $shell_call }});
my ($output, $return_code) = $anvil->System->call({
background => 1,
shell_call => $shell_call,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
output => $output,
return_code => $return_code,
}});
}
} }
# Now check to see if it's time to run less frequent tasks. # Now check to see if it's time to run less frequent tasks.

@ -6,6 +6,7 @@
use strict; use strict;
use warnings; use warnings;
use Anvil::Tools; use Anvil::Tools;
use Sys::Virt;
$| = 1; $| = 1;
@ -18,12 +19,11 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new(); my $anvil = Anvil::Tools->new();
$anvil->Get->switches; $anvil->Get->switches({list => ["convert", "job-uuid", "out-file-id", "resize", "request-host-name". "server-uuid'"], man => $THIS_FILE});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}});
my $debug = $anvil->data->{switches}{debug};
$anvil->Database->connect; $anvil->Database->connect;
$anvil->Log->entry({ source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0132" }); $anvil->Log->entry({ source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132" });
if (not $anvil->data->{sys}{database}{connections}) if (not $anvil->data->{sys}{database}{connections})
{ {
# No databases, exit. # No databases, exit.
@ -35,7 +35,7 @@ if (not $anvil->data->{sys}{database}{connections})
if (not $anvil->data->{switches}{'job-uuid'}) if (not $anvil->data->{switches}{'job-uuid'})
{ {
$anvil->data->{switches}{'job-uuid'} = $anvil->Job->get_job_uuid({ program => $THIS_FILE }); $anvil->data->{switches}{'job-uuid'} = $anvil->Job->get_job_uuid({ program => $THIS_FILE });
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
"switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'}
} }); } });
} }
@ -54,25 +54,19 @@ if ($anvil->data->{switches}{'job-uuid'})
foreach my $line (split/\n/, $anvil->data->{jobs}{job_data}) foreach my $line (split/\n/, $anvil->data->{jobs}{job_data})
{ {
if ($line =~ /server-uuid=(.*?)$/) my ($variable, $value) = ($line =~ /^(.*)=(.*)$/);
{ $value =~ s/^"(.*)\"/$1/;
$anvil->data->{switches}{'server-uuid'} = $1; $value =~ s/^'(.*)\'/$1/;
} $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:line' => $line,
if ($line =~ /resize=(.*?)$/) 's2:variable' => $variable,
{ 's3:value' => $value,
$anvil->data->{switches}{'resize'} = $1; }});
}
$anvil->data->{switches}{$variable} = $value;
if ($line =~ /request-host-uuid=(.*?)$/) $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
{ "switches::${variable}" => $anvil->data->{switches}{$variable},
$anvil->data->{switches}{'request-host-uuid'} = $1; }});
}
if ($line =~ /out-file-id=(.*?)$/)
{
$anvil->data->{switches}{'out-file-id'} = $1;
}
} }
} }
@ -82,41 +76,43 @@ my $out_file_id = $anvil->data->{switches}{'out-file-id'};
my $resize_args = $anvil->data->{switches}{'resize'}; my $resize_args = $anvil->data->{switches}{'resize'};
my $request_host_name = $anvil->data->{switches}{'request-host-name'}; my $request_host_name = $anvil->data->{switches}{'request-host-name'};
my $server_uuid = $anvil->data->{switches}{'server-uuid'}; my $server_uuid = $anvil->data->{switches}{'server-uuid'};
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
$out_file_id = ( (defined $out_file_id) && ($out_file_id ne "#!SET!#") ) ? "_${out_file_id}" : ""; is_convert => $is_convert,
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => {
debug => $debug,
job_uuid => $job_uuid, job_uuid => $job_uuid,
request_host_name => $request_host_name, out_file_id => $out_file_id,
resize_args => $resize_args, resize_args => $resize_args,
request_host_name => $request_host_name,
server_uuid => $server_uuid, server_uuid => $server_uuid,
} }); }});
$out_file_id = ((defined $out_file_id) && ($out_file_id ne "#!SET!#")) ? "_".$out_file_id : "";
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { out_file_id => $out_file_id }});
if ($server_uuid) if ($server_uuid)
{ {
my $out_file_path = $anvil->data->{path}{directories}{tmp}."/${server_uuid}_screenshot${out_file_id}"; my $out_file_path = $anvil->data->{path}{directories}{tmp}."/".$server_uuid."_screenshot".$out_file_id;
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { out_file_path => $out_file_path }});
if ($is_convert) if ($is_convert)
{ {
my ($rcode, $encoded_image) = convert_server_screenshot({ my ($return_code, $encoded_image) = convert_server_screenshot({
debug => $debug,
resize_args => $resize_args, resize_args => $resize_args,
source_file => $out_file_path, source_file => $out_file_path,
}); });
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
print($encoded_image) if ($rcode == 0); print($encoded_image) if ($return_code == 0);
$anvil->nice_exit({ exit_code => $rcode }); $anvil->nice_exit({ exit_code => $return_code });
} }
my ($rcode) = get_server_screenshot({ my ($return_code) = get_server_screenshot({
debug => $debug,
output_file => $out_file_path, output_file => $out_file_path,
server_uuid => $server_uuid, server_uuid => $server_uuid,
}); });
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { return_code => $return_code }});
if ($rcode > 0) if ($return_code > 0)
{ {
$anvil->Job->update_progress({ progress => 100, message => "message_0265" }); $anvil->Job->update_progress({ progress => 100, message => "message_0265" });
@ -127,19 +123,15 @@ if ($server_uuid)
{ {
chomp $request_host_name; chomp $request_host_name;
my $rsync = $anvil->data->{path}{exe}{rsync};
foreach my $host_name ( split(/,/, $request_host_name) ) foreach my $host_name ( split(/,/, $request_host_name) )
{ {
my $shell_call = "$rsync -e \"ssh -o BatchMode=yes\" -ac '$out_file_path' '$host_name':'$out_file_path'"; my $shell_call = $anvil->data->{path}{exe}{rsync}." -e \"ssh -o BatchMode=yes\" -ac '".$out_file_path."' '".$host_name."':'".$out_file_path."'";
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => {
host_name => $host_name, host_name => $host_name,
out_file_path => $out_file_path,
shell_call => $shell_call, shell_call => $shell_call,
} }); } });
system_call({ debug => $debug, shell_call => $shell_call }); system_call({shell_call => $shell_call });
} }
} }
@ -154,16 +146,16 @@ else
$anvil->nice_exit({ exit_code => 0 }); $anvil->nice_exit({ exit_code => 0 });
#
# Functions #############################################################################################################
# # Functions #
#############################################################################################################
sub convert_server_screenshot sub convert_server_screenshot
{ {
my $parameters = shift; my $parameters = shift;
my $resize_args = $parameters->{resize_args}; my $resize_args = $parameters->{resize_args};
my $source_file = $parameters->{source_file}; my $source_file = $parameters->{source_file};
my $debug = $parameters->{debug};
my $host_type = $anvil->Get->host_type(); my $host_type = $anvil->Get->host_type();
@ -179,12 +171,12 @@ sub convert_server_screenshot
{ {
my ($resize_x, $resize_y) = split(/x/ , $resize_args); my ($resize_x, $resize_y) = split(/x/ , $resize_args);
$shell_call .= " | $pamscale -quiet -xyfit $resize_x $resize_y"; $shell_call .= " | ".$pamscale." -quiet -xyfit ".$resize_x $resize_y;
} }
$shell_call .= " | $pamtopng -quiet | $base64 --wrap 0"; $shell_call .= " | ".$pamtopng." -quiet | ".$base64." --wrap 0";
my ($output, $return_code) = system_call({ debug => $debug, shell_call => $shell_call }); my ($output, $return_code) = system_call({shell_call => $shell_call });
return ($return_code, $output); return ($return_code, $output);
} }
@ -194,16 +186,15 @@ sub get_server_screenshot
my $parameters = shift; my $parameters = shift;
my $output_file = $parameters->{output_file}; my $output_file = $parameters->{output_file};
my $server_uuid = $parameters->{server_uuid}; my $server_uuid = $parameters->{server_uuid};
my $debug = $parameters->{debug};
return (1) if ( (not $server_uuid) || (not $output_file) ); return (1) if ( (not $server_uuid) || (not $output_file) );
my $setsid = $anvil->data->{path}{exe}{setsid}; my $setsid = $anvil->data->{path}{exe}{setsid};
my $virsh = $anvil->data->{path}{exe}{virsh}; my $virsh = $anvil->data->{path}{exe}{virsh};
my $shell_call = "$setsid --wait $virsh --quiet screenshot --domain $server_uuid --file $output_file"; my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." --quiet screenshot --domain ".$server_uuid." --file ".$output_file;
my ($output, $return_code) = system_call({ debug => $debug, shell_call => $shell_call }); my ($output, $return_code) = system_call({shell_call => $shell_call });
return ($return_code, $output); return ($return_code, $output);
} }
@ -211,12 +202,11 @@ sub get_server_screenshot
sub system_call sub system_call
{ {
my $parameters = shift; my $parameters = shift;
my $debug = $parameters->{debug};
my @call_result = $anvil->System->call($parameters); my @call_result = $anvil->System->call($parameters);
my ($output, $return_code) = @call_result; my ($output, $return_code) = @call_result;
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
%$parameters, %{$parameters},
output => $output, output => $output,
return_code => $return_code, return_code => $return_code,
} }); } });

Loading…
Cancel
Save