diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index de68dcc4..276c8284 100755 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -43,6 +43,7 @@ use Anvil::Tools::Alert; use Anvil::Tools::Database; use Anvil::Tools::Convert; use Anvil::Tools::Get; +use Anvil::Tools::Job; use Anvil::Tools::Log; use Anvil::Tools::Remote; use Anvil::Tools::Storage; @@ -120,6 +121,7 @@ sub new CONVERT => Anvil::Tools::Convert->new(), GET => Anvil::Tools::Get->new(), LOG => Anvil::Tools::Log->new(), + JOB => Anvil::Tools::Job->new(), REMOTE => Anvil::Tools::Remote->new(), STORAGE => Anvil::Tools::Storage->new(), SYSTEM => Anvil::Tools::System->new(), @@ -154,6 +156,7 @@ sub new $anvil->Convert->parent($anvil); $anvil->Get->parent($anvil); $anvil->Log->parent($anvil); + $anvil->Job->parent($anvil); $anvil->Remote->parent($anvil); $anvil->Storage->parent($anvil); $anvil->System->parent($anvil); @@ -456,6 +459,18 @@ sub Get return ($self->{HANDLE}{GET}); } +=head2 Job + +Access the C methods via 'C<< $anvil->Log->method >>'. + +=cut +sub Job +{ + my $self = shift; + + return ($self->{HANDLE}{JOB}); +} + =head2 Log Access the C methods via 'C<< $anvil->Log->method >>'. @@ -888,7 +903,7 @@ sub _set_paths 'anvil-manage-striker-peers' => "/usr/sbin/anvil-manage-striker-peers", 'anvil-prep-database' => "/usr/sbin/anvil-prep-database", '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", 'chmod' => "/usr/bin/chmod", 'chown' => "/usr/bin/chown", diff --git a/Anvil/Tools/Job.pm b/Anvil/Tools/Job.pm new file mode 100755 index 00000000..305c043e --- /dev/null +++ b/Anvil/Tools/Job.pm @@ -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; diff --git a/cgi-bin/striker b/cgi-bin/striker index 2fcaf741..5a33363a 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -234,6 +234,14 @@ sub process_task { 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 { # 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); } +# 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. sub process_update { diff --git a/html/skins/alteeve/images/reboot_icon.xcf b/html/skins/alteeve/images/reboot_icon.xcf index 7540b1a5..43b18133 100644 Binary files a/html/skins/alteeve/images/reboot_icon.xcf and b/html/skins/alteeve/images/reboot_icon.xcf differ diff --git a/html/skins/alteeve/images/reboot_needed_icon.png b/html/skins/alteeve/images/reboot_needed_icon.png index bcfda975..c1c99ace 100644 Binary files a/html/skins/alteeve/images/reboot_needed_icon.png and b/html/skins/alteeve/images/reboot_needed_icon.png differ diff --git a/share/words.xml b/share/words.xml index 746d9d9f..8ea436ee 100644 --- a/share/words.xml +++ b/share/words.xml @@ -82,9 +82,12 @@ Report maintenance mode: #!variable!program!# This system has has been set to no longer need a reboot. This system was not in maintenance mode, nothing changed. Bad call. Usage: -Set that a reboot is required: #!variable!program!# --set 1 -Clear the need for a reboot: #!variable!program!# --set 0 +Set that a reboot is required: #!variable!program!# --reboot-needed 1 +Clear the need for a reboot: #!variable!program!# --reboot-neededset 0 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. This system needs to be rebooted. This system does NOT need to be rebooted. @@ -93,6 +96,9 @@ Report if a reboot is needed: #!variable!program!# No updates were found or needed. * Packages downloaded: [#!variable!downloaded!#], Installed or updated: [#!variable!installed!#], Verified: [#!variable!verified!#], Output lines: [#!variable!lines!#]. + Are you sure you want to reboot this system? [y/N]. + Are you sure you want to power off this system? [y/N]. + Aborting. Starting: [#!variable!program!#]. @@ -171,7 +177,7 @@ Connecting to Database with configuration ID: [#!variable!uuid!#] Database user: [#!variable!user!#] already exists with ID: [#!variable!uuid!#]. users_home() was asked to find the home directory for the user: [#!variable!user!#], but was unable to do so.]]> SSH session opened without a password to: [#!variable!target!#]. - 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. + #!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.]]> [ Warning ] - The database: [#!variable!name!#] on host: [#!variable!host!#] with ID: [#!variable!uuid!#] can not be used, skipping it. The database connection error was: @@ -277,10 +283,10 @@ The database connection error was: 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. The network: [#!variable!network!#] has something set for the IP [#!variable!ip!#], but it appears to be invalid. Ignoring this network. The network: [#!variable!network!#] is not set to be configured. Skipping it. - 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 '/'). - The Storage->backup() method was called with the source file: [#!variable!source_file!#], which does not appear to exist. - The Storage->backup() method was called with the source file: [#!variable!source_file!#], which can not be read (please check permissions and SELinux). - The Storage->backup() method was called with the source file: [#!variable!source_file!#], which isn't actually a file. + 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 '/').]]> + backup() method was called with the source file: [#!variable!source_file!#], which does not appear to exist.]]> + backup() method was called with the source file: [#!variable!source_file!#], which can not be read (please check permissions and SELinux).]]> + backup() method was called with the source file: [#!variable!source_file!#], which isn't actually a file.]]> The file: [#!variable!source_file!#] has been backed up as: [#!variable!target_file!#]. Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration. @@ -292,7 +298,7 @@ The database connection error was: 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.]]> The file: [#!variable!file!#] does not exist. read_config()' was called without a file name to read.]]> - 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. + 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.]]> About to run the shell command: [#!variable!shell_call!#] on: [#!variable!target!#] as: [#!variable!remote_user!#] 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!#]. Failed to create the directory: [#!variable!directory!#]. The error (if any) was: [#!variable!error!#]. @@ -333,7 +339,10 @@ The database connection error was: Disconnected from all databases. Will reconnect when entering the main loop. Starting the background process: [#!variable!call!#] now. Background process: [#!variable!call!#] running with PID: [#!variable!pid!#]. - In Words->parse_banged_string(), while processing: [#!variable!message!#], a variable name was found to be missing. + parse_banged_string(), while processing: [#!variable!message!#], a variable name was found to be missing.]]> + update_progress() called without 'job_uuid' being set, and 'jobs::job_uuid' was also not set. Unable to find the job to update.]]> + update_progress() called with the 'job_uuid': [#!variable!job_uuid!#], which was not found. Unable to find the job to update.]]> + 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).]]> Test @@ -513,8 +522,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st The: [#!variable!field!#] must be a positive integer. There was a problem reading your session details. To be safe, you have been logged out. Please try logging back in. It appears that your session has expired. To be safe, you have been logged out. Please try logging back in. - The user ID passed in to Account->read_details: [#!variable!uuid!#] is not a valid UUID. - The user ID passed in to Account->read_details: [#!variable!uuid!#] was not found in the database. + read_details: [#!variable!uuid!#] is not a valid UUID.]]> + read_details: [#!variable!uuid!#] was not found in the database.]]> Login failed, please try again. #!data!sys::log_file!#] for details.]]> #!variable!template!#] in the template file: [#!variable!file!#].]]> @@ -530,7 +539,7 @@ The update appears to have not completed successfully. The output was: ==== - In Words->parse_banged_string(), an infinite loop was detected while processing: [#!variable!message!#]. + parse_banged_string(), an infinite loop was detected while processing: [#!variable!message!#].]]> Yes diff --git a/tools/anvil-daemon b/tools/anvil-daemon index 10d268d7..41f1be32 100755 --- a/tools/anvil-daemon +++ b/tools/anvil-daemon @@ -162,7 +162,7 @@ sub run_once # Clear the reboot request. my $output = $anvil->System->call({ 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, line => __LINE__, }); diff --git a/tools/anvil-manage-power b/tools/anvil-manage-power new file mode 100755 index 00000000..33be0bce --- /dev/null +++ b/tools/anvil-manage-power @@ -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 = ; + 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 = ; + 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}); +} diff --git a/tools/anvil-reboot-needed b/tools/anvil-reboot-needed deleted file mode 100755 index 33444405..00000000 --- a/tools/anvil-reboot-needed +++ /dev/null @@ -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}); diff --git a/tools/anvil-update-system b/tools/anvil-update-system index 7e448597..a30b5dd2 100755 --- a/tools/anvil-update-system +++ b/tools/anvil-update-system @@ -141,7 +141,6 @@ WHERE } # Clea any old runs. -$anvil->data->{sys}{last_update} = time; update_progress($anvil, 0, "clear"); # 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}) { - # Get the current job_status and append this new one. - my $job_picked_up_by = $$; - my $job_picked_up_at = 0; - my $job_status = ""; - if ($message eq "clear") - { - $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; + $anvil->Job->update_progress({ + debug => 2, + progress => $progress, + message => $message, + job_uuid => $anvil->data->{jobs}{job_uuid}}, + ); } return(0);