Veamos como usar las plantillas mason para generar los
ficheros de configuración de nuestro módulo ntp. Cuando
estudiamos el servicio que ibamos a implementar vimos que todo el
trabajo del demonio ntp se basa en el fichero de configuración
/etc/ntp.conf. Usaremos el mismo sistema que
genera HTML para generar este fichero.
Esta parte del módulo pertenece al backend, por lo que
todos los métodos necesarios para implementarla se incluirán en
EBox::NTP.
Lo primero que debemos hacer es implementar un método privado
en nuestro módulo, que llamamos _setNTPConf,
y será llamado cada vez que sea necesario generar el fichero de
configuración del demonio. Su implementación es la siguiente:
Ejemplo 7.18. Generar el fichero de configuración
/etc/ntp.conf
sub _setNTPConf
{
my $self = shift;
my @array = ();
my @servers = $self->servers;
my $synch = 'no';
my $active = 'no';
($self->synchronized) and $synch = 'yes';
($self->service) and $active = 'yes';
push(@array, 'active' => $active);
push(@array, 'synchronized' => $synch);
push(@array, 'servers' => \@servers);
$self->writeConfFile(NTPCONFFILE, "ntp/ntp.conf.mas", \@array);
}Como podemos ver su implementación es sencilla, simplemente
añadimos a la variable array los parámetros que
queremos pasar a la plantilla mason, en nuestro caso le pasamos el
parámetro active que indicará si el servicio
de sincronización a clientes de nuestra red está activo o no, el
parámetro synchronized que indicará si está
activado el servicio de sincronización externa y un último parámetro
servers que es un array con la lista de
servidores externos a los que podemos tratar de sincronizarnos. Por
último, llamamos al método writeConfFile que
se encargará de generar el fichero de configuración con los permisos
adecuados y al que le pasamos como parámetros:
La ruta completa donde se encuentra el fichero de
configuración final del servicio. En nuestro caso usamos la
constante NTPCONFFILE que debemos tener
definida anteriormente en las cabeceras de nuestro módulo de la
siguiente manera:
use constant NTPCONFFILE => "/etc/ntp.conf";
La ruta donde se encuentra la plantilla mason a utilizar.
Un array con los parámetros que deseamos pasarle a la anterior plantilla.
Veamos ahora como implementar la plantilla. Hay ciertos parámetros del fichero de configuración que hemos creido conveniente dejar con un valor preestablecido ya que así lo decidimos en la fase de estudio del servicio. Por lo demás la implementación se realiza de la misma manera que cuando generamos las plantillas mason HTML.
Ejemplo 7.19. Plantilla mason para generar el fichero
/etc/ntp.conf
<%args>
$active
$synchronized
@servers
</%args>
# /etc/ntp.conf, configuration for ntpd
# Generated by EBox
driftfile /var/lib/ntp/ntp.drift
statsdir /var/log/ntpstats/
% if ($synchronized eq 'yes') {
% if ($servers[0]) {
server <% $servers[0] %>
% }
% if ($servers[1]) {
server <% $servers[1] %>
% }
% if ($servers[2]) {
server <% $servers[2] %>
% }
% }
% if ($active eq 'yes') {
server 127.127.1.0
% }
fudge 127.127.1.0 stratum 13
restrict default kod notrap nomodify nopeer noquery
restrict 127.0.0.1 nomodifyYa tan solo nos queda ver cómo controlar el demonio del
servicio. Debemos implementar varios métodos, el primero de ellos el
método abstracto de la clase base Ebox::Module
_regenConfig, llamado cuando se
relanzan los servicios eBox o cuando se salvan datos del
módulo. Su función generar los ficheros de configuración y
es por ello que ha de realizar una llamada al método visto
anteriormente _setNTPConf. Veamos como está
implementado:
Ejemplo 7.20. Método _regenConfig
sub _regenConfig
{
my $self = shift;
$self->_setNTPConf;
$self->_doDaemon();
}Junto con la llamada al método que genera el fichero
de configuración, realizamos una llamada al método
_doDaemon. Éste y los métodos:
_daemon, _stopService
y isRunning realizarán todo el control sobre
el demonio. Veamos uno a uno cómo están implementados, empezando por
_doDaemon:
Ejemplo 7.21. Método para la gestión del demonio
sub _doDaemon
{
my $self = shift;
my $logger = EBox::Global->logger;
if (($self->service or $self->synchronized) and $self->isRunning) {
$self->_daemon('stop');
sleep 2;
if ($self->synchronized) {
my $exserver = $self->get_string('server1');
try {
root("/usr/sbin/ntpdate $exserver");
} catch EBox::Exceptions::Internal with {
$logger->info("Error, ntpdate could" .
" not be started.");
};
}
$self->_daemon('start');
} elsif ($self->service or $self->synchronized) {
if ($self->synchronized) {
my $exserver = $self->get_string('server1');
try {
root("/usr/sbin/ntpdate $exserver");
} catch EBox::Exceptions::Internal with {
$logger->info("Error ntpdate could" .
" not be started.");
};
}
$self->_daemon('start');
} elsif ($self->isRunning) {
$self->_daemon('stop');
if ($self->synchronized) {
$self->_daemon('start');
}
}
}Este método será llamado para:
Lanzar el servicio porque estaba parado.
Relanzarlo en caso de que ya estubiera lanzado.
Pararlo.
Según el caso en que nos encontremos realizaremos
llamadas al método _daemon, cuya
implementación veremos a continuación, con la acción que
queramos realizar: start o stop. Lo único que debemos tener
en cuenta es que si el servicio de sincronización mediante
servidores externos está activado, debemos tratar de sincronizarnos
con el primero de los servidores ntp mediante el comando
/usr/sbin/ntpdate, antes de arrancar el servicio con
la llamada a $self->_daemon('start') ésta es
una práctica recomendada antes de lanzar un demonio de ntp.
Veamos ahora el método _daemon,
encargado de trabajar directamente con el demonio y lanzarlo,
pararlo o relanzarlo según la cadena que recibimos como parámetro. Su
implementación es muy sencilla:
Ejemplo 7.22. Comandos para arrancar y parar el demonio ntp.
sub _daemon # (action)
{
my ($self, $action) = @_;
if ( $action eq 'start') {
root("start-stop-daemon --start --quiet --pidfile" .
" /var/run/ntpd.pid --exec /usr/sbin/ntpd " .
" -- -g -p /var/run/ntpd.pid");
} elsif ( $action eq 'stop') {
root("start-stop-daemon --stop --quiet --pidfile" .
" /var/run/ntpd.pid");
} elsif ( $action eq 'force-reload') {
root("start-stop-daemon --stop --quiet --pidfile"
" /var/run/ntpd.pid");
sleep 2;
root("start-stop-daemon --start --quiet --exec /usr/sbin/ntpd -- -g -p /var/run/ntpd.pid");
} else {
throw EBox::Exceptions::Internal("Bad argument: $action");
}
}Por último nos queda por ver cómo dos métodos, por un lado el
método abstracto de la clase base EBox::Module
_stopService que simplemente parará el
servicio, y el método isRunning que nos dirá
si el servicio está en ejecución o no a través de su identificador de
proceso o PID.
Ejemplo 7.23. Método _stopService.
sub _stopService
{
my $self = shift;
if ($self->isRunning) {
$self->_daemon('stop');
}
}
Ejemplo 7.24. Método para saber si el servicio está ejecutándose.
sub isRunning
{
my $self = shift;
return $self->pidFileRunning(PIDFILE);
}