* Got email reconfiguration when a mail queue is over ten minutes old (needs testing).

* Updated Storage->write_file to remove the cache for a written file if it exists.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 4 years ago
parent 767148b538
commit aad68b8ed0
  1. 1
      Anvil/Tools.pm
  2. 12
      Anvil/Tools/Database.pm
  3. 155
      Anvil/Tools/Email.pm
  4. 6
      Anvil/Tools/Storage.pm
  5. 8
      notes
  6. 5
      rpm/SPECS/anvil.spec
  7. 3
      tools/test.pl

@ -1208,6 +1208,7 @@ sub _set_paths
psql => "/usr/bin/psql",
'postgresql-setup' => "/usr/bin/postgresql-setup",
postmap => "/usr/sbin/postmap",
postqueue => "/usr/sbin/postqueue",
pwd => "/usr/bin/pwd",
pvs => "/usr/sbin/pvs",
pvscan => "/usr/sbin/pvscan",

@ -2732,6 +2732,9 @@ FROM
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"mail_servers::address_to_uuid::${mail_server_address}" => $anvil->data->{mail_servers}{address_to_uuid}{$mail_server_address},
}});
# Set a default 'last_used' of 0 for this host.
$anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{last_used} = 0;
}
# Look up variables for this server.
@ -2766,6 +2769,15 @@ AND
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"mail_servers::use_order::${local_host}::variables::${variable_name}" => $anvil->data->{mail_servers}{use_order}{$local_host}{variables}{$variable_name},
}});
if ($variable_name =~ /mail_server::last_used::(.*)$/)
{
my $mail_server_uuid = $1;
$anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{last_used} = $variable_value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"mail_servers::mail_server::${mail_server_uuid}::last_used" => $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{last_used},
}});
}
}
return(0);

