###
###  Copyright 2000-2007 University of Illinois Board of Trustees
###  All rights reserved. 
###
###  NTP.pm - NTP configuration module for psgconf
###
###  Campus Information Technologies and Educational Services
###  University of Illinois at Urbana-Champaign
###


package PSGConf::Control::NTP;

use strict;

use PSGConf::Action::GenerateFile::ntp_conf;
use PSGConf::Action::RestartDaemon;
use PSGConf::Data::Boolean;
use PSGConf::Data::String;
use PSGConf::Data::Integer;
use PSGConf::Data::List;
use PSGConf::Control::Packages qw(_add_pkgs);


###############################################################################
###  decide() method
###############################################################################

sub decide
{
	my ($self, $psgconf) = @_;
	my ($driftfile, $rc_name);

	return
		if ($psgconf->data_obj('ntp_enable')->equals('false')
			|| ! $psgconf->data_obj('ntp_servers')->count() );

	$driftfile = ( defined $psgconf->data_obj('ntp_driftfile')->get() )?
					$psgconf->data_obj('ntp_driftfile')->get():
					$psgconf->data_obj('etc_inet_dir')->get() . '/ntp.drift';

	$rc_name = $psgconf->data_obj('ntp_daemon_name')->get();

	$psgconf->register_actions(
		PSGConf::Action::GenerateFile::ntp_conf->new(
			name		=> $psgconf->data_obj('etc_inet_dir')->get() . '/ntp.conf',
			description	=> 'NTP configuration file',
			servers		=> $psgconf->data_obj('ntp_servers')->get(),
			minpoll		=> $psgconf->data_obj('ntp_minpoll')->get(),
			maxpoll		=> $psgconf->data_obj('ntp_maxpoll')->get(),
			driftfile		=> $driftfile,
			daemon_name	=> $psgconf->data_obj('ntp_daemon_name')->get()
		),

		###
		### We have to use the rcscript restart option because
		### ntpd dies when getting a -HUP signal.  This really
		### sucks since we do have a PID file in
		### $psgconf->data_obj('pidfile_dir')->get()
		###
		### On solaris10, this is OK, because smf(1) restarts NTP 
		### automatically, but ideally, we should do a:
		### svcadm restart svc:/network/ntp:default
		###
		### There is also a problem on the Solaris < 10 systems that
		### when '/etc/init.d/xntpd stop' is run, the pkill kills off
		### the shutdown script itself.  The answer to that is to run
		### it as '/sbin/sh /etc/init.d/xntpd stop', but that is not
		### very portable.
		###
		PSGConf::Action::RestartDaemon->new(
			name           => $psgconf->data_obj('ntp_daemon_name')->get(),
			rcscript       => $psgconf->data_obj('rc_scripts')->find($rc_name)->{fullname},
			filename       => [ $psgconf->data_obj('etc_inet_dir')->get() . '/ntp.conf' ]
		)
	);
}


###############################################################################
###  policy methods
###############################################################################

sub _policy_enable_rc_scripts
{
	my ($self, $psgconf) = @_;
	my ($rc_name, $rc_vars);

	$rc_name = $psgconf->data_obj('ntp_daemon_name')->get();
	$rc_vars = $psgconf->data_obj('rc_vars')->get();

	$psgconf->data_obj('rc_scripts')->insert (
		{ $rc_name => { 'state' => 'enable' }}
	) if ( $psgconf->data_obj('ntp_enable')->equals('true') );

	$rc_vars->{'ntpd_flags'} = 
		'-p ' . $psgconf->data_obj('pidfile_dir')->get() . '/' . $rc_name . '.pid'
		. ' -f ' . $psgconf->data_obj('ntp_driftfile')->get()
			if ($psgconf->data_obj('platform')->match('freebsd'));
}

###############################################################################
###  constructor
###############################################################################

