From fe33fbb239195ffa548005654b612e43582254f2 Mon Sep 17 00:00:00 2001 From: Digimer Date: Thu, 16 Aug 2018 02:38:58 -0400 Subject: [PATCH] * Created System->maintenance_mode to add "maintenance mode" support to Striker. * Continuing work on adding the system update job support to Striker. Untested/Incomplete. Signed-off-by: Digimer --- Anvil/Tools/Database.pm | 6 +- Anvil/Tools/System.pm | 78 +++++++++++++++ cgi-bin/striker | 168 +++++++++++++++++--------------- html/skins/alteeve/main.html | 16 --- html/skins/alteeve/striker.html | 32 ++++++ share/words.xml | 7 +- tools/anvil-configure-striker | 2 + tools/anvil.sql | 2 +- 8 files changed, 211 insertions(+), 100 deletions(-) diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 7e90c812..97a94e06 100755 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -2439,7 +2439,7 @@ This is the command (usually a shell call) to run. =head3 job_data (optional) -This is optional data used by C<< anvil-job >> when running a job. +This is used to pass information or store special progress data on a job. =head3 job_description (required*) @@ -2461,11 +2461,11 @@ This is the C<< job_name >> to INSERT or UPDATE. If a C<< job_uuid >> is passed, =head3 job_picked_up_at (optional) -When C<< anvil-jobs >> picks uup a job, it will record the (unix) time that it started. +When C<< anvil-daemon >> picks uup a job, it will record the (unix) time that it started. =head3 job_picked_up_by (optional) -When C<< anvil-jobs >> picks up a job, it will record it's PID here. +When C<< anvil-daemon >> picks up a job, it will record it's PID here. =head3 job_progress (required) diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index 56d71867..6b869335 100755 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -24,6 +24,7 @@ my $THIS_FILE = "System.pm"; # get_ips # hostname # is_local +# maintenance_mode # manage_firewall # ping # read_ssh_config @@ -876,6 +877,83 @@ sub is_local return($is_local); } +=head2 maintenance_mode + +This sets, clears or checks if the local system is in maintenance mode. Any system in maintenance mode will not be used by normal Anvil! tasks. + +This returns C<< 1 >> if maintenance mode is enabled and C<< 0 >> if disabled. + +Parameters; + +=head3 set (optional) + +If this is set to C<< 1 >>, maintenance mode is enabled. If this is set to C<< 0 >>, maintenance mode is disabled. + +=cut +sub maintenance_mode +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + + my $set = defined $parameter->{set} ? $parameter->{set} : ""; + + if ($set) + { + # Am I enabling or disabling? + if ($set eq "1") + { + # Enabling + $anvil->Database->insert_or_update_variables({ + variable_name => "maintenance_mode", + variable_value => "1", + variable_default => "0", + variable_description => "striker_0087", + variable_section => "system", + variable_source_uuid => $anvil->Get->host_uuid, + variable_source_table => "hosts", + update_value_only => 1, + }); + } + elsif ($set eq "0") + { + # Disabling + $anvil->Database->insert_or_update_variables({ + variable_name => "maintenance_mode", + variable_value => "0", + variable_default => "0", + variable_description => "striker_0087", + variable_section => "system", + variable_source_uuid => $anvil->Get->host_uuid, + variable_source_table => "hosts", + update_value_only => 1, + }); + } + else + { + # Called with an invalid value. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0197", variables => { set => $set }}); + $set = ""; + } + } + + my ($maintenance_mode, $variable_uuid, $modified_date) = $anvil->Database->read_variable({debug => $debug, variable_name => "maintenance_mode"}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + maintenance_mode => $maintenance_mode, + variable_uuid => $variable_uuid, + modified_date => $modified_date, + }}); + + if ($maintenance_mode eq "") + { + $maintenance_mode = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { maintenance_mode => $maintenance_mode }}); + } + + return($maintenance_mode); +} + =head2 manage_firewall This method manages a firewalld firewall. diff --git a/cgi-bin/striker b/cgi-bin/striker index 2ec2ca92..14dddd44 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -63,7 +63,7 @@ if (not $anvil->data->{sys}{database}{connections}) # If any jobs are pending/running, show the "unavailable" option. my $available = check_availability($anvil); my $configured = $available ? check_if_configured($anvil) : 0; -$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { available => $available, configured => $configured, }}); @@ -195,7 +195,7 @@ sub process_task # cookies were deleted (via C<< Account->logout() >>. The user needs to log back in. # 3 - There user's hash is invalid, it is probably expired. The user has been logged out and # needs to log back in. - my $cookie_problem = $anvil->Account->read_cookies({debug => 3}); + my $cookie_problem = $anvil->Account->read_cookies({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { cookie_problem => $cookie_problem }}); if (not $cookie_problem) { @@ -273,17 +273,31 @@ sub process_update $anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value}; if ($anvil->data->{cgi}{confirm}{value}) { - # Request the job and take the system offline until it's done. -# $anvil->Database->insert_or_update_variables({ -# variable_name => "system::configured", -# variable_source_uuid => $anvil->Get->host_uuid, -# variable_source_table => "hosts", -# variable_value => 0, -# update_value_only => 1, -# }); + # Record the job! + my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ + debug => 2, + file => $THIS_FILE, + line => __LINE__, + job_command => "anvil-update-system --uuid ".$anvil->Get->host_uuid, + job_data => "", + job_name => "update::system", + job_title => "job_0003", + job_description => "job_0004", + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_uuid => $job_uuid }}); - # Done. - $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "update-requested"}); + # We don't need to store anything as hidden variables, we'll read it back from the database + # later. + $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "system_update_recorded", variables => { + title_id => "", + message_id => "", + title => "#!string!striker_0044!#", + description => "#!string!striker_0088!#", + }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); + + # Set maintenance mode. + $anvil->System->maintenance_mode({debug => 2, set => 1}); } else { @@ -699,7 +713,29 @@ sub configure_striker elsif ($anvil->data->{cgi}{step}{value} eq "step3") { # User has confirmed, update the system! - $anvil->data->{form}{body} = save_job($anvil); + my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ + debug => 2, + file => $THIS_FILE, + line => __LINE__, + job_command => "anvil-configure-striker", + 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 }}); + + # Set maintenance mode. + $anvil->System->maintenance_mode({debug => 2, set => 1}); + + # We don't need to store anything as hidden variables, we'll read it back from the database later. + $anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "network_job_recorded", variables => { + title_id => "", + message_id => "", + title => "#!string!striker_0044!#", + description => "#!string!striker_0045!#", + }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { @@ -736,9 +772,17 @@ sub check_availability { my ($anvil) = @_; - my $debug = 3; + my $debug = 2; my $available = 1; - my $query = " + + # Set maintenance mode. + $available = $anvil->System->maintenance_mode({debug => $debug}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { available => $available }}); + + # TODO: Phase this out + if ($available) + { + my $query = " SELECT job_progress, modified_date, @@ -752,78 +796,44 @@ AND AND job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." ;"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); - - my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); - my $count = @{$results}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - results => $results, - count => $count, - }}); - if ($count) - { - # We're waiting for the network configuration - my $percent = $results->[0]->[0]; - my $timestamp = $results->[0]->[1]; - my $unixtime = $results->[0]->[2]; - my $seconds_ago = $anvil->Convert->add_commas({number => (time - $unixtime)}); - $available = 0; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - available => $available, - percent => $percent, - seconds_ago => $seconds_ago, - timestamp => $timestamp, - unixtime => $unixtime, - }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }}); - $anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => { - title_id => "", - message_id => "", - title => "#!string!striker_0046!#", - description => $anvil->Words->string({key => "striker_0047", variables => { percent => $percent, timestamp => $timestamp, seconds_ago => $seconds_ago }}), + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + results => $results, + count => $count, }}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'say::maintenance' => $anvil->data->{say}{maintenance} }}); + if ($count) + { + # We're waiting for the network configuration + my $percent = $results->[0]->[0]; + my $timestamp = $results->[0]->[1]; + my $unixtime = $results->[0]->[2]; + my $seconds_ago = $anvil->Convert->add_commas({number => (time - $unixtime)}); + $available = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + available => $available, + percent => $percent, + seconds_ago => $seconds_ago, + timestamp => $timestamp, + unixtime => $unixtime, + }}); + + $anvil->data->{say}{maintenance} = $anvil->Template->get({file => "striker.html", name => "striker-offline", variables => { + title_id => "", + message_id => "", + title => "#!string!striker_0046!#", + description => $anvil->Words->string({key => "striker_0047", variables => { percent => $percent, timestamp => $timestamp, seconds_ago => $seconds_ago }}), + }}); + $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 => { available => $available }}); return($available); } -# This requests the job to reconfigure the network be run -sub save_job -{ - my ($anvil) = @_; - - # Record the job! - my ($job_uuid) = $anvil->Database->insert_or_update_jobs({ - debug => 2, - file => $THIS_FILE, - line => __LINE__, - job_command => "anvil-configure-striker", - 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!#"; - - # 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. sub config_step3 { diff --git a/html/skins/alteeve/main.html b/html/skins/alteeve/main.html index 824d61b3..b4c5b668 100644 --- a/html/skins/alteeve/main.html +++ b/html/skins/alteeve/main.html @@ -177,22 +177,6 @@ - - -
-
- - - -
- #!variable!title!#
- #!variable!description!# -
-
- Reload -
- - diff --git a/html/skins/alteeve/striker.html b/html/skins/alteeve/striker.html index 13ea7a3b..cba0e6ba 100644 --- a/html/skins/alteeve/striker.html +++ b/html/skins/alteeve/striker.html @@ -447,3 +447,35 @@ + + + +
+
+ + + +
+ #!variable!title!#
+ #!variable!description!# +
+
+ Reload +
+ + + + +
+
+ + + +
+ #!variable!title!#
+ #!variable!description!# +
+
+ Reload +
+ diff --git a/share/words.xml b/share/words.xml index bb1a608a..e0883082 100644 --- a/share/words.xml +++ b/share/words.xml @@ -280,7 +280,7 @@ The database connection error was: The user has been logged out. The user hash in the user's cookie is valid. The user hash in the user's cookie was valid yesterday, updating the stored hash and allowing the user to proceed. - The user hash in the user's coolkie is invalid. It is probably expired. + The user hash in the user's cookie is invalid. It is probably expired. The user: [#!variable!user!#] logged in successfully. Theew was a failed login attempt from: [#!variable!user_agent!#], trying to log in as: [#!variable!user!#]. log in rejected. ]]> @@ -295,6 +295,7 @@ The database connection error was: Switching the default database to read from to the database: [#!variable!server!#] prior to reconnect attempt. Ready to try to reconnect to: [#!variable!server!#], but delaying for: [#!variable!delay!#] seconds to give the database a chance to come back online in case this is a transient issue. Failed to reconnect to the database, and now no connections remail. Exiting. + maintenance_mode() was passed an invalid 'set' value: [#!variable!set!#]. No action taken.]]> Test @@ -420,10 +421,14 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st Confirmed This Striker has been marked as reconfigured. Reload to start the confguration process. Would you like to update the operating system on this machine? This Striker will be placed into maintenance mode until the update completes. + When enabled on a Striker dashboard, the web interface will be disabled and ScanCore will not record to the local database. When enabled on a node, no servers will be allowed to run on it, and any already running on it will be migrated. When run on a DR node, that node will be disconnected from storage and no servers will be allowed to run on it. When disabled, all normal functions are available + The system will be updated momentarily. This system will now be in maintenance mode until the update is complete. Configure Network 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. + Update Striker + This system is now scheduled to be updated. The IP address will change. You will need to reconnect after applying these changes. diff --git a/tools/anvil-configure-striker b/tools/anvil-configure-striker index 45c86131..9cf4b03f 100755 --- a/tools/anvil-configure-striker +++ b/tools/anvil-configure-striker @@ -78,6 +78,8 @@ $anvil->Database->insert_or_update_variables({ variable_source_uuid => $anvil->Get->host_uuid, variable_source_table => "hosts", }); +# Clear maintenance mode. +$anvil->System->maintenance_mode({debug => 2, set => 0}); ### TODO: This is only until we can get the damn networking stable on reconfigure. if (not $anvil->data->{switches}{'no-reboot'}) diff --git a/tools/anvil.sql b/tools/anvil.sql index e87fb8e0..26f6a9da 100644 --- a/tools/anvil.sql +++ b/tools/anvil.sql @@ -357,7 +357,7 @@ 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_command text not null, -- This is the command to run (usually a shell call). - job_data text not null, -- + job_data text not null, -- A job can optionally use this to store miscellaneous data that doesn't belong elsewhere job_picked_up_by numeric not null default 0, -- This is the PID of the 'anvil-jobs' script that picked up the job. job_picked_up_at numeric not null default 0, -- This is unix timestamp of when the job was picked up. job_updated numeric not null default 0, -- This is unix timestamp that is perdiodically updated for jobs that take a long time. It is used to help determine when a job is hung.