* Renamed tools/anvil-reboot-needed to tools/anvil-manage-power and started adding support for rebooting and powering off to it.

* Created the Anvil::Tools::Jobs module to handle general job processing task. Moved 'update_progress' from tools/anvil-update-system to it and generalized it.
* Added some missing CDATA wrappers to the words XML file strings with '>' in it.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent 962ff89fc5
commit 545f9a9bb5
  1. 17
      Anvil/Tools.pm
  2. 279
      Anvil/Tools/Job.pm
  3. 52
      cgi-bin/striker
  4. BIN
      html/skins/alteeve/images/reboot_icon.xcf
  5. BIN
      html/skins/alteeve/images/reboot_needed_icon.png
  6. 33
      share/words.xml
  7. 2
      tools/anvil-daemon
  8. 188
      tools/anvil-manage-power
  9. 101
      tools/anvil-reboot-needed
  10. 98
      tools/anvil-update-system

@ -43,6 +43,7 @@ use Anvil::Tools::Alert;
use Anvil::Tools::Database; use Anvil::Tools::Database;
use Anvil::Tools::Convert; use Anvil::Tools::Convert;
use Anvil::Tools::Get; use Anvil::Tools::Get;
use Anvil::Tools::Job;
use Anvil::Tools::Log; use Anvil::Tools::Log;
use Anvil::Tools::Remote; use Anvil::Tools::Remote;
use Anvil::Tools::Storage; use Anvil::Tools::Storage;
@ -120,6 +121,7 @@ sub new
CONVERT => Anvil::Tools::Convert->new(), CONVERT => Anvil::Tools::Convert->new(),
GET => Anvil::Tools::Get->new(), GET => Anvil::Tools::Get->new(),
LOG => Anvil::Tools::Log->new(), LOG => Anvil::Tools::Log->new(),
JOB => Anvil::Tools::Job->new(),
REMOTE => Anvil::Tools::Remote->new(), REMOTE => Anvil::Tools::Remote->new(),
STORAGE => Anvil::Tools::Storage->new(), STORAGE => Anvil::Tools::Storage->new(),
SYSTEM => Anvil::Tools::System->new(), SYSTEM => Anvil::Tools::System->new(),
@ -154,6 +156,7 @@ sub new
$anvil->Convert->parent($anvil); $anvil->Convert->parent($anvil);
$anvil->Get->parent($anvil); $anvil->Get->parent($anvil);
$anvil->Log->parent($anvil); $anvil->Log->parent($anvil);
$anvil->Job->parent($anvil);
$anvil->Remote->parent($anvil); $anvil->Remote->parent($anvil);
$anvil->Storage->parent($anvil); $anvil->Storage->parent($anvil);
$anvil->System->parent($anvil); $anvil->System->parent($anvil);
@ -456,6 +459,18 @@ sub Get
return ($self->{HANDLE}{GET}); return ($self->{HANDLE}{GET});
} }
=head2 Job
Access the C<Job.pm> methods via 'C<< $anvil->Log->method >>'.
=cut
sub Job
{
my $self = shift;
return ($self->{HANDLE}{JOB});
}
=head2 Log =head2 Log
Access the C<Log.pm> methods via 'C<< $anvil->Log->method >>'. Access the C<Log.pm> methods via 'C<< $anvil->Log->method >>'.
@ -888,7 +903,7 @@ sub _set_paths
'anvil-manage-striker-peers' => "/usr/sbin/anvil-manage-striker-peers", 'anvil-manage-striker-peers' => "/usr/sbin/anvil-manage-striker-peers",
'anvil-prep-database' => "/usr/sbin/anvil-prep-database", 'anvil-prep-database' => "/usr/sbin/anvil-prep-database",
'anvil-update-states' => "/usr/sbin/anvil-update-states", 'anvil-update-states' => "/usr/sbin/anvil-update-states",
'anvil-reboot-needed' => "/usr/sbin/anvil-reboot-needed", 'anvil-manage-power' => "/usr/sbin/anvil-reboot-needed",
'anvil-report-memory' => "/usr/sbin/anvil-report-memory", 'anvil-report-memory' => "/usr/sbin/anvil-report-memory",
'chmod' => "/usr/bin/chmod", 'chmod' => "/usr/bin/chmod",
'chown' => "/usr/bin/chown", 'chown' => "/usr/bin/chown",

