* Created Database->get_jobs() to be a more general way to retrieve pending and recently finished jobs.

* Started adding the display of running and recently finished jobs to Striker when in maintenance mode. Still lots to do.
* Started working on the logic for what will soon be Words->decypher_string in anvil-daemon to process strings stored as '<key>,!!<name1>!<value1>!!,...,!!<nameN>!<valueN>!!'.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent bd862b2e5e
commit 60584b8cee
  1. 117
      Anvil/Tools/Database.pm
  2. 2
      cgi-bin/striker
  3. 11
      html/skins/alteeve/main.css
  4. 28
      html/skins/alteeve/striker.html
  5. 4
      share/words.xml
  6. 119
      tools/anvil-daemon
  7. 29
      tools/anvil-update-system

@ -20,6 +20,7 @@ my $THIS_FILE = "Database.pm";
# connect # connect
# disconnect # disconnect
# get_hosts # get_hosts
# get_jobs
# get_local_uuid # get_local_uuid
# initialize # initialize
# insert_or_update_bridges # insert_or_update_bridges
@ -1275,6 +1276,122 @@ FROM
$anvil->data->{sys}{hosts}{by_name}{$host_name} = $host_uuid; $anvil->data->{sys}{hosts}{by_name}{$host_name} = $host_uuid;
} }
my $return_count = @{$return};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_count => $return_count }});
return($return);
}
=head2 get_jobs
This gets the list of running jobs.
Parameters;
=head3 ended_within (optional, default 300)
Jobs that reached 100% within this number of seconds ago will be included. If this is set to C<< 0 >>, only in-progress and not-yet-picked-up jobs will be included.
=head3 job_host_uuid (default $anvil->Get->host_uuid)
This is the host that we're getting a list of jobs from.
=cut
sub get_jobs
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
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;
my $query = "
SELECT
job_uuid,
job_command,
job_data,
job_picked_up_by,
job_picked_up_at,
job_updated,
job_name,
job_progress,
job_title,
job_description,
job_status,
modified_date
FROM
jobs
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 }});
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,
}});
foreach my $row (@{$results})
{
my $job_uuid = $row->[0];
my $job_command = $row->[1];
my $job_data = defined $row->[2] ? $row->[2] : "";
my $job_picked_up_by = $row->[3];
my $job_picked_up_at = $row->[4];
my $job_updated = $row->[5];
my $job_name = $row->[6];
my $job_progress = $row->[7];
my $job_title = $row->[8];
my $job_description = $row->[9];
my $job_status = $row->[10];
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 => {
job_uuid => $job_uuid,
job_command => $job_command,
job_data => $job_data,
job_picked_up_by => $job_picked_up_by,
job_picked_up_at => $job_picked_up_at,
job_updated => $job_updated,
job_name => $job_name,
job_progress => $job_progress,
job_title => $job_title,
job_description => $job_description,
job_status => $job_status,
modified_date => $modified_date,
started_seconds_ago => $started_seconds_ago,
updated_seconds_ago => $updated_seconds_ago,
}});
# If the job is done, see if it was recently enough to care about it.
if (($job_progress eq "100") && ($updated_seconds_ago > $ended_within))
{
# Skip it
next;
}
push @{$return}, {
job_uuid => $job_uuid,
job_command => $job_command,
job_data => $job_data,
job_picked_up_by => $job_picked_up_by,
job_picked_up_at => $job_picked_up_at,
job_updated => $job_updated,
job_name => $job_name,
job_progress => $job_progress,
job_title => $job_title,
job_description => $job_description,
job_status => $job_status,
modified_date => $modified_date,
};
}
my $return_count = @{$return};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { return_count => $return_count }});
return($return); return($return);
} }

