* Fixed a subtle an annoying autovivication bug in Database->write().

* Cleaned up some logging.
* Made the "Reload" buttons work more sensibly and cleaned up some webui display stuff.
* Got deleting peers mostly working (well, it works, but then it goes into a loop thinking it needs to resync the now-gone database until the daemon restarts).
* Fixed a race condition bug where if a job exited between the time that anvil-daemon got a list of PIDs and when it checked to see if that specific pid was alive, a job that actually completed could be restarted.
* Added a loop check to anvil-manage-striker-peers where it would hold until a database connection to the newly added peer was available, preventing a condition where re-adding a peer (and so the host_uuid is in hosts) cause the job belonging to the peer to be recorded locally and then never synced to the peer.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent e79e7fd4f4
commit 43035ba038
  1. 10
      Anvil/Tools/Account.pm
  2. 4
      Anvil/Tools/Convert.pm
  3. 51
      Anvil/Tools/Database.pm
  4. 29
      cgi-bin/striker
  5. 428
      html/skins/alteeve/main.css
  6. 14
      html/skins/alteeve/striker.html
  7. 8
      share/words.xml
  8. 91
      tools/anvil-daemon
  9. 58
      tools/anvil-manage-striker-peers

@ -398,12 +398,18 @@ sub logout
$anvil->Account->_write_cookies({debug => $debug});
my $user_uuid = defined $parameter->{user_uuid} ? $parameter->{user_uuid} : "";
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid;
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
user_uuid => $user_uuid.
user_uuid => $user_uuid,
host_uuid => $host_uuid,
}});
if (not $host_uuid)
{
$host_uuid = $anvil->Get->host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
}
if (($anvil->data->{cookie}{anvil_user_uuid}) && (not $user_uuid))
{
$user_uuid = $anvil->data->{cookie}{anvil_user_uuid};

@ -86,6 +86,10 @@ This takes an integer and inserts commas to make it more readable by people.
If the input string isn't a string of digits, it is simply returned as-is.
my $string = $anvil->Convert->add_commas({number => 123456789});
# string = 123,456,789
Parameters;
=head3 number (required)

@ -706,6 +706,7 @@ sub connect
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{database}})
{
# Periodically, autovivication causes and empty key to appear.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { uuid => $uuid }});
next if ((not $uuid) or (not $anvil->Validate->is_uuid({uuid => $uuid})));
if (($db_uuid) && ($db_uuid ne $uuid))
@ -1190,6 +1191,7 @@ sub connect
# Add ourselves to the database, if needed.
$anvil->Database->insert_or_update_hosts({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::database::connections" => $anvil->data->{sys}{database}{connections} }});
return($anvil->data->{sys}{database}{connections});
}
@ -1587,11 +1589,11 @@ sub initialize
});
$anvil->data->{sys}{db_initialized}{$uuid} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::db_initialized::${uuid}" => $anvil->data->{sys}{db_initialized}{$uuid} }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::db_initialized::${uuid}" => $anvil->data->{sys}{db_initialized}{$uuid} }});
# Mark that we need to update the DB.
$anvil->data->{sys}{database}{resync_needed} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::database::resync_needed" => $anvil->data->{sys}{database}{resync_needed} }});
$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 => { success => $success }});
return($success);
@ -3399,7 +3401,7 @@ sub insert_or_update_sessions
my $parameter = shift;
my $anvil = $self->parent;
my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->insert_or_update_states()" }});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Database->insert_or_update_sessions()" }});
my $uuid = defined $parameter->{uuid} ? $parameter->{uuid} : "";
my $file = defined $parameter->{file} ? $parameter->{file} : "";
@ -3732,6 +3734,7 @@ WHERE
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0216", variables => { uuid_name => "state_uuid", uuid => $state_uuid }});
return("");
}
foreach my $row (@{$results})
{
my $old_state_name = $row->[0];
@ -4763,7 +4766,6 @@ sub mark_active
state_note => $value,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { state_uuid => $state_uuid }});
return($state_uuid);
}
@ -5191,7 +5193,7 @@ sub resync_databases
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 $data_type = $anvil->data->{sys}{database}{table}{$table}{column}{$column_name}{data_type};
$anvil->Log->variables({source => 2, line => __LINE__, level => $debug, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"s1:id" => $uuid,
"s2:row_number" => $row_number,
"s3:column_number" => $column_number,
@ -5419,7 +5421,7 @@ sub resync_databases
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0221", variables => {
to_write => $to_write_count,
host_name => $anvil->Get->host_name({debug => 2, host_uuid => $uuid}),
host_name => $anvil->Get->host_name({host_uuid => $uuid}),
}});
$anvil->Database->write({uuid => $uuid, query => $merged, source => $THIS_FILE, line => __LINE__});
undef $merged;
@ -5427,6 +5429,10 @@ sub resync_databases
}
} # foreach my $table
# Clear the variable that indicates we need a resync.
$anvil->data->{sys}{database}{resync_needed} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'sys::database::resync_needed' => $anvil->data->{sys}{database}{resync_needed} }});
# Show tables;
# SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC, table_schema DESC;
@ -5474,9 +5480,15 @@ sub write
}});
}
### NOTE: The careful checks below are to avoid autovivication biting our arses later.
# Make logging code a little cleaner
my $database_name = defined $anvil->data->{database}{$uuid}{name} ? $anvil->data->{database}{$uuid}{name} : $anvil->data->{sys}{database}{name};
my $say_server = $uuid eq "" ? $anvil->Words->string({key => "log_0129"}) : $anvil->data->{database}{$uuid}{host}.":".$anvil->data->{database}{$uuid}{port}." -> ".$database_name;
my $database_name = $anvil->data->{sys}{database}{name};
my $say_server = $anvil->Words->string({key => "log_0129"});
if (($uuid) && (exists $anvil->data->{database}{$uuid}) && (defined $anvil->data->{database}{$uuid}{name}) && ($anvil->data->{database}{$uuid}{name}))
{
$database_name = $anvil->data->{database}{$uuid}{name};
$say_server = $anvil->data->{database}{$uuid}{host}.":".$anvil->data->{database}{$uuid}{port}." -> ".$database_name;
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
database_name => $database_name,
say_server => $say_server,
@ -5951,13 +5963,16 @@ ORDER BY
if ($anvil->data->{sys}{database}{table}{$table}{last_updated} > $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{last_updated})
{
# Resync needed.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::table::${table}::last_updated" => $anvil->data->{sys}{database}{table}{$table}{last_updated},
"sys::database::table::${table}::uuid::${uuid}::last_updated" => $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{last_updated},
}});
my $difference = $anvil->Convert->add_commas({number => ($anvil->data->{sys}{database}{table}{$table}{last_updated} - $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{last_updated}) });;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0106", variables => {
uuid => $uuid,
host => $anvil->Get->host_name({debug => 2, host_uuid => $uuid}),
seconds => $difference,
table => $table,
uuid => $uuid,
host => $anvil->Get->host_name({host_uuid => $uuid}),
}});
# Mark it as behind.
@ -5967,13 +5982,16 @@ ORDER BY
elsif ($anvil->data->{sys}{database}{table}{$table}{row_count} > $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{row_count})
{
# Resync needed.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"sys::database::table::${table}::row_count" => $anvil->data->{sys}{database}{table}{$table}{row_count},
"sys::database::table::${table}::uuid::${uuid}::row_count" => $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{row_count},
}});
my $difference = $anvil->Convert->add_commas({number => ($anvil->data->{sys}{database}{table}{$table}{row_count} - $anvil->data->{sys}{database}{table}{$table}{uuid}{$uuid}{row_count}) });;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0219", variables => {
uuid => $uuid,
host => $anvil->Get->host_name({debug => 2, host_uuid => $uuid}),
missing => $difference,
table => $table,
uuid => $uuid,
host => $anvil->Get->host_name({host_uuid => $uuid}),
}});
# Mark it as behind.
@ -5983,10 +6001,7 @@ ORDER BY
}
last if $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},
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sys::database::resync_needed" => $anvil->data->{sys}{database}{resync_needed} }});
return(0);
}