@ -0,0 +1,279 @@
package Anvil::Tools::Job;
#
# This module contains methods used in job handling
#
use strict;
use warnings;
use Data::Dumper;
use Scalar::Util qw(weaken isweak);
our $VERSION = "3.0.0";
my $THIS_FILE = "Job.pm";
### Methods;
#
=pod
=encoding utf8
=head1 NAME
Anvil::Tools::Job
Provides methods related to (background) job handling.
=head1 SYNOPSIS
use Anvil::Tools;
# Get a common object handle on all Anvil::Tools modules.
my $anvil = Anvil::Tools->new();
# ...
=head1 METHODS
Methods in this module;
=cut
sub new
{
my $class = shift;
my $self = {
JOB => {
LANGUAGE => "",
},
};
bless $self, $class;
return ($self);
}
# Get a handle on the Anvil::Tools object. I know that technically that is a sibling module, but it makes more
# sense in this case to think of it as a parent.
sub parent
{
my $self = shift;
my $parent = shift;
$self->{HANDLE}{TOOLS} = $parent if $parent;
# Defend against memory leads. See Scalar::Util'.
if (not isweak($self->{HANDLE}{TOOLS}))
{
weaken($self->{HANDLE}{TOOLS});;
}
return ($self->{HANDLE}{TOOLS});
}
#############################################################################################################
# Public methods #
#############################################################################################################
=head2 update_progress
This updates the progress if we were called with a job UUID.
This also sets C<< sys::last_update >>, allowing you to see how long it's been since the progress was last updated and trigger an update on a time based counter.
Returns C<< 0 >> on success, C<< 1 >> on failure.
B<< Note >>: Some special C<< job_status >> processing is done to support some specific callers. These should not impact generic calls of this method.
Parameters;
=head3 job_uuid (optional, default 'jobs::job_uuid')
This is the UUID of the job to update. If it isn't set, but C<< jobs::job_uuid >> is set, it will be used. If that is also not set,
=head3 message (optional)
If set, this message will be appended to C<< job_status >>. If set to 'C<< clear >>', previous records will be removed.
=head3 progress (required)
This is a number to set the current progress to.
=cut
sub update_progress
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
my $salt = "";
my $job_uuid = defined $parameter->{job_uuid} ? $parameter->{job_uuid} : "";
my $message = defined $parameter->{message} ? $parameter->{message} : "";
my $progress = defined $parameter->{progress} ? $parameter->{progress} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
progress => $progress,
message => $message,
job_uuid => $job_uuid,
"jobs::job_uuid" => $anvil->data->{jobs}{job_uuid},
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_uuid => $job_uuid }});
if ((not $job_uuid) && ($anvil->data->{jobs}{job_uuid}))
{
$job_uuid = $anvil->data->{jobs}{job_uuid};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_uuid => $job_uuid }});
}
# Exit if we still don't have a job_uuid
if (not $job_uuid)
{
# Nothing we can do.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0207"});
return(1);
}
# Exit if we don't have a progress.
if ($progress eq "")
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Job->update_progress()", parameter => "progress" }});
return(1);
}
# Is the progress valid?
if (($progress =~ /\D/) or ($progress < 0) or ($progress > 100))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0209", variables => { progress => $progress }});
return(1);
}
# If 'sys::last_update' isn't set, set it now.
if (not defined $anvil->data->{sys}{last_update})
{
$anvil->data->{sys}{last_update} = time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::last_update" => $anvil->data->{sys}{last_update} }});
}
# Get the current job_status and append this new one.
my $job_picked_up_by = $$;
my $job_picked_up_at = 0;
my $job_status = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { message => $message, job_picked_up_by => $job_picked_up_by }});
if ($message eq "clear")
{
$job_picked_up_by = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_picked_up_by => $job_picked_up_by }});
}
else
{
my $query = "
SELECT
job_status,
job_picked_up_at
FROM
jobs
WHERE
job_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($job_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results,
count => $count,
}});
if (not $count)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0208", variables => {job_uuid => $job_uuid}});
return(1);
}
$job_status = $results->[0]->[0];
$job_picked_up_at = $results->[0]->[1];
$job_status = "" if not defined $job_status;
$job_picked_up_at = 0 if not defined $job_picked_up_at;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
job_status => $job_status,
job_picked_up_at => $job_picked_up_at,
}});
# Set that the job is now picked up if the progress is '1' or it 'job_picked_up_at'
# is not set yet.
if ((not $job_picked_up_at) or ($progress eq "1"))
{
$job_picked_up_at = time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_picked_up_at => $job_picked_up_at }});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { message => $message }});
if (($message) && ($job_status))
{
$job_status .= "\n";
}
if ($message)
{
$job_status .= $message;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_status => $job_status }});
}
}
### NOTE: This is used by 'anvil-update-system'.
# Insert counts
if ($job_status =~ /message_0058/gs)
{
my $downloaded = $anvil->data->{counts}{downloaded} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{downloaded}}) : 0;
my $installed = $anvil->data->{counts}{installed} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{installed}}) : 0;
my $verified = $anvil->data->{counts}{verified} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{verified}}) : 0;
my $lines = $anvil->data->{counts}{lines} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{lines}}) : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:counts::downloaded" => $anvil->data->{counts}{downloaded},
"s2:downloaded" => $downloaded,
"s3:counts::installed" => $anvil->data->{counts}{installed},
"s4:installed" => $installed,
"s5:counts::verified" => $anvil->data->{counts}{verified},
"s6:verified" => $verified,
"s7:counts::lines" => $anvil->data->{counts}{lines},
"s8:lines" => $lines,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ">> job_status" => $job_status }});
$job_status =~ s/message_0058,!!downloaded!.*?!!,!!installed!.*?!!,!!verified!.*?!!,!!lines!.*?!!/message_0058,!!downloaded!$downloaded!!,!!installed!$installed!!,!!verified!$verified!!,!!lines!$lines!!/sm;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "<< job_status" => $job_status }});
}
my $query = "
UPDATE
jobs
SET
job_picked_up_by = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_by).",
job_picked_up_at = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_at).",
job_updated = ".$anvil->data->{sys}{database}{use_handle}->quote(time).",
job_progress = ".$anvil->data->{sys}{database}{use_handle}->quote($progress).",
job_status = ".$anvil->data->{sys}{database}{use_handle}->quote($job_status).",
modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
job_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($job_uuid)."
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
# Note this update time
$anvil->data->{sys}{last_update} = time;
return(0);
}
# =head3
#
# Private Functions;
#
# =cut
#############################################################################################################
# Private functions #
#############################################################################################################
1;

