* Adding a new Database->insert_or_update_jobs() method and associated database tables.

* Fixed display issues when showing a summary of what will be done if the user confirms the reconfiguration of the Striker.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent 9648e8ba43
commit 5976e7ea32
  1. 293
      Anvil/Tools/Database.pm
  2. 2
      Anvil/Tools/Template.pm
  3. 37
      cgi-bin/home
  4. 32
      html/skins/alteeve/main.html
  5. 63
      tools/anvil.sql
  6. 3
      tools/words.xml

@ -22,6 +22,8 @@ my $THIS_FILE = "Database.pm";
# get_local_id
# initialize
# insert_or_update_hosts
# insert_or_update_jobs
# insert_or_update_network_interfaces
# insert_or_update_states
# insert_or_update_variables
# lock_file
@ -1440,6 +1442,297 @@ WHERE
}
=head2 insert_or_update_jobs
This updates (or inserts) a record in the 'jobs' table. The C<< job_uuid >> referencing the database row will be returned.
If there is an error, an empty string is returned.
Parameters;
=head3 job_uuid (optional)
This is the C<< job_uuid >> to update. If it is not specified but the C<< job_name >> is, a check will be made to see if an entry already exists. If so, that row will be UPDATEd. If not, a random UUID will be generated and a new entry will be INSERTed.
* This or C<< job_name >> must be passed
=head3 job_name (required*)
This is the C<< job_name >> to INSERT or UPDATE. If a C<< job_uuid >> is passed, then the C<< job_name >> can be changed.
* This or C<< job_uuid >> must be passed
=head3 job_host_uuid (optional)
This is the host's UUID that this job entry belongs to. If not passed, C<< sys::host_uuid >> will be used.
=head3 job_progress (required)
This is a numeric value between C<< 0 >> and C<< 100 >>. The job will update this as it runs, with C<< 100 >> indicating that the job is complete. A value of C<< 0 >> will indicate that the job needs to be started. When the daemon picks up the job, it will set this to C<< 1 >>. Any value in between is set by the job itself.
=head3 job_title (required*)
This is a string key to display in the title of the box showing that the job is running.
Variables can not be passed to this title key.
* This is not required when C<< update_progress_only >> is set
=head3 job_description (required*)
This is a string key to display in the body of the box showing that the job is running.
Variables can not be passed to this title key.
* This is not required when C<< update_progress_only >> is set
=cut
sub insert_or_update_jobs
{
my $self = shift;
my $parameter = shift;
my $anvil = $self->parent;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0125", variables => { method => "Database->insert_or_update_jobs()" }});
my $job_uuid = defined $parameter->{job_uuid} ? $parameter->{job_uuid} : "";
my $job_host_uuid = defined $parameter->{job_host_uuid} ? $parameter->{job_host_uuid} : $anvil->data->{sys}{host_uuid};
my $job_type = defined $parameter->{job_type} ? $parameter->{job_type} : "";
my $job_name = defined $parameter->{job_name} ? $parameter->{job_name} : "";
my $job_progress = defined $parameter->{job_progress} ? $parameter->{job_progress} : "";
my $job_title = defined $parameter->{job_title} ? $parameter->{job_title} : "";
my $job_description = defined $parameter->{job_description} ? $parameter->{job_description} : "";
my $update_progress_only = defined $parameter->{update_progress_only} ? $parameter->{update_progress_only} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
job_uuid => $job_uuid,
job_host_uuid => $job_host_uuid,
job_type => $job_type,
job_name => $job_name,
job_progress => $job_progress,
job_title => $job_title,
job_description => $job_description,
update_progress_only => $update_progress_only,
}});
# If I have a job_uuid and update_progress_only is true, I only need the progress.
my $problem = 0;
# Do I have a valid progress?
if (($job_progress !~ /^\d/) or ($job_progress < 0) or ($job_progress > 100))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0138", variables => { method => "Database->insert_or_update_jobs()", job_progress => $job_progress }});
$problem = 1;
}
# Make sure I have the either a valid job UUID or a name
if ((not $anvil->Validate->is_uuid({uuid => $job_uuid})) && (not $job_name))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0136", variables => {
method => "Database->insert_or_update_jobs()",
job_name => $job_name,
job_uuid => $job_uuid,
}});
$problem = 1;
}
# Unless I am updating the progress, make sure everything is passed.
if (not $update_progress_only)
{
# Everything is required, except 'job_uuid'. So, job type?
if (not $job_type)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_jobs()", parameter => "job_type" }});
$problem = 1;
}
elsif (($job_type ne "normal") && ($job_type ne "slow"))
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0137", variables => {
method => "Database->insert_or_update_jobs()",
module => "Database",
variable_name => "job_type",
variable_value => $job_type,
}});
$problem = 1;
}
# Job name?
if (not $job_name)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_jobs()", parameter => "job_name" }});
$problem = 1;
}
# Job name?
if (not $job_title)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_jobs()", parameter => "job_title" }});
$problem = 1;
}
# Job description?
if (not $job_description)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->insert_or_update_jobs()", parameter => "job_description" }});
$problem = 1;
}
}
# We're done if there was a problem
if ($problem)
{
return("");
}
# If we don't have a UUID, see if we can find one for the given job server name.
if (not $job_uuid)
{
my $query = "
SELECT
job_uuid
FROM
jobs
WHERE
job_name = ".$anvil->data->{sys}{use_db_fh}->quote($job_name)."
AND
job_host_uuid = ".$anvil->data->{sys}{use_db_fh}->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})
{
$job_uuid = $row->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
}
}
# If I still don't have an job_uuid, we're INSERT'ing .
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_uuid => $job_uuid }});
if (not $job_uuid)
{
# It's possible that this is called before the host is recorded in the database. So to be
# safe, we'll return without doing anything if there is no host_uuid in the database.
my $hosts = $anvil->Database->get_hosts();
my $found = 0;
foreach my $hash_ref (@{$hosts})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"hash_ref->{host_uuid}" => $hash_ref->{host_uuid},
"sys::host_uuid" => $anvil->data->{sys}{host_uuid},
}});
if ($hash_ref->{host_uuid} eq $anvil->data->{sys}{host_uuid})
{
$found = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { found => $found }});
}
}
if (not $found)
{
# We're out.
return("");
}
# INSERT
$job_uuid = $anvil->Get->uuid();
my $query = "
INSERT INTO
jobs
(
job_uuid,
job_host_uuid,
job_type,
job_name,
job_progress,
job_title,
job_description,
modified_date
) VALUES (
".$anvil->data->{sys}{use_db_fh}->quote($job_uuid).",
".$anvil->data->{sys}{use_db_fh}->quote($job_host_uuid).",
".$anvil->data->{sys}{use_db_fh}->quote($job_type).",
".$anvil->data->{sys}{use_db_fh}->quote($job_name).",
".$anvil->data->{sys}{use_db_fh}->quote($job_progress).",
".$anvil->data->{sys}{use_db_fh}->quote($job_title).",
".$anvil->data->{sys}{use_db_fh}->quote($job_description).",
".$anvil->data->{sys}{use_db_fh}->quote($anvil->data->{sys}{db_timestamp})."
);
";
$query =~ s/'NULL'/NULL/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
}
else
{
# Query the rest of the values and see if anything changed.
my $query = "
SELECT
job_host_uuid,
job_type,
job_name,
job_progress,
job_title,
job_description
FROM
jobs
WHERE
job_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($job_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, 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 => 3, list => {
results => $results,
count => $count,
}});
foreach my $row (@{$results})
{
my $old_job_host_uuid = $row->[0];
my $old_job_type = $row->[1];
my $old_job_name = $row->[2];
my $old_job_progress = $row->[3];
my $old_job_title = $row->[4];
my $old_job_description = $row->[5];
my $old_job_note = $row->[6];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
old_job_name => $old_job_name,
old_job_host_uuid => $old_job_host_uuid,
old_job_note => $old_job_note,
}});
# Anything change?
if (($old_job_name ne $job_name) or
($old_job_host_uuid ne $job_host_uuid) or
($old_job_note ne $job_note))
{
# Something changed, save.
my $query = "
UPDATE
jobs
SET
job_name = ".$anvil->data->{sys}{use_db_fh}->quote($job_name).",
job_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($job_host_uuid).",
job_note = ".$anvil->data->{sys}{use_db_fh}->quote($job_note).",
modified_date = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->data->{sys}{db_timestamp})."
WHERE
job_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($job_uuid)."
";
$query =~ s/'NULL'/NULL/g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }});
$anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
}
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_uuid => $job_uuid }});
return($job_uuid);
}
=head2 insert_or_update_network_interfaces
This updates (or inserts) a record in the 'interfaces' table. This table is used to store physical network interface information.