@ -301,7 +301,7 @@ sub process_power
{
# Record the job!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
debug => 3,
file => $THIS_FILE,
line => __LINE__,
job_command => $task eq "poweroff" ? "anvil-manage-power --poweroff -y" : "anvil-manage-power --reboot -y",
@ -332,8 +332,9 @@ sub process_power
{
# Show the screen the confirm the addition.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => {
title => $task eq "poweroff" ? "#!string!job_0007!#" : "#!string!job_0005!#",
message => $task eq "poweroff" ? "#!string!striker_0101!#" : "#!string!striker_0100!#",
title => $task eq "poweroff" ? "#!string!job_0007!#" : "#!string!job_0005!#",
message => $task eq "poweroff" ? "#!string!striker_0101!#" : "#!string!striker_0100!#",
hidden_fields => "",
}});
}
@ -351,7 +352,7 @@ sub process_update
{
# Record the job!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
debug => 3,
file => $THIS_FILE,
line => __LINE__,
job_command => "anvil-update-system",
@ -381,8 +382,9 @@ sub process_update
{
# Show the screen the confirm the addition.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => {
title => "#!string!striker_0078!#",
message => "#!string!striker_0086!#",
title => "#!string!striker_0078!#",
message => "#!string!striker_0086!#",
hidden_fields => "",
}});
}
@ -610,7 +612,7 @@ sub delete_sync_peer
{
# OK, save the job!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
debug => 3,
file => $THIS_FILE,
line => __LINE__,
job_command => "anvil-manage-striker-peers --remove --host-uuid ".$uuid,
@ -626,7 +628,7 @@ sub delete_sync_peer
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => {
title_id => "",
message_id => "",
reload_url => "/cgi-bin/".$THIS_FILE,
reload_url => "/cgi-bin/".$THIS_FILE."?striker=true&task=sync",
title => "#!string!striker_0044!#",
description => "#!string!striker_0104!#",
}});
@ -636,8 +638,9 @@ sub delete_sync_peer
{
# Show the screen the confirm the addition.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-action", variables => {
title => "#!string!job_0013!#",
message => $anvil->Words->string({key => "striker_0105", variables => { peer => $user."\@".$host_name }}),
title => "#!string!job_0013!#",
message => $anvil->Words->string({key => "striker_0105", variables => { peer => $user."\@".$host_name }}),
hidden_fields => "<input type=\"hidden\" name=\"delete\" id=\"delete\" value=\"".$uuid."\" />",
}});
}
@ -843,7 +846,7 @@ sub add_sync_peer
# Store the job
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
debug => 3,
file => $THIS_FILE,
line => __LINE__,
job_command => $job_command,
@ -860,7 +863,7 @@ sub add_sync_peer
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "job recorded", variables => {
title_id => "",
message_id => "",
reload_url => "/cgi-bin/".$THIS_FILE,
reload_url => "/cgi-bin/".$THIS_FILE."?striker=true&task=sync",
title => "#!string!striker_0044!#",
description => $ping ? "#!string!striker_0103!#" : "#!string!striker_0102!#",
}});
@ -926,7 +929,7 @@ sub configure_striker
{
# User has confirmed, update the system!
my ($job_uuid) = $anvil->Database->insert_or_update_jobs({
debug => 2,
debug => 3,
file => $THIS_FILE,
line => __LINE__,
job_command => "anvil-configure-striker",

@ -10,14 +10,67 @@ Colours;
- Footer text: #515151
*/
.login {
width: 600px;
height: 50px;
position: fixed;
margin-left: -300px; /* half of width */
margin-top: -25px; /* half of height */
top: 50%;
left: 50%;
a {
font-family: 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
color: #f2f2f2;
text-decoration: none;
}
body {
font-family: 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
background-image: url("/skins/alteeve/images/Texture.jpg");
background-repeat: repeat;
color: #f2f2f2;
}
.body_table {
width: 90%;
margin: auto;
top: 0;
position: absolute;
left: 5%;
}
.button {
color: #343434;
font: 0.9em 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
text-decoration: none;
background-color: #f2f2f2;
padding: 5px 10px 5px 10px;
border: 1px solid #343434;
border-radius: 3px;
}
#center_body {
height: 100%;
}
.code {
font-family: 'Dejavu Sans Mono', Courier;
}
.column_header {
text-align: left;
color: #9ba0a5;
padding: 0.15em;
}
.config_header1 {
color: #f7f7f7;
text-align: center;
font-size: 2em;
}
.config_header2 {
color: #f2f2f2;
text-align: center;
font-size: 1.5em;
}
.config_header3 {
color: #f2f2f2;
text-align: center;
font-size: 1em;
}
.error_message {
@ -30,12 +83,93 @@ Colours;
color: #ffdfdf;
}
input[type=text].input_clear, input[type=number].input_clear, select.input_clear {
.fixed_width {
font-family: 'Dejavu Sans Mono', Courier;
}
.footer {
background: #171717;
font-size: 12px;
color: #515151;
width: 90%;
position: fixed;
bottom: 0;
left: 5%;
}
.footer a:hover {
cursor: pointer;
text-decoration: none;
color: #616161;
}
.footer a:link, .footer a:visited {
cursor: pointer;
text-decoration: none;
color: #515151;
}
.form_answer {
font: 1em 'Dejavu Sans Mono', Courier;
color: #dba0a5;
white-space: nowrap;
}
.form_group_header1 {
text-align: left;
font-size: 1.1em;
font-weight: bold;
}
.form_group_header2 {
text-align: left;
font-size: 1.1em;
}
.job_output {
font: 0.8em 'Dejavu Sans Mono', Courier;
color: #d2e2d2;
white-space: nowrap;
}
.job_status {
border: 1px solid #9ba0a5;
}
input[type=text].input_alert, input[type=number].input_alert, select.input_alert {
border: 1px solid #ff3f3f;
.job_table {
border-left: 1px dotted #d02724;
}
.header {
text-align: center;
background: #343434;
color: #f2f2f2;
border-bottom: 0.2em solid #d02724;
}
.header a:hover {
cursor: pointer;
color: #f6f6f6;
text-decoration: none;
}
.header a:link, .header a:visited {
cursor: pointer;
color: #f6f6f6;
text-decoration: none;
}
/* This is used by HTML::FromText when converting a text string to HTML */
.hft-lines {
text-align: left;
font-family: 'Dejavu Sans Mono', Courier;
padding: 0.2em;
font-size: 0.9em;
}
.icon_button {
padding-top: 30px;
vertical-align: top;
}
input[type=text], input[type=number], input[type=password] {
@ -50,6 +184,44 @@ input[type=text], input[type=number], input[type=password] {
color: #f7f7f7;
}
input[type=text].input_alert, input[type=number].input_alert, select.input_alert {
border: 1px solid #ff3f3f;
}
input[type=text].input_clear, input[type=number].input_clear, select.input_clear {
border: 1px solid #9ba0a5;
}
.login {
width: 600px;
height: 50px;
position: fixed;
margin-left: -300px; /* half of width */
margin-top: -25px; /* half of height */
top: 50%;
left: 50%;
}
.logo {
border-top: 0.3em solid transparent;
border-left: 0.3em solid transparent;
border-right: 0.3em solid transparent;
height: 2.5em;
}
.menu_details {
padding-left: 10px;
padding-right: 10px;
}
.menu_title {
color: #dbe0e5;
font-size: 1.3em;
padding-top: 30px;
padding-left: 20px;
padding-bottom: 10px;
}
select {
width: 100%;
/* padding: 6px 10px; */
@ -64,40 +236,30 @@ select {
font-size: 1.0em;
}
.code {
font-family: 'Dejavu Sans Mono', Courier;
}
body {
font-family: 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
background-image: url("/skins/alteeve/images/Texture.jpg");
background-repeat: repeat;
color: #f2f2f2;
table {
border-spacing: 0;
border-collapse: collapse;
vertical-align: top;
}
a {
font-family: 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
color: #f2f2f2;
text-decoration: none;
table.centered {
margin: auto;
}
table.data_table_nowrap {
table.data_table {
border: 1px solid #8f8f8f;
border-radius: 4px;
white-space: nowrap;
}
table.data_table {
table.data_table_nowrap {
border: 1px solid #8f8f8f;
border-radius: 4px;
white-space: nowrap;
}
table.centered {
margin: auto;
}
tr.data_row {
border-top: 1px solid #5f5f5f;
td {
padding: 0;
border-collapse: collapse;
}
td.button_cell {
@ -105,27 +267,11 @@ td.button_cell {
text-align: center;
}
td.top_padded_cell {
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
padding-bottom: 0px;
}
td.padded_cell {
padding: 0px 5px;
}
td.column_header {
text-align: left;
color: #9ba0a5;
padding: 0.15em;
}
.column_header {
text-align: left;
color: #9ba0a5;
padding: 0.15em;
}
td.column_row_name {
text-align: left;
@ -134,13 +280,6 @@ td.column_row_name {
padding: 0.2em;
}
td.column_subrow_name {
text-align: right;
vertical-align: top;
color: #c7c7c7;
padding: 0.1em;
}
td.column_row_value {
text-align: left;
color: #f7f7f7;
@ -154,6 +293,7 @@ td.column_row_value_fixed {
padding: 0.2em;
font-size: 0.9em;
}
td.column_row_value_fixed_centered {
text-align: center;
color: #f7f7f7;
@ -162,59 +302,27 @@ td.column_row_value_fixed_centered {
font-size: 0.9em;
}
.body_table {
width: 90%;
margin: auto;
top: 0;
position: absolute;
left: 5%;
td.column_subrow_name {
text-align: right;
vertical-align: top;
color: #c7c7c7;
padding: 0.1em;
}
.config_header1 {
color: #f7f7f7;
text-align: center;
font-size: 2em;
td.padded_cell {
padding: 0px 5px;
}
.config_header2 {
color: #f2f2f2;
text-align: center;
font-size: 1.5em;
td.top_padded_cell {
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
padding-bottom: 0px;
}
.config_header3 {
color: #f2f2f2;
.title {
font-size: 1.2em;
text-align: center;
font-size: 1em;
}
.form_group_header1 {
text-align: left;
font-size: 1.1em;
font-weight: bold;
}
.form_group_header2 {
text-align: left;
font-size: 1.1em;
}
table {
border-spacing: 0;
border-collapse: collapse;
vertical-align: top;
}
td {
/* border: 1px solid green; */
padding: 0;
border-collapse: collapse;
}
.logo {
border-top: 0.3em solid transparent;
border-left: 0.3em solid transparent;
border-right: 0.3em solid transparent;
height: 2.5em;
}
.top_icon {
@ -224,119 +332,15 @@ td {
height: 2.5em;
}
.subtle_text {
color: #9D9D9D;
text-align: left;
font-size: 0.9em;
}
.header {
text-align: center;
background: #343434;
color: #f2f2f2;
border-bottom: 0.2em solid #d02724;
}
.header a:link, .header a:visited {
cursor: pointer;
color: #f6f6f6;
text-decoration: none;
}
.header a:hover {
cursor: pointer;
color: #f6f6f6;
text-decoration: none;
}
.footer {
background: #171717;
font-size: 12px;
color: #515151;
width: 90%;
position: fixed;
bottom: 0;
left: 5%;
}
.footer a:link, .footer a:visited {
cursor: pointer;
text-decoration: none;
color: #515151;
}
.footer a:hover {
cursor: pointer;
text-decoration: none;
color: #616161;
}
.fixed_width {
font-family: 'Dejavu Sans Mono', Courier;
}
#center_body {
height: 100%;
tr.data_row {
border-top: 1px solid #5f5f5f;
}
.striker_welcome {
}
.title {
font-size: 1.2em;
text-align: center;
}
.button {
color: #343434;
font: 0.9em 'Dejavu Sans', Arial, Helvetica, Verdana, Sans-Serif;
text-decoration: none;
background-color: #f2f2f2;
padding: 5px 10px 5px 10px;
border: 1px solid #343434;
border-radius: 3px;
}
.icon_button {
padding-top: 30px;
vertical-align: top;
}
.menu_title {
color: #dbe0e5;
font-size: 1.3em;
padding-top: 30px;
padding-left: 20px;
padding-bottom: 10px;
}
.menu_details {
padding-left: 10px;
padding-right: 10px;
}
/* This is used by HTML::FromText when converting a text string to HTML */
.hft-lines {
text-align: left;
font-family: 'Dejavu Sans Mono', Courier;
padding: 0.2em;
font-size: 0.9em;
}
.job_table {
border-left: 1px dotted #d02724;
}
.job_status {
border: 1px solid #9ba0a5;
}
.job_output {
font: 0.8em 'Dejavu Sans Mono', Courier;
color: #d2e2d2;
white-space: nowrap;
}
.form_answer {
font: 1em 'Dejavu Sans Mono', Courier;
color: #dba0a5;
white-space: nowrap;
.subtle_text {
color: #9D9D9D;
text-align: left;
font-size: 0.9em;
}

@ -25,6 +25,7 @@
<input type="submit" name="confirm" id="confirm" class="button" value="#!string!striker_0082!#">
</td>
</tr>
#!variable!hidden_fields!#
<input type="hidden" name="striker" id="striker" value="#!data!cgi::striker::value!#">
<input type="hidden" name="task" id="task" value="#!data!cgi::task::value!#">
<input type="hidden" name="save" id="save" value="#!data!cgi::save::value!#">
@ -270,8 +271,8 @@
<div id="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>
<span name="#!variable!title_id!#" id="#!variable!title_id!#" class="config_header2">#!variable!title!#</span><br />
<span name="#!variable!message_id!#" id="#!variable!message_id!#" class="config_header3">#!variable!description!#</span>
<br />
<hr />
<a href="#!variable!reload_url!#" class="button">#!string!striker_0053!#</a>
@ -494,6 +495,11 @@
<a href="?striker=true&task=sync&delete=#!variable!uuid!#" id="#!variable!uuid!#_delete" class="button">#!string!striker_0068!#<a/>
</td>
</tr>
<tr>
<td colspan="4">
<br />
</td>
</tr>
<!-- end striker-sync-entry -->
<!-- start striker-sync-inbound -->
@ -559,8 +565,8 @@
<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>
<span name="#!variable!title_id!#" id="#!variable!title_id!#" class="config_header2">#!variable!title!#</span><br />
<span name="#!variable!message_id!#" id="#!variable!message_id!#" class="config_header3">#!variable!description!#</span>
<br />
<hr />
<a href="#!variable!reload_url!#" class="button">#!string!striker_0053!#</a>

@ -254,7 +254,7 @@ The database connection error was:
<key name="log_0103">The local machine's UUID was not read properly. It should be stored in: [#!data!sys::host_uuid!#] and contain hexadecimal characters in the format: '012345-6789-abcd-ef01-23456789abcd' and usually matches the output of 'dmidecode --string system-uuid'. If this file exists and if there is a string in the file, please verify that it is structured correctly.</key>
<key name="log_0104">The database with UUID: [#!variable!uuid!#] for: [#!variable!file!#] is behind.</key>
<key name="log_0105">Anvil! database: [#!variable!database!#] already exists.</key>
<key name="log_0106">The database on: [#!variable!host!#] (UUID: [#!variable!uuid!#]) is behind. A database resync will be requested.</key>
<key name="log_0106">The table: [#!variable!table!#] (and possibly others) in the database on: [#!variable!host!#] (UUID: [#!variable!uuid!#]) is behind by: [#!variable!seconds!#] seconds. A database resync will be requested.</key>
<key name="log_0107">[ Warning ] - Failed to delete the temporary postgres password.</key>
<key name="log_0108"><![CDATA[[ Error ] - The method Database->insert_or_update_states() was called but the 'state_host_uuid' parameter was not passed or it is empty. Normally this is set to 'sys::data_uuid'.]]></key>
<key name="log_0109">[ Error ] - Failed to create the Anvil! database: [#!variable!database!#]</key>
@ -358,7 +358,7 @@ The database connection error was:
<key name="log_0207"><![CDATA[Job->update_progress() called without 'job_uuid' being set, and 'jobs::job_uuid' was also not set. Unable to find the job to update.]]></key>
<key name="log_0208"><![CDATA[Job->update_progress() called with the 'job_uuid': [#!variable!job_uuid!#], which was not found. Unable to find the job to update.]]></key>
<key name="log_0209"><![CDATA[Job->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).]]></key>
<key name="log_0210"><![CDATA[Requesting the job: [#!variable!command!#] be run by 'anvil-daemon'.]]></key>
<key name="log_0210"><![CDATA[Will now run the job: [#!variable!command!#] as a background task.]]></key>
<key name="log_0211"><![CDATA[The host: [#!variable!host!#] was passed to System->find_matching_ip(), but it failed to resolve to an IP address.]]></key>
<key name="log_0212">We've been asked to have the new peer add us. We will now wait for the peer to show up in the 'hosts' table and then request the job for it to add us.</key>
<key name="log_0213">The peer: [#!variable!peer_uuid!#] is not yet in 'hosts', continuing to wait.</key>
@ -367,9 +367,11 @@ The database connection error was:
<key name="log_0216">The #!variable!uuid_name!#: [#!variable!uuid!#] was passed in, but no record with that UUID was found in the database.</key>
<key name="log_0217">The variable with variable_uuid: [#!variable!variable_uuid!#], variable_source_table: [#!variable!variable_source_table!#] and variable_source_uuid: [#!variable!variable_source_uuid!#] was not found in the database, so unable to update.</key>
<key name="log_0218">The variable: [#!variable!name!#] was expected to be an array reference, but it wasn't. It contained (if anything): [#!variable!value!#].</key>
<key name="log_0219">The database on: [#!variable!host!#] (UUID: [#!variable!uuid!#]) is missing rows. A database resync will be requested.</key>
<key name="log_0219">The table: [#!variable!table!#] (and possibly others) in the database on: [#!variable!host!#] (UUID: [#!variable!uuid!#]) is missing: [#!variable!missing!#] row(s). A database resync will be requested.</key>
<key name="log_0220"><![CDATA[Database->insert_or_update_jobs() was called with 'update_progress_only' but without a 'job_uuid' being set.]]></key>
<key name="log_0221">Writing: [#!variable!to_write!#] record(s) to resync the database on: [#!variable!host_name!#].</key>
<key name="log_0222">The connection to the database on: [#!variable!host!#] isn't established, trying again...</key>
<key name="log_0223">The connection to the database on: [#!variable!host!#] has been successfully established.</key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key>

@ -27,6 +27,8 @@ use JSON;
use HTML::Strip;
use HTML::FromText;
use Data::Dumper;
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
if (($running_directory =~ /^\./) && ($ENV{PWD}))
@ -111,10 +113,22 @@ my $check_if_database_is_configured = 0;
while(1)
{
# Connect to the database(s)
$anvil->Storage->read_config({file => $anvil->data->{path}{configs}{'anvil.conf'}});
$anvil->Storage->read_config({force_read => 1, file => $anvil->data->{path}{configs}{'anvil.conf'}});
$anvil->Database->connect({check_if_configured => $check_if_database_is_configured});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"});
### DEBUG:
my $db_count = keys %{$anvil->data->{database}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { db_count => $db_count }});
foreach my $uuid (keys %{$anvil->data->{database}})
{
my $host = $anvil->data->{database}{$uuid}{host};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:uuid" => $uuid,
"s2:host" => $host,
}});
}
# Mark that we don't want to check the database now.
$check_if_database_is_configured = 0;
@ -168,7 +182,22 @@ while(1)
}
# Disconnect from the database(s) and sleep now.
$anvil->Database->disconnect();
$anvil->Database->disconnect({debug => 2});
### DEBUG:
$db_count = 0;
$db_count = keys %{$anvil->data->{database}};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { db_count => $db_count }});
foreach my $uuid (keys %{$anvil->data->{database}})
{
my $host = $anvil->data->{database}{$uuid}{host};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"s1:uuid" => $uuid,
"s2:host" => $host,
}});
}
die;
sleep(1);
}
@ -387,7 +416,7 @@ sub run_jobs
my $job_status = $hash_ref->{job_status};
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 => 3, list => {
job_uuid => $job_uuid,
job_command => $job_command,
job_data => $job_data,
@ -406,7 +435,7 @@ sub run_jobs
if ($job_progress ne "100")
{
$anvil->data->{sys}{jobs_running} = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::jobs_running" => $anvil->data->{sys}{jobs_running} }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "sys::jobs_running" => $anvil->data->{sys}{jobs_running} }});
}
# See if the job was picked up by a now-dead instance.
@ -422,28 +451,46 @@ sub run_jobs
# If the job is done, just clear the 'job_picked_up_by' and be done.
if ($job_progress ne "100")
{
# The previous job is gone, but the job isn't finished. Start it again.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "striker_warning_0007", variables => {
command => $job_command,
pid => $job_picked_up_by,
percent => $job_progress,
}});
# Clear some variables.
$job_progress = 0;
$job_status = "message_0056";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
job_progress => $job_progress,
job_status => $job_status,
}});
# Clear the job.
$anvil->Job->clear({debug => 3, job_uuid => $job_uuid});
# It's possible that the job updated to 100% and exited after we
# gathered the job data, so we won't restart until we've seen it not
# running and not at 100% after 5 loops.
if ((not exists $anvil->data->{lost_job_count}{$job_uuid}) or (not defined $anvil->data->{lost_job_count}{$job_uuid}))
{
$anvil->data->{lost_job_count}{$job_uuid} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lost_job_count::${job_uuid}" => $anvil->data->{lost_job_count}{$job_uuid} }});
}
if ($anvil->data->{lost_job_count}{$job_uuid} > 5)
{
# The previous job is gone, but the job isn't finished. Start it again.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "striker_warning_0007", variables => {
command => $job_command,
pid => $job_picked_up_by,
percent => $job_progress,
}});
# Clear some variables.
$job_progress = 0;
$job_status = "message_0056";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
job_progress => $job_progress,
job_status => $job_status,
}});
# Clear the job.
$anvil->Job->clear({debug => 3, job_uuid => $job_uuid});
$anvil->data->{lost_job_count}{$job_uuid} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lost_job_count::${job_uuid}" => $anvil->data->{lost_job_count}{$job_uuid} }});
}
else
{
$anvil->data->{lost_job_count}{$job_uuid}++;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "lost_job_count::${job_uuid}" => $anvil->data->{lost_job_count}{$job_uuid} }});
}
}
# Clear the PID
$job_picked_up_by = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_picked_up_by => $job_picked_up_by }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { job_picked_up_by => $job_picked_up_by }});
}
}

@ -41,9 +41,15 @@ $| = 1;
my $anvil = Anvil::Tools->new({log_level => 2, log_secure => 1});
# Read switches
$anvil->data->{switches}{list} = "";
$anvil->data->{switches}{add} = 0;
$anvil->data->{switches}{remove} = 0;
$anvil->data->{switches}{list} = "";
$anvil->data->{switches}{add} = 0;
$anvil->data->{switches}{remove} = 0;
$anvil->data->{switches}{'job-uuid'} = "";
$anvil->data->{switches}{'host-uuid'} = "";
$anvil->data->{switches}{'host'} = "";
$anvil->data->{switches}{'port'} = 5432;
$anvil->data->{switches}{'password-file'} = "";
$anvil->data->{switches}{'ping'} = 0;
$anvil->Get->switches;
# Make sure we're running as 'root'
@ -63,9 +69,9 @@ $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
# Am I adding, editing or deleting?
if (not $anvil->data->{switches}{list})
if ((not $anvil->data->{switches}{list}) && ($anvil->data->{switches}{'host-uuid'}))
{
process_entry($anvil) ;
process_entry($anvil);
}
### Report the peers.
@ -141,12 +147,12 @@ sub process_entry
{
my ($anvil) = @_;
my $job_uuid = defined $anvil->data->{switches}{'job-uuid'} ? $anvil->data->{switches}{'job-uuid'} : "";
my $host_uuid = defined $anvil->data->{switches}{'host-uuid'} ? $anvil->data->{switches}{'host-uuid'} : "";
my $host = defined $anvil->data->{switches}{'host'} ? $anvil->data->{switches}{'host'} : "";
my $port = defined $anvil->data->{switches}{'port'} ? $anvil->data->{switches}{'port'} : 5432;
my $password_file = defined $anvil->data->{switches}{'password-file'} ? $anvil->data->{switches}{'password-file'} : "";
my $ping = defined $anvil->data->{switches}{'ping'} ? $anvil->data->{switches}{'ping'} : 0;
my $job_uuid = $anvil->data->{switches}{'job-uuid'};
my $host_uuid = $anvil->data->{switches}{'host-uuid'};
my $host = $anvil->data->{switches}{'host'};
my $port = $anvil->data->{switches}{'port'};
my $password_file = $anvil->data->{switches}{'password-file'};
my $ping = $anvil->data->{switches}{'ping'};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, secure => 0, level => 2, list => {
job_uuid => $job_uuid,
host_uuid => $host_uuid,
@ -537,7 +543,35 @@ sub process_entry
$anvil->Database->connect;
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
# Now loop until we see the peer's host_uuid show up
# Now loop until we see the peer's host_uuid show up and we have a connection to the peer's
# database.
my $peer_connected = 0;
until($peer_connected)
{
my $say_host = $anvil->Get->host_name({host_uuid => $host_uuid});
$say_host = $host_uuid if not $say_host;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
say_host => $say_host,
"cache::database_handle::${host_uuid}" => $anvil->data->{cache}{database_handle}{$host_uuid},
}});
if ($anvil->data->{cache}{database_handle}{$host_uuid} =~ /^DBI::db=HASH/)
{
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, secure => 0, key => "log_0223", variables => { host => $say_host }});
$peer_connected = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_connected => $peer_connected }});
}
else
{
# Sleep and then try again to connect.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, secure => 0, key => "log_0222", variables => { host => $say_host }});
sleep 1;
$anvil->Database->connect({db_uuid => $host_uuid});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"});
}
}
my $peer_host_name = "";
my $host_seen = 0;
until($host_seen)

Loading…
Cancel
Save