@ -234,6 +234,14 @@ sub process_task
{ {
process_update($anvil); process_update($anvil);
} }
elsif ($anvil->data->{cgi}{task}{value} eq "reboot")
{
process_reboot($anvil);
}
elsif ($anvil->data->{cgi}{task}{value} eq "poweroff")
{
process_poweroff($anvil);
}
else else
{ {
# What we show for the reboot icon and text depends on if a reboot is pending. # What we show for the reboot icon and text depends on if a reboot is pending.
@ -272,6 +280,50 @@ sub process_task
return(0); return(0);
} }
# This handles updating this Striker.
sub process_reboot
{
my ($anvil) = @_;
### NOTE: This doesn't update Striker (the Alteeve) stack yet, just the base OK.
$anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value};
if ($anvil->data->{cgi}{confirm}{value})
{
# Record the job!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
file => $THIS_FILE,
line => __LINE__,
job_command => "anvil-manage-power --reboot -y",
job_data => "",
job_name => "reboot::system",
job_title => "job_0003",
job_description => "job_0004",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
# We don't need to store anything as hidden variables, we'll read it back from the database
# later.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "system_update_recorded", variables => {
title_id => "",
message_id => "",
title => "#!string!striker_0044!#",
description => "#!string!striker_0088!#",
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }});
# Set maintenance mode.
$anvil->System->maintenance_mode({debug => 2, set => 1});
}
else
{
# Show the screen the confirm the addition.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-update"});
}
return(0);
}
# This handles updating this Striker. # This handles updating this Striker.
sub process_update sub process_update
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 24 KiB