@ -125,7 +125,7 @@ sub get
my $file = defined $parameter->{file} ? $parameter->{file} : "";
my $language = defined $parameter->{language} ? $parameter->{language} : $anvil->Words->language;
my $name = defined $parameter->{name} ? $parameter->{name} : "";
my $show_name = defined $parameter->{show_name} ? $parameter->{show_name} : 0;
my $show_name = defined $parameter->{show_name} ? $parameter->{show_name} : 1;
my $skin = defined $parameter->{skin} ? $parameter->{skin} : $anvil->Template->skin;
my $variables = defined $parameter->{variables} ? $parameter->{variables} : "";
$skin = $anvil->data->{path}{directories}{skins}."/".$skin;

@ -79,6 +79,10 @@ $anvil->Get->cgi();
$anvil->data->{skin}{url} = $anvil->data->{path}{urls}{skins}."/".$anvil->Template->skin;
my $header = $anvil->Template->get({file => "main.html", name => "header", variables => { language => $anvil->Words->language }});
my $body = "";
# If any jobs are pending/running, show the "unavailable" option.
my $available = check_availability($anvil);
# This will be true when the dashboard is unconfigured.
if (not $anvil->data->{cgi}{step}{value})
{
@ -91,7 +95,7 @@ elsif ($anvil->data->{cgi}{step}{value} eq "step1")
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }});
if ($sane)
{
# Step 1 was sanem show step 2.
# Step 1 was sane, show step 2.
$body = config_step2($anvil);
}
else
@ -104,10 +108,10 @@ elsif ($anvil->data->{cgi}{step}{value} eq "step2")
{
# Sanity check step1.
my $sane = sanity_check_step2($anvil);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }});
if ($sane)
{
# Step 1 was sanem show step 2.
# Step 2 was sane, show step 3.
$body = config_step3($anvil);
}
else
@ -116,6 +120,11 @@ elsif ($anvil->data->{cgi}{step}{value} eq "step2")
$body = config_step2($anvil);
}
}
elsif ($anvil->data->{cgi}{step}{value} eq "step3")
{
# User has confirmed, update the system!
update_system($anvil);
}
else
{
$body = get_network_details_form($anvil);
@ -146,6 +155,27 @@ $anvil->nice_exit({exit_code => 0});
# Functions #
#############################################################################################################
# This sets a flag that disables this dashboard and requests the reconfiguration of this system.
sub update_system
{
my ($anvil) = @_;
return(0);
}
# This checks to see if anything is running that requires Striker being unavailable. If not, this returns
# '1'. If there is a job pending/running, it returns '0'
sub check_availability
{
my ($anvil) = @_;
my $available = 1;
return($available);
}
# This shows the user what is about to be done and asks the user to confirm.
sub config_step3
{
@ -284,6 +314,7 @@ ORDER BY
striker_password => $anvil->data->{cgi}{striker_password}{value},
networks => $networks,
cgi_list => $cgi."step",
show_name => 1,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { step3_body => $step3_body }});

