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


package PSGConf::Control::NFS_Server;

use strict;

use PSGConf::Action::GenerateFile::dfstab;
use PSGConf::Action::GenerateFile::etc_exports;
use PSGConf::Action::GenerateFile::BSD_exports;
use PSGConf::Action::RunCommand;
use PSGConf::Data::Boolean;
use PSGConf::Data::Hash;
use PSGConf::Data::List;
use PSGConf::Control::Packages qw(_add_pkgs);


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

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

	return
		if ($psgconf->data_obj('nfs_server_enable')->equals('false'));

	if ($psgconf->data_obj('platform')->match('solaris'))
	{
		$psgconf->register_actions(
			PSGConf::Action::GenerateFile::dfstab->new(
				name		=> '/etc/dfs/dfstab',
				description	=> 'NFS server exports file',
				exports		=> $psgconf->data_obj('nfs_exports')->get()
			)
		);
	}
	elsif ($psgconf->data_obj('platform')->match('linux'))
	{
		$psgconf->register_actions(
			PSGConf::Action::GenerateFile::BSD_exports->new(
				name		=> '/etc/exports',
				description	=> 'NFS server exports file',
				exports		=> $psgconf->data_obj('nfs_exports')->get()
			)
		);
	}
	else
	{
		$psgconf->register_actions(
			PSGConf::Action::GenerateFile::etc_exports->new(
				name		=> '/etc/exports',
				description	=> 'NFS server exports file',
				exports		=> $psgconf->data_obj('nfs_exports')->get()
			)
		);
	}

	$cmd = ($psgconf->data_obj('platform')->match('freebsd')
		? 'killall -1 mountd'
		: 'exportfs -a');
	$psgconf->register_actions(
		PSGConf::Action::RunCommand->new(
			name		=> 'NFS exports',
			command		=> $cmd,
			check_func	=> \&_check_exportfs
		)
	);
}


###############################################################################
###  plugin function for PSGConf::Action::RunCommand
###############################################################################

sub _check_exportfs
{
	my ($self, $psgconf) = @_;
	my ($action, $filename);

	return
		if ($psgconf->data_obj('nfs_server_enable')->equals('false'));

	$filename = ($psgconf->data_obj('platform')->match('solaris')
		     ? '/etc/dfs/dfstab'
		     : '/etc/exports');

	$action = $psgconf->get_action($filename);

	return 0
		if (! defined($action)
		    || ! $action->changed());

	return 1;
}


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

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

	# Note: the RPC portmapper may be needed elsewhere, so
	# we enable it here if we need it, but we don't explicitly
	# disable it if we don't need it

	if ($psgconf->data_obj('platform')->match('aix'))
	{
		if ( $psgconf->data_obj('nfs_server_enable')->equals('true') ) {
			$psgconf->data_obj('inittab')->replace_row_cells(
				{ 0 => 'rcnfs' },
				{ 2 => 'wait' } 
			);
		}
	}

	foreach $script (@{$psgconf->data_obj('nfs_server_daemons')->get()}) {
		if ( $psgconf->data_obj('nfs_server_enable')->equals('true') ) {
			$psgconf->data_obj('rc_scripts')->insert(
				{ $script => { 'state' => 'enable' }}
			);
		}
	}
}


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

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

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

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

	$psgconf->register_data(
		nfs_server_enable	=> PSGConf::Data::Boolean->new(
							value => 'false'
						),
		nfs_server_daemons	=> PSGConf::Data::List->new(),
		nfs_server_packages	=> PSGConf::Data::List->new(),
		nfs_exports		=> PSGConf::Data::Hash->new(
						value_type	=> 'HASH',
						key_abspath	=> 1
					   )
	);

	$psgconf->register_policy($self,
		nfs_server_add_packages		=> '_add_pkgs',
		nfs_server_enable_rc_scripts	=> '_policy_enable_rc_scripts',
	);

	return $self;
}


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

1;

__END__

=head1 NAME

PSGConf::Control::NFS_Server - psgconf control class for NFS servers

=head1 SYNOPSIS

In F<psgconf_modules>:

  Control PSGConf::Control::NFS_Server

=head1 DESCRIPTION

The B<PSGConf::Control::NFS_Server> module provides a B<psgconf> control
object for configuring NFS servers.  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<nfs_server_enable>

A B<PSGConf::Data::Boolean> object indicating whether the NFS server
should be configured.

=item I<nfs_server_packages>

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

=item I<nfs_server_daemons>

A B<PSGConf::Data::List> object containing the list of I<rc_scripts>
to enable for this service to work.

=item I<nfs_exports>

A B<PSGConf::Data::Hash> object containing the list of filesystems to
export.  The key is the name of the filesystem to export, and the value
is an anonymous hash containing the options for the export.  There are
a few special options:

=over 4

=item rw

This maps to an anonymous hash whose keys are the hostnames to whom the
filesystem should be exported to in read-write mode.  If no value is
specified, the filesystem will be exported read-write to all clients
(which is probably not what you want).

=item ro

This maps to an anonymous hash whose keys are the hostnames to whom the
filesystem should be exported to in read-only mode.  If no value is
specified, the filesystem will be exported read-only to all clients
(which is probably not what you want).

=item root

This maps to an anonymous hash whose keys are the hostnames to whom the
filesystem should be exported to with C<root> access.

=back

Any other options will be used verbatim.  However, the special options
listed above should be used for the functionality they provide, even if
the underlying NFS implementation uses a different syntax or option name.
For example, under AIX, the C<access> option should never be specified,
since the C<ro> option can be used instead.

=back

The constructor also registers the following policy methods:

=over 4

=item I<nfs_server_enable_rc_scripts>

Enables (depending on if I<nfs_server_enabled>
is set) the NFS server RC scripts using the I<rc_scripts>
and I<inittab> data objects (provided by
B<PSGConf::Control::InitScripts> and B<PSGConf::Control::Inittab>).

If I<nfs_server_enabled> is set, also enables the RPC portmapper RC
script using the I<rc_scripts> data object (provided by
B<PSGConf::Control::InitScripts>).

=back

=item decide()

If I<nfs_server_enable> is not set, does nothing.

Under Solaris, registers a B<PSGConf::Action::GenerateFile::dfstab>
action object to create F</etc/dfs/dfstab>.

Under Linux or any of the BSD operating systems, registers a
B<PSGConf::Action::GenerateFile::BSD_exports> action object to create
F</etc/exports>.

Under all other platforms, registers a
B<PSGConf::Action::GenerateFile::etc_exports> action object to create
F</etc/exports>.

For all platforms, registers a B<PSGConf::Action::RunCommand> action
object to run C<exportfs -a> if the exports list has changed.

=back

=head1 SEE ALSO

L<perl>

L<PSGConf>

L<PSGConf::Action::GenerateFile::dfstab>

L<PSGConf::Action::GenerateFile::etc_exports>

L<PSGConf::Action::GenerateFile::BSD_exports>

L<PSGConf::Action::RunCommand>

L<PSGConf::Control::InitScripts>

L<PSGConf::Control::Packages>

L<PSGConf::Data::Boolean>

L<PSGConf::Data::List>

L<PSGConf::Data::Hash>

L<psgconf-intro>

=cut



syntax highlighted by Code2HTML, v. 0.9.1