* 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/",
resource_status => "/sys/kernel/debug/drbd/resources",
scan_agents => "/usr/sbin/scancore-agents",
screenshots => "/opt/alteeve/screenshots",
shared => {
archives => "/mnt/shared/archives",
base => "/mnt/shared",
@ -1263,6 +1264,8 @@ sub _set_paths
pgrep => "/usr/bin/pgrep",
ps => "/usr/bin/ps",
psql => "/usr/bin/psql",
pamtopng => "/usr/bin/pamtopng",
pnmtojpeg => "/usr/bin/pnmtojpeg",
'postgresql-setup' => "/usr/bin/postgresql-setup",
postmap => "/usr/sbin/postmap",
postqueue => "/usr/sbin/postqueue",
@ -1285,6 +1288,7 @@ sub _set_paths
storcli64 => "/opt/MegaRAID/storcli/storcli64",
strings => "/usr/bin/strings",
'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-initialize-host' => "/usr/sbin/striker-initialize-host",
'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.
=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)
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()" }});
my $backup = defined $parameter->{backup} ? $parameter->{backup} : 1;
my $binary = defined $parameter->{binary} ? $parameter->{binary} : 0;
my $body = defined $parameter->{body} ? $parameter->{body} : "";
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $group = defined $parameter->{group} ? $parameter->{group} : getgrgid($();
@ -5247,7 +5252,7 @@ sub write_file
my $error = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => {
backup => $backup,
body => (not $secure) ? $body : $anvil->Log->is_secure($body),
binary => $binary,
file => $file,
group => $group,
mode => $mode,
@ -5259,6 +5264,12 @@ sub write_file
user => $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.
$user =~ s/^(\S+)\s.*$/$1/;
@ -5480,6 +5491,7 @@ fi";
$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->Storage->write_file({
binary => $binary,
body => $body,
debug => $debug,
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_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_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. -->
<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_0039">Amps</key>
<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
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!#
====================
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>
<!-- 日本語 -->

@ -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.
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__});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { parse_output => $parse_output }});
my $shell_call = $anvil->data->{path}{exe}{'anvil-parse-fence-agents'}.$anvil->Log->switches;
$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.
update_state_file($anvil);
@ -570,6 +575,25 @@ sub handle_periodic_tasks
# Check for stale db_in_use states.
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.

@ -6,6 +6,7 @@
use strict;
use warnings;
use Anvil::Tools;
use Sys::Virt;
$| = 1;
@ -18,12 +19,11 @@ if (($running_directory =~ /^\./) && ($ENV{PWD}))
my $anvil = Anvil::Tools->new();
$anvil->Get->switches;
my $debug = $anvil->data->{switches}{debug};
$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}});
$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})
{
# No databases, exit.
@ -35,7 +35,7 @@ if (not $anvil->data->{sys}{database}{connections})
if (not $anvil->data->{switches}{'job-uuid'})
{
$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'}
} });
}
@ -54,25 +54,19 @@ if ($anvil->data->{switches}{'job-uuid'})
foreach my $line (split/\n/, $anvil->data->{jobs}{job_data})
{
if ($line =~ /server-uuid=(.*?)$/)
{
$anvil->data->{switches}{'server-uuid'} = $1;
}
if ($line =~ /resize=(.*?)$/)
{
$anvil->data->{switches}{'resize'} = $1;
}
if ($line =~ /request-host-uuid=(.*?)$/)
{
$anvil->data->{switches}{'request-host-uuid'} = $1;
}
if ($line =~ /out-file-id=(.*?)$/)
{
$anvil->data->{switches}{'out-file-id'} = $1;
}
my ($variable, $value) = ($line =~ /^(.*)=(.*)$/);
$value =~ s/^"(.*)\"/$1/;
$value =~ s/^'(.*)\'/$1/;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
's1:line' => $line,
's2:variable' => $variable,
's3:value' => $value,
}});
$anvil->data->{switches}{$variable} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"switches::${variable}" => $anvil->data->{switches}{$variable},
}});
}
}
@ -82,41 +76,43 @@ my $out_file_id = $anvil->data->{switches}{'out-file-id'};
my $resize_args = $anvil->data->{switches}{'resize'};
my $request_host_name = $anvil->data->{switches}{'request-host-name'};
my $server_uuid = $anvil->data->{switches}{'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 => $debug, list => {
debug => $debug,
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
is_convert => $is_convert,
job_uuid => $job_uuid,
request_host_name => $request_host_name,
out_file_id => $out_file_id,
resize_args => $resize_args,
request_host_name => $request_host_name,
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)
{
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)
{
my ($rcode, $encoded_image) = convert_server_screenshot({
debug => $debug,
my ($return_code, $encoded_image) = convert_server_screenshot({
resize_args => $resize_args,
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({
debug => $debug,
my ($return_code) = get_server_screenshot({
output_file => $out_file_path,
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" });
@ -127,19 +123,15 @@ if ($server_uuid)
{
chomp $request_host_name;
my $rsync = $anvil->data->{path}{exe}{rsync};
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'";
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => {
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 => {
host_name => $host_name,
out_file_path => $out_file_path,
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 });
#
# Functions
#
#############################################################################################################
# Functions #
#############################################################################################################
sub convert_server_screenshot
{
my $parameters = shift;
my $resize_args = $parameters->{resize_args};
my $source_file = $parameters->{source_file};
my $debug = $parameters->{debug};
my $host_type = $anvil->Get->host_type();
@ -179,12 +171,12 @@ sub convert_server_screenshot
{
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);
}
@ -194,16 +186,15 @@ sub get_server_screenshot
my $parameters = shift;
my $output_file = $parameters->{output_file};
my $server_uuid = $parameters->{server_uuid};
my $debug = $parameters->{debug};
return (1) if ( (not $server_uuid) || (not $output_file) );
my $setsid = $anvil->data->{path}{exe}{setsid};
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);
}
@ -211,12 +202,11 @@ sub get_server_screenshot
sub system_call
{
my $parameters = shift;
my $debug = $parameters->{debug};
my @call_result = $anvil->System->call($parameters);
my ($output, $return_code) = @call_result;
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => $debug, list => {
%$parameters,
$anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => {
%{$parameters},
output => $output,
return_code => $return_code,
} });

Loading…
Cancel
Save