@ -309,7 +309,7 @@
</tr>
<tr>
<td>
#!string!striker_0024!#:
&nbsp; &bull; #!string!striker_0024!#:
</td>
<td class="column_row_value_fixed">
#!variable!ip_address!#
@ -317,13 +317,15 @@
</tr>
<tr>
<td>
#!string!striker_0029!#:
&nbsp; &bull; #!string!striker_0029!#:
</td>
<td class="column_row_value_fixed">
#!variable!primary!#
</td>
</tr>
<tr>
<td>
#!string!striker_0030!#:
&nbsp; &bull; #!string!striker_0030!#:
</td>
<td class="column_row_value_fixed">
#!variable!backup!#
@ -342,7 +344,7 @@
</tr>
<tr>
<td>
#!string!striker_0024!#:
&nbsp; &bull; #!string!striker_0024!#:
</td>
<td class="column_row_value_fixed">
#!variable!ip_address!#
@ -350,7 +352,7 @@
</tr>
<tr>
<td>
#!string!striker_0026!#:
&nbsp; &bull; #!string!striker_0026!#:
</td>
<td class="column_row_value_fixed">
#!variable!gateway!#
@ -358,7 +360,7 @@
</tr>
<tr>
<td>
#!string!striker_0027!#:
&nbsp; &bull; #!string!striker_0027!#:
</td>
<td class="column_row_value_fixed">
#!variable!dns!#
@ -366,13 +368,15 @@
</tr>
<tr>
<td>
#!string!striker_0029!#:
&nbsp; &bull; #!string!striker_0029!#:
</td>
<td class="column_row_value_fixed">
#!variable!primary!#
</td>
</tr>
<tr>
<td>
#!string!striker_0030!#:
&nbsp; &bull; #!string!striker_0030!#:
</td>
<td class="column_row_value_fixed">
#!variable!backup!#
@ -391,7 +395,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0024!#:
&nbsp; &bull; #!string!striker_0024!#:
</td>
<td class="column_row_value_fixed">
#!variable!ip_address!#
@ -399,7 +403,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0028!#:
&nbsp; &bull; #!string!striker_0028!#:
</td>
<td class="column_row_value_fixed">
#!variable!primary!#
@ -418,7 +422,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0024!#:
&nbsp; &bull; #!string!striker_0024!#:
</td>
<td class="column_row_value_fixed">
#!variable!ip_address!#
@ -426,7 +430,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0026!#:
&nbsp; &bull; #!string!striker_0026!#:
</td>
<td class="column_row_value_fixed">
#!variable!gateway!#
@ -434,7 +438,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0027!#:
&nbsp; &bull; #!string!striker_0027!#:
</td>
<td class="column_row_value_fixed">
#!variable!dns!#
@ -442,7 +446,7 @@
</tr>
<tr>
<td class="column_subrow_name">
#!string!striker_0028!#:
&nbsp; &bull; #!string!striker_0028!#:
</td>
<td class="column_row_value_fixed">
#!variable!primary!#