@ -792,11 +792,13 @@ sub check_availability
$available = 0; $available = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { available => $available }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { available => $available }});
my $jobs_list = "#!string!striker_0097!#";
$anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => { $anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => {
title_id => "", title_id => "",
message_id => "", message_id => "",
title => "#!string!striker_0046!#", title => "#!string!striker_0046!#",
description => $anvil->Words->string({key => "striker_0090", variables => { }}), description => $anvil->Words->string({key => "striker_0090", variables => { }}),
job_list => $jobs_list
}}); }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }});
} }

@ -91,6 +91,11 @@ table.data_table {
border: 1px solid #8f8f8f; border: 1px solid #8f8f8f;
border-radius: 4px; border-radius: 4px;
} }
table.centered {
margin: auto;
}
tr.data_row { tr.data_row {
border-top: 1px solid #5f5f5f; border-top: 1px solid #5f5f5f;
} }
@ -167,6 +172,12 @@ td.column_row_value_fixed_centered {
} }
.config_header2 { .config_header2 {
color: #f2f2f2;
text-align: center;
font-size: 1.5em;
}
.config_header3 {
color: #f2f2f2; color: #f2f2f2;
text-align: center; text-align: center;
font-size: 1em; font-size: 1em;

@ -186,21 +186,45 @@
<!-- end striker-login --> <!-- end striker-login -->
<!-- start striker-offline --> <!-- start striker-offline -->
<table> <table class="centered">
<tr>
<td>
&nbsp;
</td>
</tr>
<div id="striker-offline"> <div id="striker-offline">
<tr> <tr>
<td> <td>
<span name="#!variable!title_id!#" id="#!variable!title_id!#" class="config_header1">#!variable!title!#</span><br /> <span name="#!variable!title_id!#" id="#!variable!title_id!#" class="config_header1">#!variable!title!#</span><br />
<span name="#!variable!message_id!#" id="#!variable!message_id!#" class="config_header2">#!variable!description!#</span> <span name="#!variable!message_id!#" id="#!variable!message_id!#" class="config_header3">#!variable!description!#</span>
<br /> <br />
<hr> <hr>
<a href="/" class="button">#!string!striker_0053!#</a> <a href="/" class="button">#!string!striker_0053!#</a>
</td> </td>
</tr> </tr>
</div> </div>
<tr>
<td>
&nbsp;
</td>
</tr>
<div id="running-jobs">
<tr>
<td>
<span name="jobs-title" id="jobs-title" class="config_header2">#!string!header_0011!#</span><br />
<span name="jobs-message" id="jobs-message" class="config_header3">#!string!striker_0096!#</span>
<br />
<hr>
#!variable!job_list!#
</td>
</tr>
</div>
</table> </table>
<!-- end striker-offline --> <!-- end striker-offline -->
<!-- start job-details -->
<!-- end job-details -->
<!-- start striker-setup --> <!-- start striker-setup -->
<table align="center" class="striker_welcome"> <table align="center" class="striker_welcome">
<tr> <tr>

@ -365,7 +365,7 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="header_0008">Via network:</key> <key name="header_0008">Via network:</key>
<key name="header_0009">Peer Connections</key> <key name="header_0009">Peer Connections</key>
<key name="header_0010">Ping</key> <key name="header_0010">Ping</key>
<key name="header_0011"></key> <key name="header_0011">Jobs</key>
<!-- General strings shown in Striker --> <!-- General strings shown in Striker -->
<key name="striker_0001">Welcome! Lets setup your #!string!brand_0003!# dashboard...</key> <key name="striker_0001">Welcome! Lets setup your #!string!brand_0003!# dashboard...</key>
@ -463,6 +463,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="striker_0093">This machine needs to be rebooted. This option will restart the host operating system.</key> <key name="striker_0093">This machine needs to be rebooted. This option will restart the host operating system.</key>
<key name="striker_0094">Power off this Striker</key> <key name="striker_0094">Power off this Striker</key>
<key name="striker_0095">This will power off the Striker machine and leave it off. To power it back on, you will need physical access or cycle the power of the PDU feeding this Striker.</key> <key name="striker_0095">This will power off the Striker machine and leave it off. To power it back on, you will need physical access or cycle the power of the PDU feeding this Striker.</key>
<key name="striker_0096">Recent and Running Jobs</key>
<key name="striker_0097">There are no jobs currently running or recently completed.</key>
<!-- Strings used by jobs --> <!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key> <key name="job_0001">Configure Network</key>

@ -242,37 +242,27 @@ sub run_jobs
my $jobs_file = "{\"jobs\":[\n"; my $jobs_file = "{\"jobs\":[\n";
# Get a list of pending or incomplete jobs. # Get a list of pending or incomplete jobs.
my $query = " my $return = $anvil->Database->get_jobs({debug => 2, ended_within => 300});
SELECT my $count = @{$return};
job_uuid,
job_command,
job_data,
job_picked_up_by,
job_picked_up_at,
job_updated,
job_progress
FROM
jobs
WHERE
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 $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 => 2, list => {
results => $results, 'return' => $return,
count => $count, count => $count,
}}); }});
foreach my $row (@{$results}) foreach my $hash_ref (@{$return})
{ {
my $job_uuid = $row->[0]; my $job_uuid = $hash_ref->{job_uuid};
my $job_command = $row->[1]; my $job_command = $hash_ref->{job_command};
my $job_data = defined $row->[2] ? $row->[2] : ""; my $job_data = $hash_ref->{job_data};
my $job_picked_up_by = $row->[3]; my $job_picked_up_by = $hash_ref->{job_picked_up_by};
my $job_picked_up_at = $row->[4]; my $job_picked_up_at = $hash_ref->{job_picked_up_at};
my $job_updated = $row->[5]; my $job_updated = $hash_ref->{job_updated};
my $job_progress = $row->[6]; my $job_name = $hash_ref->{job_name};
my $job_progress = $hash_ref->{job_progress};
my $job_title = $hash_ref->{job_title};
my $job_description = $hash_ref->{job_description};
my $job_status = $hash_ref->{job_status};
my $started_seconds_ago = $job_picked_up_at ? (time - $job_picked_up_at) : 0; my $started_seconds_ago = $job_picked_up_at ? (time - $job_picked_up_at) : 0;
my $updated_seconds_ago = $job_updated ? (time - $job_updated) : 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 => 2, list => {
@ -287,22 +277,64 @@ WHERE
updated_seconds_ago => $updated_seconds_ago, updated_seconds_ago => $updated_seconds_ago,
}}); }});
# This will be appended to the json file # TODO: Make this a Words->decypher_string() method
my $json_string = "{ \"job_uuid\":\"".$job_uuid."\", \"job_command\":\"".$job_command."\", \"job_data\":\"".$job_data."\", \"job_picked_up_at\":\"".$job_picked_up_at."\", \"job_updated\":\"".$job_updated."\", \"job_progress\":\"".$job_progress."\", \"job_progress\":\"".$job_progress."\", \"started_seconds_ago\":\"".$started_seconds_ago."\", \"updated_seconds_ago\":\"".$updated_seconds_ago."\" }, \n"; my $say_progress = "";
if ($job_progress)
# If the job is done, see if it was recently enough to record in the jobs.json file.
if ($job_progress eq "100")
{ {
# Record in JSON if it wass last updated less than 5 minutes ago. foreach my $message (split/\n/, $job_progress)
if ($updated_seconds_ago < 300)
{ {
$jobs_file .= $json_string; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message => $message }});
if ($message =~ /^(.*?),(.*)$/)
{
my $key = $1;
my $variable_string = $2;
my $variables = {};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
key => $key,
variable_string => $variable_string,
}});
foreach my $pair (split/,/, $variable_string)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pair => $pair }});
my $name = "";
my $value = "";
if ($pair =~ /^!!(.*?)!(.*)!!$/)
{
$name = $1;
$value = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
name => $name,
value => $value,
}});
}
elsif ($pair =~ /^!!(.*?)!!!$/)
{
$name = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { name => $name }});
}
else
{
# what?!
}
$variables->{$name} = $value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "variables->$name" => $variables->{$name} }});
}
$say_progress = $anvil->Words->string({key => $key, variables => $variables}),
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "say_progress" => $say_progress }});
}
} }
next;
} }
# If we're here, the job isn't done. So first, record it. # Add this to the jobs.json file
$jobs_file .= $json_string; $jobs_file .= "{ \"job_uuid\":\"".$job_uuid."\",
\"job_command\":\"".$job_command."\",
\"job_data\":\"".$job_data."\",
\"job_picked_up_at\":\"".$job_picked_up_at."\",
\"job_updated\":\"".$job_updated."\",
\"job_progress\":\"".$job_progress."\",
\"started_seconds_ago\":\"".$started_seconds_ago."\",
\"updated_seconds_ago\":\"".$updated_seconds_ago."\" }, \n";
# See if the job was picked up by another running instance. # See if the job was picked up by another running instance.
if ($job_picked_up_by) if ($job_picked_up_by)
@ -336,20 +368,9 @@ WHERE
}); });
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "jobs::handles::${job_uuid}" => $anvil->data->{jobs}{handles}{$job_uuid} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "jobs::handles::${job_uuid}" => $anvil->data->{jobs}{handles}{$job_uuid} }});
# Record the PID # Log the PID (the job should update the database).
my $pid = $anvil->data->{jobs}{handles}{$job_uuid}->pid(); my $pid = $anvil->data->{jobs}{handles}{$job_uuid}->pid();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pid => $pid }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pid => $pid }});
my $query = "
UPDATE
jobs
SET
job_picked_up_by = ".$anvil->data->{sys}{database}{use_handle}->quote($pid).",
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__});
} }
} }