sub new
{
	my ($class, $psgconf) = @_;
	my ($self);

	$self = {};
	bless($self, $class);

	### So that _add_pkgs knows which directives to look at
	$self->{name} = 'ntp';
	$self->{enable} = $self->{name} . '_enable';
	$self->{packages} = $self->{name} . '_packages';

	$psgconf->register_data(
		ntp_enable		=> PSGConf::Data::Boolean->new(
							value => 'false'
						),
		ntp_driftfile		=> PSGConf::Data::String->new(
							'value_abspath' => 1
						),
		ntp_user			=> PSGConf::Data::String->new(
							value => 'root'
						),
		ntp_group			=> PSGConf::Data::String->new(
							value => 'wheel'
						),
		ntp_daemon_name	=> PSGConf::Data::String->new(
							value => 'ntpd'
						),
		ntp_minpoll		=> PSGConf::Data::Integer->new(
							value => 4
						),
		ntp_maxpoll		=> PSGConf::Data::Integer->new(
							value => 10
						),
		ntp_servers		=> PSGConf::Data::List->new(),
		ntp_packages		=> PSGConf::Data::List->new()
	);

	$psgconf->register_policy($self,
		ntp_add_packages		=> '_add_pkgs',
		ntp_enable_rc_scripts => '_policy_enable_rc_scripts',
	);

	return $self;
}


###############################################################################
###  documentation
###############################################################################

1;

__END__

=head1 NAME

PSGConf::Control::NTP - psgconf control class for NTP configuration

=head1 SYNOPSIS

In F<psgconf_modules>:

  Control PSGConf::Control::NTP

=head1 DESCRIPTION

The B<PSGConf::Control::NTP> module provides a B<psgconf> control object
for configuring NTP.  It supports the following methods:

=over 4

=item new()

The constructor.  Its parameter is a reference to the B<PSGConf>
object.  It registers the following data objects:

=over 4

=item I<ntp_enable>

A B<PSGConf::Data::Boolean> object enabling the NTP module.

=item I<ntp_daemon_name>

A B<PSGConf::Data::String> object to define what the process name is.

=item I<ntp_driftfile>

A B<PSGConf::Data::String> object for the location of the 'ntp.drift'
file is.  Defaults to C<etc_inet_dir/ntp.drift>.

=item I<ntp_user>

A B<PSGConf::Data::String> object for the account C<ntpd> is going
to run under.  Defaults to C<root>, but not implemented.

=item I<ntp_group>

A B<PSGConf::Data::String> object for the group C<ntpd> is going
to run under.  Defaults to C<wheel>, but not implemented.

=item I<ntp_servers>

A B<PSGConf::Data::List> object containing the hostname(s) of the NTP
server(s) to sync against.

=item I<ntp_minpoll>

A B<PSGConf::Data::Integer> object for the minimum poll value for all
the I<ntp_servers>.  Defaults to 4.

=item I<ntp_maxpoll>

A B<PSGConf::Data::Integer> object for the maximum poll value for all
the I<ntp_servers>.  Defaults to 10.

=item I<ntp_packages>

A B<PSGConf::Data::List> object containing the packages to install.

=back

The constructor also registers the following policy method:

=over 4

=item I<ntp_enable_rc_scripts>

Modifies the I<rc_scripts> data object (provided by
B<PSGConf::Control::InitScripts>) to enable the NTP daemon.

=back

=item decide()

If I<ntp_servers> is set, registers a
B<PSGConf::Action::CreateFile> object to create
the F<ntp.drift> file. Also registers a
B<PSGConf::Action::GenerateFile::ntp_conf> object to create
the F<ntp.conf> file.  The file will be placed in the directory
specified by the I<etc_inet_dir> data object, which is provided by the
B<PSGConf::Control::Core> module.  And finally bounces the
C<NTP> daemon itself if the F<ntp.conf> file was updated.

=back

=head1 SEE ALSO

L<perl>

ntpd(8)

xntpd(8)

L<PSGConf>

L<PSGConf::Action::GenerateFile::ntp_conf>

L<PSGConf::Action::RestartDaemon>

L<PSGConf::Control::Core>

L<PSGConf::Control::InitScripts>

L<PSGConf::Control::Packages>

L<PSGConf::Data::Boolean>

L<PSGConf::Data::String>

L<PSGConf::Data::Integer>

L<PSGConf::Data::List>

L<psgconf-intro>

=cut



syntax highlighted by Code2HTML, v. 0.9.1