@ -11,6 +11,7 @@ package Anvil::Tools::Email;
use strict;
use warnings;
use Data::Dumper;
use JSON;
use Scalar::Util qw(weaken isweak);
use Text::Diff;
@ -104,10 +105,21 @@ sub check_config
# We check to see if there are any emails in the queue. If we see queued emails for more than five
# minutes, and a second mail server is configured, we'll automatically reconfigure for the next
# known server.
$anvil->Database->get_mail_servers({debug => $debug});
my ($oldest_message) = $anvil->Email->check_queue({debug => $debug});
if ($oldest_message > 600)
{
$anvil->Email->swap_server({debug => $debug});
# Switch out mail servers. If there's only one mail server, this just checks the existing
# config.
my $mail_server_uuid = $anvil->Email->get_next_server({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { mail_server_uuid => $mail_server_uuid }});
$anvil->Email->_configure_for_server({
debug => $debug,
mail_server_uuid => $mail_server_uuid,
});
return($problem);
}
# If not configured look in variables for 'mail_server::last_used::<mail_server_uuid>'. The first one
@ -117,26 +129,54 @@ sub check_config
# In any case where the mail server is configured, the server that is used has their
# 'mail_server::last_used::<mail_server_uuid>' variable set to the current time stamp.
# Is the postfix daemon running?
# Get the list of mail servers.
my $reconfigure = 1;
if ($reconfigure)
# What, if anything, is the current mail server?
my $current_mail_server = "";
my $postfix_main = $anvil->Storage->read_file({
debug => $debug,
file => $anvil->data->{path}{configs}{postfix_main},
});
foreach my $line (split/\n/, $postfix_main)
{
# Get the list of mail servers.
$anvil->Database->get_mail_servers({debug => $debug});
if (($line =~ /relayhost = \[(.*?)\]:/) or ($line =~ /relayhost = (.*?):/))
{
$current_mail_server = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { current_mail_server => $current_mail_server }});
# What is the UUID for this mail server?
my $mail_server_uuid = $anvil->data->{mail_servers}{address_to_uuid}{$current_mail_server} ? $anvil->data->{mail_servers}{address_to_uuid}{$current_mail_server} : "";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { mail_server_uuid => $mail_server_uuid }});
if ($mail_server_uuid)
{
# Looks OK, so run the configure (it'll do nothing if there are no changes).
$reconfigure = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { reconfigure => $reconfigure }});
### TODO: This just bootstraps the initial config
$anvil->Email->_configure_for_server({
debug => $debug,
mail_server_uuid => $mail_server_uuid,
});
}
}
}
if ($reconfigure)
{
my $used_mail_server_count = exists $anvil->data->{mail_servers}{use_order} ? keys %{$anvil->data->{mail_servers}{use_order}} : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { used_mail_server_count => $used_mail_server_count }});
if (not $used_mail_server_count)
{
# Just pick the first one.
foreach my $mail_server_uuid (keys %{$anvil->data->{mail_servers}{mail_server}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { mail_server_uuid => $mail_server_uuid }});
$anvil->Email->_configure_for_server({
debug => $debug,
mail_server_uuid => $mail_server_uuid,
});
last;
}
}
}
@ -161,24 +201,99 @@ sub check_queue
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Email->check_queue()" }});
my $oldest_message = 0;
my ($queue, $return_code) = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{postqueue}." -j"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
queue => $queue,
return_code => $return_code,
}});
### TODO
# If configured/running, the number of messages in queue is checked. If '0',
# 'mail_server::queue_empty' is updated with the current time. If 1 or more, the time since the queue
# was last 0 is checked. If > 300, the mail server is reconfigured to use the mail server with the
# oldest 'mail_server::last_used::<mail_server_uuid>' time.
# This is empty if there is nothing in the queue.
foreach my $email (split/\n/, $queue)
{
my $json = JSON->new->allow_nonref;
my $postqueueu = $json->decode($email);
my $queue_id = $postqueueu->{queue_id};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { queue_id => $queue_id }});
$anvil->data->{mail}{queue}{$queue_id}{sender} = $postqueueu->{sender};
$anvil->data->{mail}{queue}{$queue_id}{queue_name} = $postqueueu->{queue_name};
$anvil->data->{mail}{queue}{$queue_id}{arrival_time} = $postqueueu->{arrival_time};
$anvil->data->{mail}{queue}{$queue_id}{message_age} = time - $postqueueu->{arrival_time};
$anvil->data->{mail}{queue}{$queue_id}{message_size} = $postqueueu->{message_size};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"mail::queue::${queue_id}::sender" => $anvil->data->{mail}{queue}{$queue_id}{sender},
"mail::queue::${queue_id}::queue_name" => $anvil->data->{mail}{queue}{$queue_id}{queue_name},
"mail::queue::${queue_id}::arrival_time" => $anvil->data->{mail}{queue}{$queue_id}{arrival_time},
"mail::queue::${queue_id}::message_age" => $anvil->data->{mail}{queue}{$queue_id}{message_age},
"mail::queue::${queue_id}::message_size" => $anvil->data->{mail}{queue}{$queue_id}{message_size},
}});
foreach my $recipient_hash (@{$postqueueu->{recipients}})
{
my $address = $recipient_hash->{address};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { queue_id => $queue_id }});
$anvil->data->{mail}{queue}{$queue_id}{recipient}{$address}{delay_reason} = $recipient_hash->{delay_reason};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"mail::queue::${queue_id}::recipient::${address}::delay_reason" => $anvil->data->{mail}{queue}{$queue_id}{recipient}{$address}{delay_reason},
}});
}
if ($anvil->data->{mail}{queue}{$queue_id}{message_age} > $oldest_message)
{
$oldest_message = $anvil->data->{mail}{queue}{$queue_id}{message_age};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { oldest_message => $oldest_message }});
}
};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { oldest_message => $oldest_message }});
return($oldest_message);
}
=head2 swap_server
=head2 get_next_server
When two or more mail servers are configured, this will return the C<< mail_server_uuid >> of the mail server used in the most distant past. If two or more mail servers have never been used before, a random unused server is returned.
If only one mail servers exists, its UUID is returned, making this method safe to call without concern for configured mail server count.
This method takes no parameters.
=cut
sub swap_server
sub get_next_server
{
my $self = shift;
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 => "Email->check_queue()" }});
# If configured/running, the number of messages in queue is checked. If '0',
# 'mail_server::queue_empty' is updated with the current time. If 1 or more, the time since the queue
# was last 0 is checked. If > 300, the mail server is reconfigured to use the mail server with the
# oldest 'mail_server::last_used::<mail_server_uuid>' time.
my $oldest_mail_server_time = time;
my $oldest_mail_server_uuid = "";
foreach my $mail_server_uuid (keys %{$anvil->data->{mail_servers}{mail_server}})
{
my $last_used = $anvil->data->{mail_servers}{mail_server}{$mail_server_uuid}{last_used};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
mail_server_uuid => $mail_server_uuid,
last_used => $last_used,
}});
if ($last_used < $oldest_mail_server_time)
{
$oldest_mail_server_time = $last_used;
$oldest_mail_server_uuid = $mail_server_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
oldest_mail_server_time => $oldest_mail_server_time,
oldest_mail_server_uuid => $oldest_mail_server_uuid,
}});
}
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { oldest_mail_server_uuid => $oldest_mail_server_uuid }});
return($oldest_mail_server_uuid);
}
# =head3
@ -249,6 +364,7 @@ sub _configure_for_server
{
$old_postfix_relay_file = $anvil->Storage->read_file({
debug => $debug,
secure => 1,
file => $anvil->data->{path}{configs}{postfix_relay_password},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => {
@ -257,9 +373,7 @@ sub _configure_for_server
}
my $new_postfix_relay_file = "[".$mail_server_address."]:".$mail_server_port." ".$mail_server_username.":".$mail_server_password."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => {
new_postfix_relay_file => $new_postfix_relay_file,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { new_postfix_relay_file => $new_postfix_relay_file }});
if ($new_postfix_relay_file ne $old_postfix_relay_file)
{
@ -297,9 +411,7 @@ sub _configure_for_server
debug => $debug,
file => $anvil->data->{path}{configs}{postfix_main},
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
old_postfix_relay_file => $old_postfix_relay_file,
}});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { old_postfix_relay_file => $old_postfix_relay_file }});
my $last_line = "";
my $relayhost_seen = 0;
@ -678,7 +790,6 @@ sub _configure_for_server
user => "root",
group => "root",
overwrite => 1,
secure => 1,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
reload => $reload,