@ -82,9 +82,12 @@ Report maintenance mode: #!variable!program!#
<key name="message_0050">This system has has been set to no longer need a reboot.</key> <key name="message_0050">This system has has been set to no longer need a reboot.</key>
<key name="message_0051">This system was not in maintenance mode, nothing changed.</key> <key name="message_0051">This system was not in maintenance mode, nothing changed.</key>
<key name="message_0052">Bad call. Usage: <key name="message_0052">Bad call. Usage:
Set that a reboot is required: #!variable!program!# --set 1 Set that a reboot is required: #!variable!program!# --reboot-needed 1
Clear the need for a reboot: #!variable!program!# --set 0 Clear the need for a reboot: #!variable!program!# --reboot-neededset 0
Report if a reboot is needed: #!variable!program!# Report if a reboot is needed: #!variable!program!#
Reboot the system: #!variable!program!# --reboot [-y]
Poweroff the system: #!variable!program!# --poweroff [-y]
The '-y' option prevents a confirmation prompt.
</key> </key>
<key name="message_0053">This system needs to be rebooted.</key> <key name="message_0053">This system needs to be rebooted.</key>
<key name="message_0054">This system does NOT need to be rebooted.</key> <key name="message_0054">This system does NOT need to be rebooted.</key>
@ -93,6 +96,9 @@ Report if a reboot is needed: #!variable!program!#
<key name="message_0057">No updates were found or needed.</key> <key name="message_0057">No updates were found or needed.</key>
<!-- NOTE: If you change the variable names below, you have to update 'anvil-update-system' as well. --> <!-- NOTE: If you change the variable names below, you have to update 'anvil-update-system' as well. -->
<key name="message_0058">* Packages downloaded: [#!variable!downloaded!#], Installed or updated: [#!variable!installed!#], Verified: [#!variable!verified!#], Output lines: [#!variable!lines!#].</key> <key name="message_0058">* Packages downloaded: [#!variable!downloaded!#], Installed or updated: [#!variable!installed!#], Verified: [#!variable!verified!#], Output lines: [#!variable!lines!#].</key>
<key name="message_0059">Are you sure you want to reboot this system? [y/N].</key>
<key name="message_0060">Are you sure you want to power off this system? [y/N].</key>
<key name="message_0061">Aborting.</key>
<!-- Log entries --> <!-- Log entries -->
<key name="log_0001">Starting: [#!variable!program!#].</key> <key name="log_0001">Starting: [#!variable!program!#].</key>
@ -171,7 +177,7 @@ Connecting to Database with configuration ID: [#!variable!uuid!#]
<key name="log_0060">Database user: [#!variable!user!#] already exists with ID: [#!variable!uuid!#].</key> <key name="log_0060">Database user: [#!variable!user!#] already exists with ID: [#!variable!uuid!#].</key>
<key name="log_0061"><![CDATA[[ Error ] - The method Get->users_home() was asked to find the home directory for the user: [#!variable!user!#], but was unable to do so.]]></key> <key name="log_0061"><![CDATA[[ Error ] - The method Get->users_home() was asked to find the home directory for the user: [#!variable!user!#], but was unable to do so.]]></key>
<key name="log_0062">SSH session opened without a password to: [#!variable!target!#].</key> <key name="log_0062">SSH session opened without a password to: [#!variable!target!#].</key>
<key name="log_0063">The database: [#!variable!host!# -> #!variable!name!#] with the UUID: [#!variable!uuid!#] did not respond to pings and 'database::#!variable!uuid!#::ping' is not set to '0' in '#!data!path::configs::anvil.conf!#', skipping it.</key> <key name="log_0063"><![CDATA[The database: [#!variable!host!# -> #!variable!name!#] with the UUID: [#!variable!uuid!#] did not respond to pings and 'database::#!variable!uuid!#::ping' is not set to '0' in '#!data!path::configs::anvil.conf!#', skipping it.]]></key>
<key name="log_0064">[ Warning ] - The database: [#!variable!name!#] on host: [#!variable!host!#] with ID: [#!variable!uuid!#] can not be used, skipping it.</key> <key name="log_0064">[ Warning ] - The database: [#!variable!name!#] on host: [#!variable!host!#] with ID: [#!variable!uuid!#] can not be used, skipping it.</key>
<key name="log_0065"> <key name="log_0065">
The database connection error was: The database connection error was:
@ -277,10 +283,10 @@ The database connection error was:
<key name="log_0147">A job to configure the network was found, and it was picked up by: [#!variable!pid!#], but that process is not running and it appears to only be: [#!variable!percent!# %] complete. Taking the job.</key> <key name="log_0147">A job to configure the network was found, and it was picked up by: [#!variable!pid!#], but that process is not running and it appears to only be: [#!variable!percent!# %] complete. Taking the job.</key>
<key name="log_0148">The network: [#!variable!network!#] has something set for the IP [#!variable!ip!#], but it appears to be invalid. Ignoring this network.</key> <key name="log_0148">The network: [#!variable!network!#] has something set for the IP [#!variable!ip!#], but it appears to be invalid. Ignoring this network.</key>
<key name="log_0149">The network: [#!variable!network!#] is not set to be configured. Skipping it.</key> <key name="log_0149">The network: [#!variable!network!#] is not set to be configured. Skipping it.</key>
<key name="log_0150">The Storage->backup() method was called with the source file: [#!variable!source_file!#], which does not appear to be a full path and file name (should start with '/').</key> <key name="log_0150"><![CDATA[The Storage->backup() method was called with the source file: [#!variable!source_file!#], which does not appear to be a full path and file name (should start with '/').]]></key>
<key name="log_0151">The Storage->backup() method was called with the source file: [#!variable!source_file!#], which does not appear to exist.</key> <key name="log_0151"><![CDATA[The Storage->backup() method was called with the source file: [#!variable!source_file!#], which does not appear to exist.]]></key>
<key name="log_0152">The Storage->backup() method was called with the source file: [#!variable!source_file!#], which can not be read (please check permissions and SELinux).</key> <key name="log_0152"><![CDATA[The Storage->backup() method was called with the source file: [#!variable!source_file!#], which can not be read (please check permissions and SELinux).]]></key>
<key name="log_0153">The Storage->backup() method was called with the source file: [#!variable!source_file!#], which isn't actually a file.</key> <key name="log_0153"><![CDATA[The Storage->backup() method was called with the source file: [#!variable!source_file!#], which isn't actually a file.]]></key>
<key name="log_0154">The file: [#!variable!source_file!#] has been backed up as: [#!variable!target_file!#].</key> <key name="log_0154">The file: [#!variable!source_file!#] has been backed up as: [#!variable!target_file!#].</key>
<key name="log_0155">Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration.</key> <key name="log_0155">Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration.</key>
<key name="log_0156"><![CDATA[[ Error ] - The method: [#!variable!method!#] must be called with root-level priviledges.]]></key> <key name="log_0156"><![CDATA[[ Error ] - The method: [#!variable!method!#] must be called with root-level priviledges.]]></key>
@ -292,7 +298,7 @@ The database connection error was:
<key name="log_0162"><![CDATA[[ Error ] - The method Storage->read_file() tried to rsync the remote file: [#!variable!remote_file!#] to the local temporary file: [#!variable!local_file!#], but it did not arrive. There might be more information above.]]></key> <key name="log_0162"><![CDATA[[ Error ] - The method Storage->read_file() tried to rsync the remote file: [#!variable!remote_file!#] to the local temporary file: [#!variable!local_file!#], but it did not arrive. There might be more information above.]]></key>
<key name="log_0163">The file: [#!variable!file!#] does not exist.</key> <key name="log_0163">The file: [#!variable!file!#] does not exist.</key>
<key name="log_0164"><![CDATA[[ Warning ] - Storage->read_config()' was called without a file name to read.]]></key> <key name="log_0164"><![CDATA[[ Warning ] - Storage->read_config()' was called without a file name to read.]]></key>
<key name="log_0165">The Storage->backup() method was asked to backup the file: [#!variable!source_file!#] on: [#!variable!target!#], but it looks like there was a problem connecting to the target.</key> <key name="log_0165"><![CDATA[The Storage->backup() method was asked to backup the file: [#!variable!source_file!#] on: [#!variable!target!#], but it looks like there was a problem connecting to the target.]]></key>
<key name="log_0166">About to run the shell command: [#!variable!shell_call!#] on: [#!variable!target!#] as: [#!variable!remote_user!#]</key> <key name="log_0166">About to run the shell command: [#!variable!shell_call!#] on: [#!variable!target!#] as: [#!variable!remote_user!#]</key>
<key name="log_0167">Failed to create the directory: [#!variable!directory!#] on: [#!variable!target!#] as: [#!variable!remote_user!#]. The error (if any) was: [#!variable!error!#] and the output (if any) was: [#!variable!output!#].</key> <key name="log_0167">Failed to create the directory: [#!variable!directory!#] on: [#!variable!target!#] as: [#!variable!remote_user!#]. The error (if any) was: [#!variable!error!#] and the output (if any) was: [#!variable!output!#].</key>
<key name="log_0168">Failed to create the directory: [#!variable!directory!#]. The error (if any) was: [#!variable!error!#].</key> <key name="log_0168">Failed to create the directory: [#!variable!directory!#]. The error (if any) was: [#!variable!error!#].</key>
@ -333,7 +339,10 @@ The database connection error was:
<key name="log_0203">Disconnected from all databases. Will reconnect when entering the main loop.</key> <key name="log_0203">Disconnected from all databases. Will reconnect when entering the main loop.</key>
<key name="log_0204">Starting the background process: [#!variable!call!#] now.</key> <key name="log_0204">Starting the background process: [#!variable!call!#] now.</key>
<key name="log_0205">Background process: [#!variable!call!#] running with PID: [#!variable!pid!#].</key> <key name="log_0205">Background process: [#!variable!call!#] running with PID: [#!variable!pid!#].</key>
<key name="log_0206">In Words->parse_banged_string(), while processing: [#!variable!message!#], a variable name was found to be missing.</key> <key name="log_0206"><![CDATA[In Words->parse_banged_string(), while processing: [#!variable!message!#], a variable name was found to be missing.]]></key>
<key name="log_0207"><![CDATA[Job->update_progress() called without 'job_uuid' being set, and 'jobs::job_uuid' was also not set. Unable to find the job to update.]]></key>
<key name="log_0208"><![CDATA[Job->update_progress() called with the 'job_uuid': [#!variable!job_uuid!#], which was not found. Unable to find the job to update.]]></key>
<key name="log_0209"><![CDATA[Job->update_progress() called with 'progress' set to an invalid value: [#!variable!progress!#]. This must be a whole number between '0' and '100' (fractions not allowed).]]></key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. --> <!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key> <key name="t_0000">Test</key>
@ -513,8 +522,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="error_0022">The: [#!variable!field!#] must be a positive integer.</key> <key name="error_0022">The: [#!variable!field!#] must be a positive integer.</key>
<key name="error_0023">There was a problem reading your session details. To be safe, you have been logged out. Please try logging back in.</key> <key name="error_0023">There was a problem reading your session details. To be safe, you have been logged out. Please try logging back in.</key>
<key name="error_0024">It appears that your session has expired. To be safe, you have been logged out. Please try logging back in.</key> <key name="error_0024">It appears that your session has expired. To be safe, you have been logged out. Please try logging back in.</key>
<key name="error_0025">The user ID passed in to Account->read_details: [#!variable!uuid!#] is not a valid UUID.</key> <key name="error_0025"><![CDATA[The user ID passed in to Account->read_details: [#!variable!uuid!#] is not a valid UUID.]]></key>
<key name="error_0026">The user ID passed in to Account->read_details: [#!variable!uuid!#] was not found in the database.</key> <key name="error_0026"><![CDATA[The user ID passed in to Account->read_details: [#!variable!uuid!#] was not found in the database.]]></key>
<key name="error_0027">Login failed, please try again.</key> <key name="error_0027">Login failed, please try again.</key>
<key name="error_0028"><![CDATA[There appears to be a problem with Striker. The login failed, please check: [<span class="code">#!data!sys::log_file!#</span>] for details.]]></key> <key name="error_0028"><![CDATA[There appears to be a problem with Striker. The login failed, please check: [<span class="code">#!data!sys::log_file!#</span>] for details.]]></key>
<key name="error_0029"><![CDATA[Failed to find the template: [<span class="code">#!variable!template!#</span>] in the template file: [<span class="code">#!variable!file!#</span>].]]></key> <key name="error_0029"><![CDATA[Failed to find the template: [<span class="code">#!variable!template!#</span>] in the template file: [<span class="code">#!variable!file!#</span>].]]></key>
@ -530,7 +539,7 @@ The update appears to have not completed successfully. The output was:
==== ====
</key> </key>
<key name="error_0036"></key> <key name="error_0036"></key>
<key name="error_0037">In Words->parse_banged_string(), an infinite loop was detected while processing: [#!variable!message!#].</key> <key name="error_0037"><![CDATA[In Words->parse_banged_string(), an infinite loop was detected while processing: [#!variable!message!#].]]></key>
<!-- These are units, words and so on used when displaying information. --> <!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key> <key name="unit_0001">Yes</key>

@ -162,7 +162,7 @@ sub run_once
# Clear the reboot request. # Clear the reboot request.
my $output = $anvil->System->call({ my $output = $anvil->System->call({
debug => 2, debug => 2,
shell_call => $anvil->data->{path}{exe}{'anvil-reboot-needed'}." --set 0", shell_call => $anvil->data->{path}{exe}{'anvil-reboot-needed'}." --reboot-needed 0",
source => $THIS_FILE, source => $THIS_FILE,
line => __LINE__, line => __LINE__,
}); });

@ -0,0 +1,188 @@
#!/usr/bin/perl
#
# This manages power on the host. It can set that a reboot is or is no longer required. It can also reboot or
# power off the machine.
#
# Examples;
# - Mark that a reboot is required - anvil-manage-power --reboot-needed 1
# - Clear that a reboot is needed - anvil-manage-power --reboot-needed 0
# - Report whether a reboot is needed or not - anvil-manage-power
# - Reboot the system - anvil-manage-power --reboot [-y]
# - Power the system off - anvil-manage-power --poweroff [-y]
#
# Exit codes;
# 0 = Normal exit.
# 1 = No database connections available.
#
# TODO: Don't reboot or power off until all external users are done with the database on this system (if
# applicable)
#
use strict;
use warnings;
use Anvil::Tools;
# Disable buffering
$| = 1;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
$anvil->Storage->read_config({file => "/etc/anvil/anvil.conf"});
# Read switches
$anvil->data->{switches}{'poweroff'} = "";
$anvil->data->{switches}{'power-off'} = "";
$anvil->data->{switches}{'reboot'} = "";
$anvil->data->{switches}{'y'} = "";
$anvil->data->{switches}{'yes'} = "";
$anvil->data->{switches}{'reboot-needed'} = "";
$anvil->Get->switches;
if ($anvil->data->{switches}{'power-off'})
{
$anvil->data->{switches}{'poweroff'} = 1;
}
if ($anvil->data->{switches}{'yes'})
{
$anvil->data->{switches}{'y'} = 1;
}
# Connect to DBs.
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
# No databases, exit.
print $anvil->Words->string({key => "error_0003"})."\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "error_0003"});
$anvil->nice_exit({exit_code => 1});
}
# Are we being asked to reboot or power off?
if ($anvil->data->{switches}{'reboot'})
{
# Did the user confirm?
if ($anvil->data->{switches}{'reboot'} =~ /^y/i)
{
do_reboot($anvil);
}
else
{
# Not yet, ask to confirm.
print $anvil->Words->string({key => "message_0059"})." ";
my $answer = <STDIN>;
chomp($answer);
if ($answer =~ /^y/i)
{
do_reboot($anvil);
}
else
{
# Abort and exit.
print $anvil->Words->string({key => "message_0061"})."\n";
$anvil->nice_exit({exit_code => 0});
}
}
}
if ($anvil->data->{switches}{'poweroff'})
{
# Did the user confirm?
if ($anvil->data->{switches}{'poweroff'} =~ /^y/i)
{
do_poweroff($anvil);
}
else
{
# Not yet, ask to confirm.
print $anvil->Words->string({key => "message_0060"})." ";
my $answer = <STDIN>;
chomp($answer);
if ($answer =~ /^y/i)
{
do_poweroff($anvil);
}
else
{
# Abort and exit.
print $anvil->Words->string({key => "message_0061"})."\n";
$anvil->nice_exit({exit_code => 0});
}
}
}
my $reboot_needed = $anvil->System->reboot_needed({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::reboot-needed" => $anvil->data->{switches}{'reboot-needed'} }});
if ($anvil->data->{switches}{'reboot-needed'} eq "1")
{
# Enable
if (not $reboot_needed)
{
$reboot_needed = $anvil->System->reboot_needed({debug => 2, set => 1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
print $anvil->Words->string({key => "message_0048"})."\n";
}
else
{
# Was already set, do nothing
print $anvil->Words->string({key => "message_0049"})."\n";
}
}
elsif ($anvil->data->{switches}{'reboot-needed'} eq "0")
{
# Disabled
if ($reboot_needed)
{
$reboot_needed = $anvil->System->reboot_needed({debug => 2, set => 0});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
print $anvil->Words->string({key => "message_0050"})."\n";
}
else
{
# Was already disabled, do nothing
print $anvil->Words->string({key => "message_0051"})."\n";
}
}
elsif ($anvil->data->{switches}{'reboot-needed'})
{
# Bad call
print $anvil->Words->string({key => "message_0052", variables => { program => $THIS_FILE }})."\n";
}
# Get the current state
if ($reboot_needed)
{
# Report that we're in mainteance mode
print $anvil->Words->string({key => "message_0053"})."\n";
}
else
{
# Report that we're not.
print $anvil->Words->string({key => "message_0054"})."\n";
}
# We're done
$anvil->nice_exit({exit_code => 0});
#############################################################################################################
# Private functions. #
#############################################################################################################
# This does a reboot, clearing the flag indicating a reboot is required in the process.
sub do_reboot
{
my ($anvil) = @_;
$anvil->nice_exit({exit_code => 0});
}

@ -1,101 +0,0 @@
#!/usr/bin/perl
#
# This set, clear and report if the host needs to be rebooted.
#
# Examples;
# - Enable - anvil-reboot-needed --set 1
# - Disable - anvil-reboot-needed --set 0
# - Report - anvil-reboot-needed
#
# Exit codes;
# 0 = Normal exit.
# 1 = No database connections available.
use strict;
use warnings;
use Anvil::Tools;
# Disable buffering
$| = 1;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
$anvil->Storage->read_config({file => "/etc/anvil/anvil.conf"});
# Read switches
$anvil->data->{switches}{set} = "";
$anvil->Get->switches;
# Connect to DBs.
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
if (not $anvil->data->{sys}{database}{connections})
{
# No databases, exit.
print $anvil->Words->string({key => "error_0003"})."\n";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, secure => 0, key => "error_0003"});
$anvil->nice_exit({exit_code => 1});
}
my $reboot_needed = $anvil->System->reboot_needed({debug => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::set" => $anvil->data->{switches}{set} }});
if ($anvil->data->{switches}{set} eq "1")
{
# Enable
if (not $reboot_needed)
{
$reboot_needed = $anvil->System->reboot_needed({debug => 2, set => 1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
print $anvil->Words->string({key => "message_0048"})."\n";
}
else
{
# Was already set, do nothing
print $anvil->Words->string({key => "message_0049"})."\n";
}
}
elsif ($anvil->data->{switches}{set} eq "0")
{
# Disabled
if ($reboot_needed)
{
$reboot_needed = $anvil->System->reboot_needed({debug => 2, set => 0});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }});
print $anvil->Words->string({key => "message_0050"})."\n";
}
else
{
# Was already disabled, do nothing
print $anvil->Words->string({key => "message_0051"})."\n";
}
}
elsif ($anvil->data->{switches}{set})
{
# Bad call
print $anvil->Words->string({key => "message_0052", variables => { program => $THIS_FILE }})."\n";
}
# Get the current state
if ($reboot_needed)
{
# Report that we're in mainteance mode
print $anvil->Words->string({key => "message_0053"})."\n";
}
else
{
# Report that we're not.
print $anvil->Words->string({key => "message_0054"})."\n";
}
# We're done
$anvil->nice_exit({exit_code => 0});

@ -141,7 +141,6 @@ WHERE
} }
# Clea any old runs. # Clea any old runs.
$anvil->data->{sys}{last_update} = time;
update_progress($anvil, 0, "clear"); update_progress($anvil, 0, "clear");
# We'll keep a count of lines and packages to show the user. # We'll keep a count of lines and packages to show the user.
@ -196,97 +195,12 @@ sub update_progress
if ($anvil->data->{jobs}{job_uuid}) if ($anvil->data->{jobs}{job_uuid})
{ {
# Get the current job_status and append this new one. $anvil->Job->update_progress({
my $job_picked_up_by = $$; debug => 2,
my $job_picked_up_at = 0; progress => $progress,
my $job_status = ""; message => $message,
if ($message eq "clear") job_uuid => $anvil->data->{jobs}{job_uuid}},
{ );
$job_picked_up_by = 0;
}
else
{
my $query = "
SELECT
job_status,
job_picked_up_at
FROM
jobs
WHERE
job_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{jobs}{job_uuid})."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$job_status = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$job_picked_up_at = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[1];
$job_status = "" if not defined $job_status;
$job_picked_up_at = 0 if not defined $job_picked_up_at;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
job_status => $job_status,
job_picked_up_at => $job_picked_up_at,
}});
# Set that the job is now picked up if the progress is '1' or it 'job_picked_up_at'
# is not set yet.
if ((not $job_picked_up_at) or ($progress eq "1"))
{
$job_picked_up_at = time;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_picked_up_at => $job_picked_up_at }});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message => $message }});
if (($message) && ($job_status))
{
$job_status .= "\n";
}
if ($message)
{
$job_status .= $message;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_status => $job_status }});
}
}
# Insert counts
if ($job_status =~ /message_0058/gs)
{
my $downloaded = $anvil->data->{counts}{downloaded} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{downloaded}}) : 0;
my $installed = $anvil->data->{counts}{installed} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{installed}}) : 0;
my $verified = $anvil->data->{counts}{verified} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{verified}}) : 0;
my $lines = $anvil->data->{counts}{lines} ? $anvil->Convert->add_commas({number => $anvil->data->{counts}{lines}}) : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:counts::downloaded" => $anvil->data->{counts}{downloaded},
"s2:downloaded" => $downloaded,
"s3:counts::installed" => $anvil->data->{counts}{installed},
"s4:installed" => $installed,
"s5:counts::verified" => $anvil->data->{counts}{verified},
"s6:verified" => $verified,
"s7:counts::lines" => $anvil->data->{counts}{lines},
"s8:lines" => $lines,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ">> job_status" => $job_status }});
$job_status =~ s/message_0058,!!downloaded!.*?!!,!!installed!.*?!!,!!verified!.*?!!,!!lines!.*?!!/message_0058,!!downloaded!$downloaded!!,!!installed!$installed!!,!!verified!$verified!!,!!lines!$lines!!/sm;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< job_status" => $job_status }});
}
my $query = "
UPDATE
jobs
SET
job_picked_up_by = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_by).",
job_picked_up_at = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_at).",
job_updated = ".$anvil->data->{sys}{database}{use_handle}->quote(time).",
job_progress = ".$anvil->data->{sys}{database}{use_handle}->quote($progress).",
job_status = ".$anvil->data->{sys}{database}{use_handle}->quote($job_status).",
modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
job_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{jobs}{job_uuid})."
";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
# Note this update time
$anvil->data->{sys}{last_update} = time;
} }
return(0); return(0);

Loading…
Cancel
Save