* Fixed a bug in Database->insert_or_update_jobs().

* Fixed some logging in Get->cgi() and generally cleaned up logging levels.
* Got striker to the point where the job to reconfigure the network is saved in the database and the dashboard goes offline until it is done.
* Created the start of the new anvil-configure-network tool.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent e38bc826dd
commit 7694847160
  1. 16
      Anvil/Tools/Database.pm
  2. 15
      Anvil/Tools/Get.pm
  3. 142
      cgi-bin/home
  4. 38
      html/skins/alteeve/main.html
  5. 8
      share/words.xml
  6. 33
      tools/anvil-configure-network
  7. 1
      tools/anvil-update-states

@ -1622,7 +1622,7 @@ sub insert_or_update_jobs
my $job_picked_up_at = defined $parameter->{job_picked_up_at} ? $parameter->{job_picked_up_at} : 0; my $job_picked_up_at = defined $parameter->{job_picked_up_at} ? $parameter->{job_picked_up_at} : 0;
my $job_updated = defined $parameter->{job_updated} ? $parameter->{job_updated} : 0; my $job_updated = defined $parameter->{job_updated} ? $parameter->{job_updated} : 0;
my $job_name = defined $parameter->{job_name} ? $parameter->{job_name} : ""; my $job_name = defined $parameter->{job_name} ? $parameter->{job_name} : "";
my $job_progress = defined $parameter->{job_progress} ? $parameter->{job_progress} : ""; my $job_progress = defined $parameter->{job_progress} ? $parameter->{job_progress} : 0;
my $job_title = defined $parameter->{job_title} ? $parameter->{job_title} : ""; my $job_title = defined $parameter->{job_title} ? $parameter->{job_title} : "";
my $job_description = defined $parameter->{job_description} ? $parameter->{job_description} : ""; my $job_description = defined $parameter->{job_description} ? $parameter->{job_description} : "";
my $update_progress_only = defined $parameter->{update_progress_only} ? $parameter->{update_progress_only} : 0; my $update_progress_only = defined $parameter->{update_progress_only} ? $parameter->{update_progress_only} : 0;
@ -1779,11 +1779,11 @@ INSERT INTO
".$anvil->data->{sys}{use_db_fh}->quote($job_uuid).", ".$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_host_uuid).",
".$anvil->data->{sys}{use_db_fh}->quote($job_command).", ".$anvil->data->{sys}{use_db_fh}->quote($job_command).",
".$anvil->data->{sys}{use_db_fh}->quote($job_name).",
".$anvil->data->{sys}{use_db_fh}->quote($job_data).", ".$anvil->data->{sys}{use_db_fh}->quote($job_data).",
".$anvil->data->{sys}{use_db_fh}->quote($job_picked_up_by).", ".$anvil->data->{sys}{use_db_fh}->quote($job_picked_up_by).",
".$anvil->data->{sys}{use_db_fh}->quote($job_picked_up_at).", ".$anvil->data->{sys}{use_db_fh}->quote($job_picked_up_at).",
".$anvil->data->{sys}{use_db_fh}->quote($job_updated).", ".$anvil->data->{sys}{use_db_fh}->quote($job_updated).",
".$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_progress).",
".$anvil->data->{sys}{use_db_fh}->quote($job_title).", ".$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($job_description).",
@ -3381,11 +3381,11 @@ sub resync_databases
my $self = shift; my $self = shift;
my $parameter = shift; my $parameter = shift;
my $anvil = $self->parent; my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 2; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->resync_databases()" }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->resync_databases()" }});
# If a resync isn't needed, just return. # If a resync isn't needed, just return.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'sys::database::resync_needed' => $anvil->data->{sys}{database}{resync_needed} }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'sys::database::resync_needed' => $anvil->data->{sys}{database}{resync_needed} }});
if (not $anvil->data->{sys}{database}{resync_needed}) if (not $anvil->data->{sys}{database}{resync_needed})
{ {
return(0); return(0);
@ -3511,7 +3511,7 @@ sub resync_databases
my $column_value = defined $row->[$column_number] ? $row->[$column_number] : "NULL"; my $column_value = defined $row->[$column_number] ? $row->[$column_number] : "NULL";
my $not_null = $anvil->data->{sys}{database}{table}{$table}{column}{$column_name}{not_null}; my $not_null = $anvil->data->{sys}{database}{table}{$table}{column}{$column_name}{not_null};
my $data_type = $anvil->data->{sys}{database}{table}{$table}{column}{$column_name}{data_type}; my $data_type = $anvil->data->{sys}{database}{table}{$table}{column}{$column_name}{data_type};
$anvil->Log->variables({source => 2, line => __LINE__, level => 3, list => { $anvil->Log->variables({source => 2, line => __LINE__, level => $debug, list => {
"s1:id" => $id, "s1:id" => $id,
"s2:row_number" => $row_number, "s2:row_number" => $row_number,
"s3:column_number" => $column_number, "s3:column_number" => $column_number,
@ -3523,14 +3523,14 @@ sub resync_databases
if (($not_null) && ($column_value eq "NULL")) if (($not_null) && ($column_value eq "NULL"))
{ {
$column_value = ""; $column_value = "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { column_value => $column_value }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { column_value => $column_value }});
} }
# The modified_date should be the first row. # The modified_date should be the first row.
if ($column_name eq "modified_date") if ($column_name eq "modified_date")
{ {
$modified_date = $column_value; $modified_date = $column_value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { modified_date => $modified_date }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { modified_date => $modified_date }});
next; next;
} }
@ -3538,7 +3538,7 @@ sub resync_databases
if ($column_name eq $uuid_column) if ($column_name eq $uuid_column)
{ {
$row_uuid = $column_value; $row_uuid = $column_value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { row_uuid => $row_uuid }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { row_uuid => $row_uuid }});
# This is used to determine if a given entry needs to be # This is used to determine if a given entry needs to be
# updated or inserted into the public schema # updated or inserted into the public schema

@ -262,8 +262,8 @@ sub cgi
# This is a pretty way of displaying the passed-in CGI variables. It loops through all we've got and # This is a pretty way of displaying the passed-in CGI variables. It loops through all we've got and
# sorts out the longest variable name. Then it loops again, appending '.' to shorter ones so that # sorts out the longest variable name. Then it loops again, appending '.' to shorter ones so that
# everything is lined up in the logs. # everything is lined up in the logs. This almost always prints, save for log level 0.
if ($anvil->Log->level >= $debug) if ($anvil->Log->level >= 1)
{ {
my $longest_variable = 0; my $longest_variable = 0;
foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cgi}}) foreach my $variable (sort {$a cmp $b} keys %{$anvil->data->{cgi}})
@ -303,8 +303,15 @@ sub cgi
} }
$say_value .= " "; $say_value .= " ";
} }
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { # This is always '1' as the passed-in variables are what we want to see.
"cgi::${variable}::$say_value" => $anvil->data->{cgi}{$variable}{value}, my $censored_value = $anvil->data->{cgi}{$variable}{value};
if ((($variable =~ /passwd/) or ($variable =~ /password/)) && (not $anvil->Log->secure))
{
# This is a password and we're not logging sensitive data, obfuscate it.
$censored_value = "--";
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 1, list => {
"cgi::${variable}::$say_value" => $censored_value,
}}); }});
} }
} }

