diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 0ef79b46..ea7a3748 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -44,6 +44,7 @@ use Anvil::Tools::Alert; use Anvil::Tools::Convert; use Anvil::Tools::Database; use Anvil::Tools::DRBD; +use Anvil::Tools::Email; use Anvil::Tools::Get; use Anvil::Tools::Job; use Anvil::Tools::Log; @@ -125,6 +126,7 @@ sub new CONVERT => Anvil::Tools::Convert->new(), DATABASE => Anvil::Tools::Database->new(), DRBD => Anvil::Tools::DRBD->new(), + EMAIL => Anvil::Tools::Email->new(), GET => Anvil::Tools::Get->new(), LOG => Anvil::Tools::Log->new(), JOB => Anvil::Tools::Job->new(), @@ -166,6 +168,7 @@ sub new $anvil->Convert->parent($anvil); $anvil->Database->parent($anvil); $anvil->DRBD->parent($anvil); + $anvil->Email->parent($anvil); $anvil->Get->parent($anvil); $anvil->Log->parent($anvil); $anvil->Job->parent($anvil); @@ -502,6 +505,18 @@ sub DRBD return ($self->{HANDLE}{DRBD}); } +=head2 Email + +Access the C methods via 'C<< $anvil->Email->method >>'. + +=cut +sub Email +{ + my $self = shift; + + return ($self->{HANDLE}{EMAIL}); +} + =head2 Get Access the C methods via 'C<< $anvil->Get->method >>'. diff --git a/Anvil/Tools/Account.pm b/Anvil/Tools/Account.pm index b2039526..18da3b7c 100644 --- a/Anvil/Tools/Account.pm +++ b/Anvil/Tools/Account.pm @@ -531,15 +531,19 @@ sub read_cookies # Validate the cookie if there is a User UUID. Pick the random number up from the database. my $query = " SELECT - session_salt + a.user_name, + b.session_salt FROM - sessions + users a, + sessions b WHERE - session_user_uuid = ".$anvil->Database->quote($anvil->data->{cookie}{anvil_user_uuid})." + a.user_uuid = b.session_user_uuid +AND + b.session_user_uuid = ".$anvil->Database->quote($anvil->data->{cookie}{anvil_user_uuid})." AND - session_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." + b.session_host_uuid = ".$anvil->Database->quote($anvil->Get->host_uuid)." ;"; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0124", variables => { 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 => { @@ -562,9 +566,13 @@ AND } # Read in their "rand" value - $anvil->data->{sessions}{session_salt} = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; + $anvil->data->{sys}{users}{user_name} = $results->[0]->[0]; + $anvil->data->{sessions}{session_salt} = $results->[0]->[1]; $anvil->data->{sessions}{session_salt} = "" if not defined $anvil->data->{sessions}{session_salt}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sessions::session_salt" => $anvil->data->{sessions}{session_salt} }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "sys::users::user_name" => $anvil->data->{sys}{users}{user_name}, + "sessions::session_salt" => $anvil->data->{sessions}{session_salt}, + }}); # Generate a hash using today and yesterday's date. my ($today_hash) = $anvil->Account->_build_cookie_hash({ diff --git a/Anvil/Tools/Email.pm b/Anvil/Tools/Email.pm new file mode 100755 index 00000000..88d30dec --- /dev/null +++ b/Anvil/Tools/Email.pm @@ -0,0 +1,121 @@ +package Anvil::Tools::Email; +# +# This module contains methods used to manage the local postfix server and handle and dispatch email via +# mailx. +# + +use strict; +use warnings; +use Scalar::Util qw(weaken isweak); +use Data::Dumper; + +our $VERSION = "3.0.0"; +my $THIS_FILE = "Email.pm"; + +### Methods; + +=pod + +=encoding utf8 + +=head1 NAME + +Anvil::Tools::Email + +Provides all methods used to manage the local C<< postfix >> server and handle and dispatch email via C<< mailx >> + +=head1 SYNOPSIS + + use Anvil::Tools; + + # Get a common object handle on all Anvil::Tools modules. + my $anvil = Anvil::Tools->new(); + + # Access to methods using '$anvil->Email->X'. + # + # + +=head1 METHODS + +Methods in this module; + +=cut +sub new +{ + my $class = shift; + my $self = { + }; + + bless $self, $class; + + return ($self); +} + +# Get a handle on the Anvil::Tools object. I know that technically that is a sibling module, but it makes more +# sense in this case to think of it as a parent. +sub parent +{ + my $self = shift; + my $parent = shift; + + $self->{HANDLE}{TOOLS} = $parent if $parent; + + # Defend against memory leads. See Scalar::Util'. + if (not isweak($self->{HANDLE}{TOOLS})) + { + weaken($self->{HANDLE}{TOOLS}); + } + + return ($self->{HANDLE}{TOOLS}); +} + +############################################################################################################# +# Public methods # +############################################################################################################# + +=head2 check_postfix + +This method checks the current postfix server configuration to see if it needs to be updated, then checks to see if the local C<< postfix >> daemin is enabled and started. + +If any problem is encountered, C<< 1 >> is returned. Otherwise, if all is well, C<< 0 >> is returned. + +Parameters; + +=head3 config (optional, default '1') + +If set to C<< 0 >>, the configuration is not checked or updated. + +=head3 daemon (optional, default '1') + +If set to C<< 0 >>, the C<< postfix >> daemon is not checked or started. + +=cut +sub check_postfix +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + + my $problem = 0; + my $config = defined $parameter->{config} ? $parameter->{config} : 1; + my $daemon = defined $parameter->{daemon} ? $parameter->{daemon} : 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + config => $config, + daemon => $daemon, + }}); + + + + return($problem); +} + +# =head3 +# +# Private Functions; +# +# =cut + +############################################################################################################# +# Private functions # +############################################################################################################# diff --git a/cgi-bin/striker b/cgi-bin/striker index 1ef4287d..2142ac7f 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -210,6 +210,7 @@ sub print_and_exit files_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "files_button_on"}) : $anvil->Template->get({file => "main.html", name => "files_button_off"}), jobs_button => $say_jobs_button, striker_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "striker_button_on"}) : $anvil->Template->get({file => "main.html", name => "striker_button_off"}), + email_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "email_button_on"}) : $anvil->Template->get({file => "main.html", name => "email_button_off"}), user_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "user_button_on"}) : $anvil->Template->get({file => "main.html", name => "user_button_off"}), }}); my $footer = $anvil->Template->get({file => "main.html", name => "footer", variables => { @@ -329,6 +330,10 @@ sub process_task { process_jobs_menu($anvil); } + elsif ($anvil->data->{cgi}{email}{value}) + { + process_email_menu($anvil); + } else { # Load the main page. @@ -349,6 +354,52 @@ sub process_task return(0); } +# This handles tasks related to email, mail servers and alert recipients. +sub process_email_menu +{ + my ($anvil) = @_; + + $anvil->data->{form}{back_link} = "?email=true"; + $anvil->data->{cgi}{task}{value} = "" if not defined $anvil->data->{cgi}{task}{value}; + $anvil->data->{cgi}{action}{value} = "" if not defined $anvil->data->{cgi}{action}{value}; + $anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "form::back_link" => $anvil->data->{form}{back_link}, + "cgi::task::value" => $anvil->data->{cgi}{task}{value}, + "cgi::action::value" => $anvil->data->{cgi}{action}{value}, + "cgi::save::value" => $anvil->data->{cgi}{save}{value}, + }}); + + if ($anvil->data->{cgi}{task}{value} eq "email_server") + { + #process_email_server_page($anvil); + } + elsif ($anvil->data->{cgi}{task}{value} eq "email_recipient") + { + #process_email_recipient_page($anvil); + } + else + { + # What we show for the reboot icon and text depends on if a reboot is pending. + my $reboot_needed = $anvil->System->reboot_needed(); + my $reboot_icon = $reboot_needed ? "reboot_needed_icon.png" : "reboot_icon.png"; + my $reboot_message = $reboot_needed ? "#!string!striker_0093!#" : "#!string!striker_0092!#"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + reboot_needed => $reboot_needed, + reboot_icon => $reboot_icon, + reboot_message => $reboot_message, + }}); + + # The 'back' goes home + $anvil->data->{form}{back_link} = "?"; + $anvil->data->{form}{refresh_link} = "?email=true"; + $anvil->data->{form}{body} = $anvil->Template->get({file => "email.html", name => "main-menu", variables => { + }}); + } + + return(0); +} + # This handles the "Striker" menu items. sub process_striker_menu { diff --git a/html/skins/alteeve/email.html b/html/skins/alteeve/email.html new file mode 100644 index 00000000..b598757e --- /dev/null +++ b/html/skins/alteeve/email.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + +
+   +
+ #!string!striker_0165!# +
+   +
+ + + #!string!striker_0166!# +
+ + + #!string!striker_0167!# +
+ + diff --git a/html/skins/alteeve/email.js b/html/skins/alteeve/email.js new file mode 100644 index 00000000..353a83ba --- /dev/null +++ b/html/skins/alteeve/email.js @@ -0,0 +1,6 @@ +$.ajaxSetup({ + cache: false +}); +$(function() { + +}); diff --git a/html/skins/alteeve/images/email_off.png b/html/skins/alteeve/images/email_off.png new file mode 100644 index 00000000..7ed0f653 Binary files /dev/null and b/html/skins/alteeve/images/email_off.png differ diff --git a/html/skins/alteeve/images/email_on.png b/html/skins/alteeve/images/email_on.png new file mode 100644 index 00000000..98c996f7 Binary files /dev/null and b/html/skins/alteeve/images/email_on.png differ diff --git a/html/skins/alteeve/images/email_recipient.png b/html/skins/alteeve/images/email_recipient.png new file mode 100644 index 00000000..8c7ce4a7 Binary files /dev/null and b/html/skins/alteeve/images/email_recipient.png differ diff --git a/html/skins/alteeve/images/email_server.png b/html/skins/alteeve/images/email_server.png new file mode 100644 index 00000000..54248afe Binary files /dev/null and b/html/skins/alteeve/images/email_server.png differ diff --git a/html/skins/alteeve/images/sources.txt b/html/skins/alteeve/images/sources.txt index 3cc078c4..f164e80b 100644 --- a/html/skins/alteeve/images/sources.txt +++ b/html/skins/alteeve/images/sources.txt @@ -58,3 +58,12 @@ Folder by Mint Shirt from the Noun Project (https://thenounproject.com/term/fold Broken Key by I Putu Kharismayadi from the Noun Project (https://thenounproject.com/term/folder/1481931/) - broken_key.png + +Mail By unlimicon, ID from the Noun Project (https://thenounproject.com/term/mail/867234/) + - email.png + +Mail server Mail Server by SBTS from the Noun Project (https://thenounproject.com/term/mail-server/1236869/) + - email_server.png + +Reader by Richa from the Noun Project + - email_recipient.png diff --git a/html/skins/alteeve/main.html b/html/skins/alteeve/main.html index deeb4d2a..055e9fea 100644 --- a/html/skins/alteeve/main.html +++ b/html/skins/alteeve/main.html @@ -48,6 +48,9 @@ #!variable!anvil_button!# + + #!variable!email_button!# + #!variable!user_button!# @@ -58,6 +61,14 @@ + + + + + +#!string!striker_0164!# + + diff --git a/notes b/notes index 98987e68..68e49348 100644 --- a/notes +++ b/notes @@ -48,21 +48,29 @@ dnf download --source awscli booth booth-arbitrator booth-core booth-site booth- pcs pcs-snmp python3-azure-sdk python3-boto3 python3-botocore python3-fasteners python3-gflags python3-google-api-client python3-httplib2 python3-oauth2client python3-s3transfer python3-uritemplate \ resource-agents resource-agents-aliyun resource-agents-gcp -rpm -Uvh python-s3transfer-0.1.13-1.el8.src.rpm python-oauth2client-4.1.2-6.el8.src.rpm booth-1.0-5.f2d38ce.git.el8.src.rpm google-api-python-client-1.6.5-3.el8.src.rpm python-boto3-1.6.1-2.el8.src.rpm python-httplib2-0.10.3-4.el8.src.rpm python-botocore-1.9.1-2.el8.src.rpm corosync-qdevice-3.0.0-2.el8.src.rpm python-uritemplate-3.0.0-3.el8.src.rpm python3-azure-sdk-4.0.0-9.el8.src.rpm awscli-1.14.50-5.el8.src.rpm python-gflags-2.0-15.el8ost.src.rpm resource-agents-4.1.1-33.el8.src.rpm python-fasteners-0.14.1-15.el8ost.src.rpm pcs-0.10.2-4.el8.src.rpm fence-agents-4.2.1-30.el8_1.1.src.rpm +rpm -Uvh python-s3transfer-0.1.13-1.el8.src.rpm python-oauth2client-4.1.2-6.el8.src.rpm booth-1.0-5.f2d38ce.git.el8.src.rpm google-api-python-client-1.6.5-3.el8.src.rpm python-boto3-1.6.1-2.el8.src.rpm python-httplib2-0.10.3-4.el8.src.rpm python-botocore-1.9.1-2.el8.src.rpm corosync-qdevice-3.0.0-2.el8.src.rpm python-uritemplate-3.0.0-3.el8.src.rpm python3-azure-sdk-4.0.0-9.el8.src.rpm awscli-1.14.50-5.el8.src.rpm python-gflags-2.0-15.el8ost.src.rpm resource-agents-4.1.1-33.el8.src.rpm pcs-0.10.2-4.el8.src.rpm fence-agents-4.2.1-30.el8_1.1.src.rpm +rpm -Uvh python-fasteners-0.14.1-15.el8ost.src.rpm -rpmbuild -ba python-s3transfer.spec python-oauth2client.spec booth.spec google-api-python-client.spec python-boto3.spec python-httplib2.spec python-botocore.spec corosync-qdevice.spec python-uritemplate.spec python3-azure-sdk.spec \ - awscli.spec python-gflags.spec resource-agents.spec python-fasteners.spec pcs.spec fence-agents.spec +rpm -Uvh awscli-1.14.50-5.el8.src.rpm booth-1.0-5.f2d38ce.git.el8.src.rpm corosync-qdevice-3.0.0-2.el8.src.rpm fence-agents-4.2.1-30.el8.1.src.rpm google-api-python-client-1.6.5-3.el8.src.rpm pacemaker-2.0.2-3.el8.2.src.rpm \ + pcs-0.10.2-4.el8.src.rpm python-boto3-1.6.1-2.el8.src.rpm python-botocore-1.9.1-2.el8.src.rpm python-gflags-2.0-15.el8.src.rpm python-httplib2-0.10.3-4.el8.src.rpm python-oauth2client-4.1.2-6.el8.src.rpm \ + python-s3transfer-0.1.13-1.el8.src.rpm python-uritemplate-3.0.0-3.el8.src.rpm python3-azure-sdk-4.0.0-9.el8.src.rpm resource-agents-4.1.1-33.el8.src.rpm -The key packages which are needed are: - corosync - corosynclib-devel - pacemaker - pacemaker-cli - pacemaker-doc - pacemaker-libs-devel - pcs - resource-agents + +rpmbuild -ba --sign pcs.spec +rpmbuild -ba --sign python3-azure-sdk.spec +rpmbuild -ba --sign python-s3transfer.spec python-oauth2client.spec booth.spec google-api-python-client.spec python-boto3.spec python-httplib2.spec python-botocore.spec corosync-qdevice.spec python-uritemplate.spec awscli.spec python-gflags.spec resource-agents.spec fence-agents.spec + +# rpmbuild -ba python-fasteners.spec + + +### Need to find/build +python2-futures +python2-monotonic + + +dnf install booth-site corosync corosynclib-devel pacemaker pacemaker-cli pacemaker-libs-devel pcs + Network planning; diff --git a/rpm/SPECS/anvil.spec b/rpm/SPECS/anvil.spec index 6220f533..24f89e5f 100644 --- a/rpm/SPECS/anvil.spec +++ b/rpm/SPECS/anvil.spec @@ -37,6 +37,7 @@ Requires: hdparm Requires: htop Requires: iproute Requires: lsscsi +Requires: mailx Requires: mlocate Requires: perl-Capture-Tiny Requires: perl-Data-Dumper diff --git a/share/words.xml b/share/words.xml index cc36163c..bb609b5e 100644 --- a/share/words.xml +++ b/share/words.xml @@ -1019,6 +1019,10 @@ If you are comfortable that the target has changed for a known reason, you can s The network will soon be reconfigured and then the target will reboot. In a couple minutes, it should be ready. Return How many network connections will exist for each network type. + Email and alert configuration + Alert email server and recipient configuration. + Configure which server(s) can be used for forwarding email alerts to. + Configure who will receive email alerts. #!variable!number!#/sec diff --git a/tools/scancore b/tools/scancore index 103fcf65..b8e83e25 100755 --- a/tools/scancore +++ b/tools/scancore @@ -233,6 +233,8 @@ sub prepare_for_run $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0132"}); + # TODO: Check/configure the mail server. + return(0); } diff --git a/tools/test.pl b/tools/test.pl index 92ceb0be..0a07028b 100755 --- a/tools/test.pl +++ b/tools/test.pl @@ -30,4 +30,4 @@ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure = print "DB Connections: [".$anvil->data->{sys}{database}{connections}."]\n"; #$anvil->Network->load_interfces({debug => 2}); -$anvil->System->generate_state_json({debug => 2}); +#$anvil->System->generate_state_json({debug => 2});