Adding mail report support.

This commit is contained in:
sergiotarxz 2021-11-13 20:38:53 +01:00
parent 09e7d74d2f
commit 91562a3ae3
7 changed files with 224 additions and 27 deletions

View File

@ -10,5 +10,11 @@ WriteMakefile(
PREREQ_PM => {
'DBD::SQLite' => 0,
'DateTime' => 0,
'Email::Sender::Simple' => 0,
'Email::Sender::Transport::SMTP' => 0,
'Email::MIME' => 0,
'IO::Socket::SSL' => 0,
'MIME::Base64' => 0,
'Authen::SASL' => 0,
}
);

View File

@ -6,15 +6,34 @@ use strict;
use warnings;
use Carp qw/confess/;
use POSIX qw/WNOHANG/;
use Try::Tiny;
use Cualsea::Server::Loop;
use Cualsea::Server::MonitorController;
my $loop = Cualsea::Server::Loop->new;
my $pid = fork;
if ($pid) {{
local $SIG{INT} = \&finish_parent;
while (1) {
my $loop = Cualsea::Server::Loop->new;
try {
$loop->run;
} catch {
confess $_;
};
}
finish_parent();
}}
my $monitor_controller = Cualsea::Server::MonitorController->new;
while (1) {
try {
$loop->run;
} catch {
confess $_;
};
$monitor_controller->loop;
}
sub finish_parent {
kill 'INT', $pid;
1 while waitpid $pid, WNOHANG;
exit;
}

View File

@ -25,6 +25,11 @@ my @migrations = (
date_execution TEXT,
parameters TEXT,
result TEXT
);',
'CREATE TABLE monitor (
id INTEGER PRIMARY KEY,
date_execution TEXT,
is_up INTEGER
);'
);

View File

@ -0,0 +1,88 @@
package Cualsea::Server::Mail;
use v5.30.0;
use strict;
use warnings;
use Const::Fast;
use Email::Sender::Transport::SMTP;
use Email::Sender::Simple qw/sendmail/;
use Email::MIME;
const my $MAIL_CONFIG_FILE => '/etc/cualsea/mail.conf';
const my $REPORT_TO_CONFIG_FILE => '/etc/cualsea/report_to';
const my $FROM_CONFIG_FILE => '/etc/cualsea/from';
sub new {
my $class = shift;
return bless {}, $class;
}
sub notify_service_down {
my $self = shift;
my $name = shift;
my $mime = Email::MIME->create(
header_str => [
From => $self->from,
To => [ $self->report_to ],
Subject => "Service $name down",
],
parts => [
Email::MIME->create(
attributes => {
content_type => 'text/plain',
disposition => 'attachment',
charset => 'UTF-8',
encoding => "8bit",
},
body_str => "$name is not up",
)
]
);
sendmail($mime, { transport => $self->transport });
}
sub report_to {
my $self = shift;
if (!defined $self->{report_to}) {
open my $fh, '<', $REPORT_TO_CONFIG_FILE or die "Unable to get mail to report from config file";
my $email = <$fh>;
chomp $email;
close $fh;
$self->{report_to} = $email;
}
return $self->{report_to};
}
sub from {
my $self = shift;
if (!defined $self->{from}) {
open my $fh, '<', $FROM_CONFIG_FILE or die "Unable to get mail From from config file";
my $email = <$fh>;
chomp $email;
close $fh;
$self->{from} = $email;
}
return $self->{from};
}
sub transport {
my $self = shift;
if (!defined $self->{transport}) {
my %parameters;
open my $fh, '<', $MAIL_CONFIG_FILE or die "Unable to get transport from config file";
while (my $line = <$fh>) {
my ($key, $value) = $line =~ /^(.*?)=(.*?)\s*$/;
if ($key eq 'hosts') {
$value = [ $value ];
}
$parameters{$key} = $value;
}
close $fh;
$self->{transport} = Email::Sender::Transport::SMTP->new(%parameters);
}
return $self->{transport};
}
1;

View File