@ -29,11 +29,8 @@ print $anvil->Template->get({file => "shared.html", name => "http_headers"})."\n
# Set the log level to 2. Setting 3 slows he program down a LOT. # Set the log level to 2. Setting 3 slows he program down a LOT.
$anvil->Log->level({set => 2}); $anvil->Log->level({set => 2});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { testing => "123" }});
# Read the config and then connect to the database. # Read the config and then connect to the database.
$anvil->Storage->read_config({file => "/etc/anvil/anvil.conf", debug => 2}); $anvil->Storage->read_config({file => "/etc/anvil/anvil.conf"});
# Make sure I can read the host UUID. # Make sure I can read the host UUID.
if (not $anvil->Get->host_uuid) if (not $anvil->Get->host_uuid)
@ -85,53 +82,60 @@ my $body = "";
# If any jobs are pending/running, show the "unavailable" option. # If any jobs are pending/running, show the "unavailable" option.
my $available = check_availability($anvil); my $available = check_availability($anvil);
if (not $available)
# This will be true when the dashboard is unconfigured.
if (not $anvil->data->{cgi}{step}{value})
{ {
$body = config_step1($anvil); # Set the body to 'say::maintenance'.
$body = $anvil->data->{say}{maintenance};
} }
elsif ($anvil->data->{cgi}{step}{value} eq "step1") else
{ {
# Sanity check step1. # This will be true when the dashboard is unconfigured.
my $sane = sanity_check_step1($anvil); if (not $anvil->data->{cgi}{step}{value})
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }});
if ($sane)
{ {
# Step 1 was sane, show step 2. $body = config_step1($anvil);
$body = config_step2($anvil);
} }
else elsif ($anvil->data->{cgi}{step}{value} eq "step1")
{ {
# No good # Sanity check step1.
$body = config_step1($anvil); my $sane = sanity_check_step1($anvil);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { sane => $sane }});
if ($sane)
{
# Step 1 was sane, show step 2.
$body = config_step2($anvil);
}
else
{
# No good
$body = config_step1($anvil);
}
} }
} elsif ($anvil->data->{cgi}{step}{value} eq "step2")
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 => 2, list => { sane => $sane }});
if ($sane)
{ {
# Step 2 was sane, show step 3. # Sanity check step1.
$body = config_step3($anvil); my $sane = sanity_check_step2($anvil);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { sane => $sane }});
if ($sane)
{
# Step 2 was sane, show step 3.
$body = config_step3($anvil);
}
else
{
# No good
$body = config_step2($anvil);
}
}
elsif ($anvil->data->{cgi}{step}{value} eq "step3")
{
# User has confirmed, update the system!
$body = save_job($anvil);
} }
else else
{ {
# No good $body = get_network_details_form($anvil);
$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);
}
my $buttons = $anvil->Template->get({file => "main.html", name => "button_bar"}); my $buttons = $anvil->Template->get({file => "main.html", name => "button_bar"});
my $footer = $anvil->Template->get({file => "main.html", name => "footer"}); my $footer = $anvil->Template->get({file => "main.html", name => "footer"});
@ -158,25 +162,69 @@ $anvil->nice_exit({exit_code => 0});
# Functions # # Functions #
############################################################################################################# #############################################################################################################
# This sets a flag that disables this dashboard and requests the reconfiguration of this system. # This checks to see if anything is running that requires Striker being unavailable. If not, this returns
sub update_system # '1'. If there is a job pending/running, it returns '0'
sub check_availability
{ {
my ($anvil) = @_; my ($anvil) = @_;
my $available = 1;
my $query = "SELECT count(*) FROM jobs WHERE job_name = 'configure::network' AND job_progress != 100 AND job_host_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
return(0); my $count = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }});
if ($count)
{
# We're waiting for the network configuration
$available = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { available => $available }});
$anvil->data->{say}{maintenance} = $anvil->Template->get({file => "main.html", name => "striker-offline", variables => {
title_id => "",
message_id => "",
title => "#!string!striker_0046!#",
description => "#!string!striker_0047!#",
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }});
}
return($available);
} }
# This checks to see if anything is running that requires Striker being unavailable. If not, this returns # This requests the job to reconfigure the network be run
# '1'. If there is a job pending/running, it returns '0' sub save_job
sub check_availability
{ {
my ($anvil) = @_; my ($anvil) = @_;
my $available = 1; # Record the job!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
file => $THIS_FILE,
line => __LINE__,
job_command => "anvil-configure-network",
job_data => "form::config_step2",
job_name => "configure::network",
job_title => "job_0001",
job_description => "job_0002",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
# TODO: Check that a job_uuid was returned and warn of a problem if not.
my $say_title = "#!string!striker_0044!#";
my $say_desciption = "#!string!striker_0045!#";
return($available); # We don't need to store anything as hidden variables, we'll read it back from the database later.
my $job_recorded_body = $anvil->Template->get({file => "main.html", name => "network_job_recorded", variables => {
title_id => "",
message_id => "",
title => $say_title,
description => $say_desciption,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_recorded_body => $job_recorded_body }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }});
return($job_recorded_body);
} }
# This shows the user what is about to be done and asks the user to confirm. # This shows the user what is about to be done and asks the user to confirm.
@ -308,7 +356,7 @@ ORDER BY
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "striker_warning_0001"}) }}); $anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "striker_warning_0001"}) }});
} }
# # We don't need to store anything as hidden variables, we'll read it back from the database later.
my $step3_body = $anvil->Template->get({file => "main.html", name => "config_step3", variables => { my $step3_body = $anvil->Template->get({file => "main.html", name => "config_step3", variables => {
step1_welcome_title_id => "", step1_welcome_title_id => "",
step1_welcome_message_id => "", step1_welcome_message_id => "",

@ -251,7 +251,6 @@
#!variable!organization!# #!variable!organization!#
</td> </td>
</tr> </tr>
<input type="hidden" name="organization" id="organization" value="#!variable!organization!#">
<!-- Domain name --> <!-- Domain name -->
<tr> <tr>
<td class="column_row_name"> <td class="column_row_name">
@ -261,7 +260,6 @@
#!variable!domain!# #!variable!domain!#
</td> </td>
</tr> </tr>
<input type="hidden" name="domain" id="domain" value="#!variable!domain!#">
<!-- User --> <!-- User -->
<tr> <tr>
<td class="column_row_name"> <td class="column_row_name">
@ -293,18 +291,40 @@
</td> </td>
</tr> </tr>
<!-- NOTE: For now, we support only one BCN in the web UI, but the system will be ready for N-number later. --> <!-- NOTE: For now, we support only one BCN in the web UI, but the system will be ready for N-number later. -->
<input type="hidden" name="step" id="step" value="step3"> <input type="hidden" name="step" id="step" value="step3">
<input type="hidden" name="cgi_list" id="cgi_list" value="next,step,#!variable!cgi_list!#"> <input type="hidden" name="cgi_list" id="cgi_list" value="next,step">
<input type="hidden" name="prefix" id="prefix" value="#!variable!prefix!#">
<input type="hidden" name="sequence" id="sequence" value="#!variable!sequence!#">
<input type="hidden" name="bcn_count" id="bcn_count" value="#!variable!bcn_count!#">
<input type="hidden" name="ifn_count" id="ifn_count" value="#!variable!ifn_count!#">
</form> </form>
</div> </div>
</table> </table>
<!-- end config_step3 --> <!-- end config_step3 -->
<!-- start network_job_recorded -->
<table>
<div id="network_job_recorded_div">
<tr>
<td>
<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>
</td>
</tr>
</div>
</table>
<!-- end network_job_recorded -->
<!-- start striker-offline -->
<table>
<div id="network_job_recorded_div">
<tr>
<td>
<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>
</td>
</tr>
</div>
</table>
<!-- end striker-offline -->
<!-- start step3_bonded_interface --> <!-- start step3_bonded_interface -->
<tr> <tr>
<td class="column_row_name"> <td class="column_row_name">
@ -584,7 +604,7 @@
<table id="network_status" class="data_table_nowrap"> <table id="network_status" class="data_table_nowrap">
<tr> <tr>
<td colspan="5" class="column_header"> <td colspan="5" class="column_header">
#!string!header_0001!# <a href="/">#!string!header_0001!#</a>
</td> </td>
</tr> </tr>
<tr class="data_row"> <tr class="data_row">

@ -293,6 +293,14 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="striker_0041">We're almost ready! Does this look right? If so, we'll setup this Striker dashboard.</key> <key name="striker_0041">We're almost ready! Does this look right? If so, we'll setup this Striker dashboard.</key>
<key name="striker_0042">What we are planning to do...</key> <key name="striker_0042">What we are planning to do...</key>
<key name="striker_0043">Apply New Configuration</key> <key name="striker_0043">Apply New Configuration</key>
<key name="striker_0044">Done!</key>
<key name="striker_0045">The network will be reconfigured momentarily. You may need to reconnect using the new network address you chose.</key>
<key name="striker_0046">Offline...</key>
<key name="striker_0047">A job to reconfigure the network on this machine is underway. Please try again soon.</key>
<!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key>
<key name="job_0002">The network configuration will be updated based on the variables stored in the database. Reconnecting to the machine using the new IP address may be required.</key>
<!-- Warnings --> <!-- Warnings -->
<key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key> <key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key>

@ -0,0 +1,33 @@
#!/usr/bin/perl
#
# This is called when the local network needs to be reconfigured.
#
# Exit codes;
# 0 = Normal exit.
#
use strict;
use warnings;
use Data::Dumper;
use Anvil::Tools;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
{
$running_directory =~ s/^\./$ENV{PWD}/;
}
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
$| = 1;
my $anvil = Anvil::Tools->new();
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 1});
# Read switches
$anvil->Get->switches;
# Paths
$anvil->data->{path}{config}{'anvil.conf'} = "/etc/anvil/anvil.conf";
$anvil->Storage->read_config({file => $anvil->data->{path}{config}{'anvil.conf'}});

@ -138,7 +138,6 @@ sub report_network
}}); }});
$anvil->Database->insert_or_update_network_interfaces({ $anvil->Database->insert_or_update_network_interfaces({
debug => 2,
file => $THIS_FILE, file => $THIS_FILE,
line => __LINE__, line => __LINE__,
network_interface_name => $interface, network_interface_name => $interface,

Loading…
Cancel
Save