@ -117,8 +117,9 @@ update_progress($anvil, 0, "clear");
# Mark that we're starting # Mark that we're starting
print $THIS_FILE."; time: [".time."], running with PID: [".$$."]\n"; print $THIS_FILE."; time: [".time."], running with PID: [".$$."]\n";
update_progress($anvil, 1, "message_0033"); update_progress($anvil, 1, "message_0033");
sleep 60; sleep 10;
print $THIS_FILE."; time: [".time."], exiting\n"; print $THIS_FILE."; time: [".time."], exiting\n";
update_progress($anvil, 2, "message_0034");
exit; exit;
run_os_update($anvil); run_os_update($anvil);
@ -158,6 +159,7 @@ sub update_progress
{ {
# Get the current job_status and append this new one. # Get the current job_status and append this new one.
my $job_picked_up_by = $$; my $job_picked_up_by = $$;
my $job_picked_up_at = 0;
my $job_status = ""; my $job_status = "";
if ($message eq "clear") if ($message eq "clear")
{ {
@ -167,7 +169,8 @@ sub update_progress
{ {
my $query = " my $query = "
SELECT SELECT
job_status job_status,
job_picked_up_at
FROM FROM
jobs jobs
WHERE WHERE
@ -175,9 +178,22 @@ WHERE
;"; ;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $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_status = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$job_status = "" if not defined $job_status; $job_picked_up_at = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[1];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_status => $job_status }}); $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 }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message => $message }});
if ($job_status) if ($job_status)
@ -196,7 +212,8 @@ UPDATE
jobs jobs
SET SET
job_picked_up_by = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_by).", job_picked_up_by = ".$anvil->data->{sys}{database}{use_handle}->quote($job_picked_up_by).",
job_updated = ".time.", 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_progress = ".$anvil->data->{sys}{database}{use_handle}->quote($progress).",
job_status = ".$anvil->data->{sys}{database}{use_handle}->quote($job_status).", 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})." modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})."

Loading…
Cancel
Save