@ -3266,6 +3266,12 @@ sub write_file
print $file_handle $body;
close $file_handle;
# Delete the cache for this file, if it exists.
if (exists $anvil->data->{cache}{file}{$file})
{
delete $anvil->data->{cache}{file}{$file};
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { mode => $mode }});
if ($mode)
{

@ -1,3 +1,11 @@
============
From: test-alert@alert.alteeve.com
To: Madison Kelly <debug@alteeve.com>
Subject: [ ScanCore ] - Test email
Reply-To:
This is a test alert.
============
DISABLE KSM!

@ -26,6 +26,11 @@ Summary: Alteeve's Anvil! Core package
Requires: bash-completion
Requires: binutils
Requires: chrony
Requires: cyrus-sasl
Requires: cyrus-sasl-gssapi
Requires: cyrus-sasl-lib
Requires: cyrus-sasl-md5
Requires: cyrus-sasl-plain
Requires: bind-utils
Requires: dmidecode
Requires: dnf-utils

@ -29,5 +29,6 @@ $anvil->Database->connect();
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0132"});
$anvil->Get->switches;
$anvil->Email->check_config({debug => 3});
my ($oldest_message) = $anvil->Email->check_queue({debug => 2});
print "Oldest message: [".$oldest_message."]\n";

Loading…
Cancel
Save