diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 015f7dc3..ca0a54b1 100755 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -361,7 +361,7 @@ sub nice_exit { my $self = shift; my $parameter = shift; - my $anvil = $self; + my $anvil = $self; my $exit_code = defined $parameter->{exit_code} ? $parameter->{exit_code} : 0; @@ -371,12 +371,21 @@ sub nice_exit # Report the runtime. my $end_time = Time::HiRes::time; my $run_time = $end_time - $anvil->data->{ENV_VALUES}{START_TIME}; + my $caller = ($0 =~ /^.*\/(.*)$/)[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 's1:ENV_VALUES::START_TIME' => $anvil->data->{ENV_VALUES}{START_TIME}, 's2:end_time' => $end_time, 's3:run_time' => $run_time, + 's4:caller' => $caller, + }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0135", variables => { 'caller' => $caller, runtime => $run_time }}); + + my ($package, $filename, $line) = caller; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + 's1:package' => $package, + 's2:filename' => $filename, + 's3:line' => $line, }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0135", variables => { runtime => $run_time }}); # Close the log file. if ($anvil->data->{HANDLE}{log_file}) @@ -1056,7 +1065,7 @@ sub catch_sig if ($signal) { - print "Process with PID: [$$] exiting on SIG".$signal.".\n"; + print "\n\nProcess with PID: [$$] exiting on SIG".$signal.".\n"; if ($anvil->data->{sys}{terminal}{stty}) { diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index ca1f62dd..9e269c39 100755 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -1307,6 +1307,10 @@ sub get_jobs my $return = []; my $ended_within = defined $parameter->{ended_within} ? $parameter->{ended_within} : 300; my $job_host_uuid = defined $parameter->{job_host_uuid} ? $parameter->{job_host_uuid} : $anvil->Get->host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + ended_within => $ended_within, + job_host_uuid => $job_host_uuid, + }}); my $query = " SELECT @@ -1327,11 +1331,11 @@ FROM WHERE job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($job_host_uuid)." ;"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + $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 => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { results => $results, count => $count, }}); @@ -1351,7 +1355,7 @@ WHERE my $modified_date = $row->[11]; my $started_seconds_ago = $job_picked_up_at ? (time - $job_picked_up_at) : 0; my $updated_seconds_ago = $job_updated ? (time - $job_updated) : 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_uuid => $job_uuid, job_command => $job_command, job_data => $job_data, diff --git a/Anvil/Tools/Get.pm b/Anvil/Tools/Get.pm index 04e53e7d..e603a8d2 100755 --- a/Anvil/Tools/Get.pm +++ b/Anvil/Tools/Get.pm @@ -45,7 +45,7 @@ Provides all methods related to getting access to frequently used data. # Access to methods using '$anvil->Get->X'. # # Example using 'date_and_time()'; - my $foo_path = $anvil->Get->date_and_time({...}); + my $date = $anvil->Get->date_and_time({...}); =head1 METHODS @@ -384,7 +384,7 @@ sub date_and_time my $time_only = defined $parameter->{time_only} ? $parameter->{time_only} : 0; my $date_only = defined $parameter->{date_only} ? $parameter->{date_only} : 0; - # NOTE: This is used too early for normal error handling. + ### NOTE: This is used too early for normal error handling. # Are things sane? if ($use_time =~ /D/) { diff --git a/Anvil/Tools/Job.pm b/Anvil/Tools/Job.pm index 305c043e..a65369c1 100755 --- a/Anvil/Tools/Job.pm +++ b/Anvil/Tools/Job.pm @@ -12,7 +12,9 @@ our $VERSION = "3.0.0"; my $THIS_FILE = "Job.pm"; ### Methods; -# +# clear +# get_job_uuid +# update_progress =pod @@ -75,6 +77,120 @@ sub parent # Public methods # ############################################################################################################# +=head2 clear + +This clears the C<< job_picked_up_by >> value for the given job. + +Parameters; + +=head3 job_uuid (required) + +This is the C<< job_uuid >> of the job to clear. + +=cut +sub clear +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + + my $job_uuid = defined $parameter->{job_uuid} ? $parameter->{job_uuid} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_uuid => $job_uuid }}); + + # Return if we don't have a program name. + if ($job_uuid eq "") + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Job->clear()", parameter => "job_uuid" }}); + return(1); + } + + my $query = " +UPDATE + jobs +SET + job_picked_up_by = '0', + 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 => 2, list => { query => $query }}); + $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); + + return(0); +} + +=head2 get_job_uuid + +This takes the name of a program and looks in jobs for a pending job with the same command. If it is found, C<< jobs::job_uuid >> is set and the C<< job_uuid >> is returned. If no job is found, and empty string is returned. + +Parameters; + +=head3 host_uuid (optional, default Get->host_uuid()) + +If set, this will search for the job on a specific host. + +=head3 program (required) + +This is the program name to look for. Specifically, this string is used to search C<< job_command >> (anchored to the start of the column and a wild-card end, ie: C<< program => foo >> would find C<< foobar >> or C<< foo --bar >>). Be as specific as possible. If two or more results are found, no C<< job_uuid >> will be returned. There must be only one match for this method to work properly. + +=cut +sub get_job_uuid +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + + my $job_uuid = ""; + my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid; + my $program = defined $parameter->{program} ? $parameter->{program} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + host_uuid => $host_uuid, + program => $program, + }}); + + # Return if we don't have a program name. + if ($program eq "") + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Job->get_job_uuid()", parameter => "program" }}); + return(1); + } + + my $query = " +SELECT + job_uuid +FROM + jobs +WHERE + job_command LIKE ".$anvil->data->{sys}{database}{use_handle}->quote($program."%")." +AND + job_progress != '100' +AND + job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_uuid)." +;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, 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 => 2, list => { + results => $results, + count => $count, + }}); + if ($count == 1) + { + # Found it + $job_uuid = defined $results->[0]->[0] ? $results->[0]->[0] : ""; + $anvil->data->{jobs}{job_uuid} = $job_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + job_uuid => $job_uuid, + "jobs::job-uuid" => $anvil->data->{jobs}{'job-uuid'}, + }}); + } + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); + return($job_uuid); +} + =head2 update_progress This updates the progress if we were called with a job UUID. @@ -107,7 +223,6 @@ sub update_progress 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} : ""; @@ -125,7 +240,7 @@ sub update_progress $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 + # Return if we still don't have a job_uuid if (not $job_uuid) { # Nothing we can do. @@ -133,7 +248,7 @@ sub update_progress return(1); } - # Exit if we don't have a progress. + # Return 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" }}); diff --git a/cgi-bin/striker b/cgi-bin/striker index b916d4b6..d2d0c2aa 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -184,7 +184,7 @@ sub process_task elsif ((defined $anvil->data->{cgi}{logout}) && ($anvil->data->{cgi}{logout}{value})) { # Bye now! - $anvil->Account->logout({debug => 3}); + $anvil->Account->logout(); } else { @@ -312,6 +312,9 @@ sub process_power description => $task eq "poweroff" ? "#!string!job_0008!#" : "#!string!job_0006!#", }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); + + # Log the user out, just to be safe. + $anvil->Account->logout(); } else { @@ -850,7 +853,7 @@ sub check_availability # If we have any running or recently finished jobs, we'll desplay them below. my $jobs_list = "#!string!striker_0097!#"; - my $return = $anvil->Database->get_jobs({debug => 2, ended_within => 300}); + my $return = $anvil->Database->get_jobs({ended_within => 300}); my $count = @{$return}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { count => $count }}); if ($count) diff --git a/share/words.xml b/share/words.xml index 5d55a37a..1bc45d19 100644 --- a/share/words.xml +++ b/share/words.xml @@ -101,6 +101,7 @@ The '-y' option prevents a confirmation prompt. Aborting. Powering off the local system now. Rebooting the local system now. + The Anvil! has restarted at: [#!variable!date_and_time!#] after powering back on. Starting: [#!variable!program!#]. @@ -270,7 +271,7 @@ The database connection error was: Connected to: [#!data!sys::database::connections!#] database(s). Failed to read the system UUID. Received a non-UUID string: [#!variable!uuid!#]. Is the user: [#!variable!user!#] in the 'kmem' group? The read host UUID: [#!variable!uuid!#] does not appear to be a valid UUID. - Runtime was approximately: [#!variable!runtime!#] seconds. + - #!variable!caller!# runtime was approximately: [#!variable!runtime!#] seconds. [#!variable!variable_value!#]. See 'perldoc Anvil::Tools::#!variable!module!#' for valid options.]]> @@ -483,8 +484,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st There are no jobs currently running or recently completed. Back Job - Reboot this system? If you proceed, this system will be withdrawn from the Anvil! and rebooted. Please be sure you have access in the rare chance that the system fails to boot back up. - Power off this system? If you proceed, this system will be withdrawn from the Anvil! and powered off. You will need physical access to the machine to turn it back on in most cases. A properly condigured Striker dashboard will power on after a power cycle (via a PDU) or any machine with IPMI if you have access to a machine on the BCN. + Reboot this system? If you proceed, you will be logged out and this system will be rebooted. Please be sure you have access in the rare chance that the system fails to boot back up. + Power off this system? If you proceed, you will be logged out and this system will be powered off. You will need physical access to the machine to turn it back on in most cases. A properly condigured Striker dashboard will power on after a power cycle (via a PDU) or any machine with IPMI if you have access to a machine on the BCN. Configure Network diff --git a/tools/anvil-daemon b/tools/anvil-daemon index 6b707b06..7d1e9350 100755 --- a/tools/anvil-daemon +++ b/tools/anvil-daemon @@ -11,6 +11,11 @@ # TODO: # - Need to check what kind of machine this is and not prep the database unless its a dashboard. # - Add a "running: pending,yes,done,dead" and show an appropriate icon beside jobs +# - Decide if holding before the main loop until 'systemctl is-system-running' returns 'running' is a good +# idea or not. +# +# NOTE: +# - For later; 'reboot --force --force' immediately kills the OS, like disabling ACPI on EL6 and hitting the power button. Might be useful in ScanCore down the road. # use strict; @@ -63,6 +68,7 @@ $anvil->data->{switches}{'refresh-json'} = ""; $anvil->data->{switches}{'run-once'} = 0; $anvil->data->{switches}{'main-loop-only'} = 0; $anvil->data->{switches}{'no-start'} = 0; +$anvil->data->{switches}{'startup-only'} = 0; $anvil->Get->switches; if ($anvil->data->{switches}{'refresh-json'}) @@ -90,7 +96,7 @@ while(1) { # Connect to the database(s) $anvil->Storage->read_config({file => "/etc/anvil/anvil.conf"}); - $anvil->Database->connect({debug => 2}); + $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); if ($anvil->data->{sys}{database}{connections}) @@ -124,12 +130,13 @@ while(1) } # Disconnect from the database(s) and sleep now. - $anvil->Database->disconnect({debug => 2}); + $anvil->Database->disconnect(); sleep 2; } $anvil->nice_exit({code => 0}); + ############################################################################################################# # Functions # ############################################################################################################# @@ -146,6 +153,11 @@ sub run_once # Check to see if we need to do boot-time tasks. We only run these if we've just booted boot_time_tasks($anvil); + if ($anvil->data->{switches}{'startup-only'}) + { + $anvil->nice_exit({code => 0}); + } + return(0); } @@ -214,6 +226,26 @@ AND # Clear the reboot request. $reboot_needed = $anvil->System->reboot_needed({set => 0}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { reboot_needed => $reboot_needed }}); + + # Check to see if there was a reboot job in progress. If so, finish it off. + my $job_uuid = $anvil->Job->get_job_uuid({debug => 2, program => "anvil-manage-power"}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); + + if ($job_uuid) + { + # Update the percentage to '100' and then clear the old PID. + my $date_time = $anvil->Get->date_and_time(); + if ($anvil->data->{jobs}{job_uuid}) + { + $anvil->Job->update_progress({ + debug => 2, + progress => 100, + message => "message_0064,!!date_and_time!".$date_time."!!", + job_uuid => $job_uuid + }); + } + $anvil->Job->clear({job_uuid => $job_uuid}); + } } return(0); @@ -261,7 +293,7 @@ sub keep_running # Free up memory $anvil->data->{jobs}{handles}{$job_uuid}->cleanup(); - clear_job($anvil, $job_uuid); + $anvil->Job->clear({job_uuid => $job_uuid}); } } } @@ -275,26 +307,6 @@ sub keep_running return(0); } -# This clears the 'job_picked_up_by'. -sub clear_job -{ - my ($anvil, $job_uuid) = @_; - - my $query = " -UPDATE - jobs -SET - job_picked_up_by = '0', - 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 => 2, list => { query => $query }}); - $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); - - return(0); -} - # This will check for any jobs that aren't at 100%. For each found, if 'picked_up_by' is set, a check is made # to see if the PID is still alive. If it isn't, or if 'picked_up_by' is not set, the appropriate tool is # invoked to handle it. @@ -310,7 +322,7 @@ sub run_jobs my $jobs_file = "{\"jobs\":[\n"; # Get a list of pending or incomplete jobs. - my $return = $anvil->Database->get_jobs({debug => 2, ended_within => 300}); + my $return = $anvil->Database->get_jobs({ended_within => 300}); my $count = @{$return}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'return' => $return, @@ -364,7 +376,7 @@ sub run_jobs if (not exists $anvil->data->{pids}{$job_picked_up_by}) { # If the job is done, just clear the 'job_picked_up_by' and be done. - clear_job($anvil, $job_uuid); + $anvil->Job->clear({job_uuid => $job_uuid}); if ($job_progress ne "100") { # The previous job is gone, but the job isn't finished. Start it again. diff --git a/tools/anvil-manage-power b/tools/anvil-manage-power index b358b2f0..4c279cc4 100755 --- a/tools/anvil-manage-power +++ b/tools/anvil-manage-power @@ -70,7 +70,7 @@ if (not $anvil->data->{sys}{database}{connections}) if ($anvil->data->{switches}{'reboot'}) { # Did the user confirm? - if ($anvil->data->{switches}{'reboot'} =~ /^y/i) + if ($anvil->data->{switches}{'y'}) { do_poweroff($anvil, "reboot"); } @@ -95,7 +95,7 @@ if ($anvil->data->{switches}{'reboot'}) if ($anvil->data->{switches}{'poweroff'}) { # Did the user confirm? - if ($anvil->data->{switches}{'poweroff'} =~ /^y/i) + if ($anvil->data->{switches}{'y'}) { do_poweroff($anvil, "poweroff"); } @@ -178,19 +178,51 @@ $anvil->nice_exit({exit_code => 0}); # Private functions. # ############################################################################################################# -# This does a reboot, clearing the flag indicating a reboot is required in the process. +# This does a reboot or power off sub do_poweroff { my ($anvil, $task) = @_; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { task => $task }}); my $say_task = $task eq "poweroff" ? "message_0062" : "message_0063"; + my $percent = $task eq "poweroff" ? 100 : 50; print $anvil->Words->string({key => $say_task})."\n"; - # Clear the "reboot needed" flag. - $reboot_needed = $anvil->System->reboot_needed({set => 0}); + # If I don't have a job_uuid, try to find one. + my $job_uuid = ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }}); + if ($anvil->data->{switches}{'job-uuid'}) + { + $job_uuid = $anvil->data->{switches}{'job-uuid'}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); + } + else + { + $job_uuid = $anvil->Job->get_job_uuid({debug => 2, program => $THIS_FILE}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); + } + + if ($job_uuid) + { + $anvil->Job->clear({job_uuid => $job_uuid}); + $anvil->Job->update_progress({ + debug => 2, + progress => $percent, + message => $say_task, + job_uuid => $job_uuid, + }); + } + + # Make sure the 'reboot needed' flag is set. When 'anvil-daemon' starts, it will use this to confirm + # that it is starting post-reboot and clear it. + $reboot_needed = $anvil->System->reboot_needed({set => 1}); - # Set the progress to '50%' (anvil-daemon will set it to 100% when it starts post-boot). + # Now do the deed. + my $shell_call = $anvil->data->{path}{exe}{systemctl}." ".$task; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); + my $output = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); + # Unlikely we're still alive, but 'poweroff' and 'reboot' do return once enqueued, so... + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); $anvil->nice_exit({exit_code => 0}); } diff --git a/tools/anvil-update-system b/tools/anvil-update-system index a30b5dd2..d937082f 100755 --- a/tools/anvil-update-system +++ b/tools/anvil-update-system @@ -58,31 +58,8 @@ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list if (not $anvil->data->{switches}{'job-uuid'}) { # See if a job is waiting to run. - my $query = " -SELECT - job_uuid -FROM - jobs -WHERE - job_command LIKE '".$THIS_FILE."%' -AND - job_progress != '100' -AND - job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." -;"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, 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 => 2, list => { - results => $results, - count => $count, - }}); - if ($count == 1) - { - # Found it - $anvil->data->{jobs}{job_uuid} = defined $results->[0]->[0] ? $results->[0]->[0] : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }}); - } + $anvil->data->{switches}{job_uuid} = $anvil->Job->get_job_uuid({debug => 2, program => $THIS_FILE}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "switches::job-uuid" => $anvil->data->{switches}{'job-uuid'} }}); } if ($anvil->data->{switches}{'job-uuid'}) { @@ -199,8 +176,8 @@ sub update_progress debug => 2, progress => $progress, message => $message, - job_uuid => $anvil->data->{jobs}{job_uuid}}, - ); + job_uuid => $anvil->data->{jobs}{job_uuid}, + }); } return(0);