@ -273,6 +273,69 @@ CREATE TRIGGER trigger_variables
FOR EACH ROW EXECUTE PROCEDURE history_variables();
-- This holds jobs to be run.
CREATE TABLE jobs (
job_uuid uuid not null primary key, --
job_host_uuid uuid not null, -- This is the host that requested the job
job_type text not null, -- This indicates which daemon should run this job ('normal' = anvil_daemon, 'slow' = anvil_jobs)
job_name text not null, -- This is the 'x::y::z' style job name.
job_progress numeric not null, -- An "approximate" percentage completed
job_title text not null, -- This is a word key for the title of this job
job_description text not null, -- This is a word key that describes this job.
modified_date timestamp with time zone not null,
FOREIGN KEY(job_host_uuid) REFERENCES hosts(host_uuid)
);
ALTER TABLE jobs OWNER TO #!job!user!#;
CREATE TABLE history.jobs (
history_id bigserial,
job_uuid uuid,
job_host_uuid uuid,
job_type text,
job_name text,
job_progress numeric,
job_title text,
job_description text,
modified_date timestamp with time zone not null
);
ALTER TABLE history.jobs OWNER TO #!job!user!#;
CREATE FUNCTION history_jobs() RETURNS trigger
AS $$
DECLARE
history_jobs RECORD;
BEGIN
SELECT INTO history_jobs * FROM jobs WHERE job_uuid = new.job_uuid;
INSERT INTO history.jobs
(job_uuid,
job_host_uuid,
job_type,
job_name,
job_progress,
job_title,
job_description,
modified_date)
VALUES
(history_jobs.job_uuid,
history_jobs.job_host_uuid,
history_jobs.job_type,
history_jobs.job_name,
history_jobs.job_progress,
history_jobs.job_title,
history_jobs.job_description,
history_jobs.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_jobs() OWNER TO #!job!user!#;
CREATE TRIGGER trigger_jobs
AFTER INSERT OR UPDATE ON jobs
FOR EACH ROW EXECUTE PROCEDURE history_jobs();
-- ------------------------------------------------------------------------------------------------------- --
-- These are special tables with no history or tracking UUIDs that simply record transient information. --
-- ------------------------------------------------------------------------------------------------------- --

@ -206,6 +206,9 @@ The database connection error was:
<key name="log_0133">Failed to read the system UUID. Received a non-UUID string: [#!variable!uuid!#]. Is the user: [#!variable!user!#] in the 'kmem' group?</key>
<key name="log_0134">The read host UUID: [#!variable!uuid!#] does not appear to be a valid UUID.</key>
<key name="log_0135">Runtime was approximately: [#!variable!runtime!#] seconds.</key>
<key name="log_0136"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with either 'job_uuid': [#!variable!job_uuid!#] not being passed (or was not a valid UUID), or 'job_name': [#!variable!job_name!#] not being passed.]]></key>
<key name="log_0137"><![CDATA[[ Error ] - The method: [#!variable!method!#] was called with an invalid value for: [#!variable!variable_name!#]: -> [#!variable!variable_value!#]. See 'perldoc Anvil::Tools::#!variable!module!#' for valid options.]]></key>
<key name="log_0138"><![CDATA[[ Error ] - The method: [#!variable!method!#] was with an invalid 'job_progress': [#!variable!job_progress!#]. It needs to be a whole-number value between 0 and 100, inclusive.]]></key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key>

Loading…
Cancel
Save