@ -18,6 +18,7 @@ use JSON;
use Cualsea::MessageManager;
use Cualsea::Server::DB;
use Cualsea::Server::Service;
sub handle_add {
my %params = @_;
@ -62,7 +63,7 @@ sub handle_del {
my $name = $params{name};
my $dbh = Cualsea::Server::DB->dbh();
if ( !check_if_service_exists_in_db($name) ) {
if ( !Cualsea::Server::Service::check_if_service_exists_in_db($name) ) {
return {
is_error => 1,
desc => 'Service not found.',
@ -81,23 +82,13 @@ EOF
};
}
sub check_if_service_exists_in_db {
my $name = shift;
my $dbh = Cualsea::Server::DB->dbh();
my $service = $dbh->selectrow_hashref( <<"EOF", undef, $name );
SELECT name FROM services WHERE name = ?
EOF
if ( !defined $service ) {
return 0;
}
return 1;
}
sub handle_start {
my %params = @_;
my $name = $params{name};
if ( !check_if_service_exists_in_db($name) ) {
if ( !Cualsea::Server::Service::check_if_service_exists_in_db($name) ) {
return {
is_error => 1,
desc => 'Service not found.',
@ -105,7 +96,7 @@ sub handle_start {
};
}
if ( _is_started_service($name) ) {
if ( Cualsea::Server::Service::is_started_service($name) ) {
return {
is_error => 1,
desc => 'Service already started.',
@ -120,23 +111,19 @@ sub handle_start {
};
}
sub _is_started_service {
my $name = shift;
return !system "/etc/init.d/$name", 'status';
}
sub handle_stop {
my %params = @_;
my $name = $params{name};
if ( !check_if_service_exists_in_db($name) ) {
if ( !Cualsea::Server::Service::check_if_service_exists_in_db($name) ) {
return {
is_error => 1,
desc => 'Service not found.',
status => 404,
};
}
if ( !_is_started_service($name) ) {
if ( !Cualsea::Server::Service::is_started_service($name) ) {
return {
is_error => 1,
desc => 'Service already stopped.',
@ -156,7 +143,7 @@ sub handle_restart {
my %params = @_;
my $name = $params{name};
if ( !check_if_service_exists_in_db($name) ) {
if ( !Cualsea::Server::Service::check_if_service_exists_in_db($name) ) {
return {
is_error => 1,
desc => 'Service not found.',

View File

@ -0,0 +1,68 @@
package Cualsea::Server::MonitorController;
use v5.30.0;
use strict;
use warnings;
use DateTime;
use Cualsea::Server::DB;
use Cualsea::Server::Service;
use Cualsea::Server::Mail;
sub new {
my $class = shift;
return bless {}, $class;
}
sub last_date {
my $self = shift;
if ( !exists $self->{last_date} ) {
$self->{last_date} = DateTime->now();
}
return $self->{last_date};
}
sub loop {
my $self = shift;
my $last_date = $self->last_date;
my $current_date = DateTime->now();
if ( $current_date > $last_date->clone->add( minutes => 1 ) ) {
$self->{last_date} = $current_date;
$self->monitor;
}
}
sub monitor {
my $self = shift;
my $dbh = Cualsea::Server::DB->dbh();
my $services = $dbh->selectall_arrayref( <<'EOF', { Slice => {} } );
SELECT name,pidfile FROM services;
EOF
for my $service (@$services) {
my $pidfile = $service->{pidfile};
my $name = $service->{name};
my $started = Cualsea::Server::Service::is_started_service($name);
if ($started) {{
my $success_opening = open my $fh, '<', $pidfile;
if (!$success_opening) {
$started = 0;
# Cool trick to escape if {{ }}
next;
}
my $pid = <$fh>;
chomp $pid;
$started = !system 'ps', '-p', $pid;
close $fh;
}}
$dbh->do( 'INSERT INTO monitor (date_execution, is_up) VALUES (?, ?);',
undef, DateTime->now() . '', $started );
if (!$started) {
say "$name stopped";
my $mailer = Cualsea::Server::Mail->new();
$mailer->notify_service_down($name);
}
}
}
1;

View File

@ -0,0 +1,24 @@
package Cualsea::Server::Service;
use v5.30.0;
use strict;
use warnings;
sub is_started_service {
my $name = shift;
return !system "/etc/init.d/$name", 'status';
}
sub check_if_service_exists_in_db {
my $name = shift;
my $dbh = Cualsea::Server::DB->dbh();
my $service = $dbh->selectrow_hashref( <<"EOF", undef, $name );
SELECT name FROM services WHERE name = ?
EOF
if ( !defined $service ) {
return 0;
}
return 1;
}
1;