###
### Copyright 2000-2007 University of Illinois Board of Trustees
### All rights reserved.
###
### PSGConf::Control::logadm - psgconf control class for controlling log rotation/pruning for Solaris
###
### Campus Information Technologies and Educational Services
### University of Illinois at Urbana-Champaign
###
package PSGConf::Control::logadm;
use PSGConf::Action::GenerateFile::Literal;
use PSGConf::Data::Boolean;
use PSGConf::Data::Hash;
use PSGConf::Data::Integer;
use PSGConf::Data::List;
use PSGConf::Data::String;
###############################################################################
### policies
###############################################################################
sub _policy_merge_timestamps
{
my ($self, $psgconf) = @_;
my ($line, $line2, $obj, $log, @data);
local *FP;
return
if ($psgconf->data_obj('logadm_enable')->equals('false'));
if (!open (FP, $psgconf->data_obj('logadm_conf_file')->get())) {
warn "\n\t!!! can't open existing logadm conf file (%s)\n",
$psgconf->data_obj('logadm_conf_file')->get()
if ( $psgconf->{verbose} );
return;
}
@data = <FP>;
close FP;
foreach $line ( @data ) {
### Skip this line if we do not have any timestamp info...
next if ( $line !~ / -P / );
chomp $line;
### Find the log file we are working with
$log = $line;
$log =~ s/ .*$//;
### Now get the time stamp itself (w/o the single quotes).
$line =~ s/^.* -P '//;
$line =~ s/' .*$//;
### Validate that we have a good timestamp.
next if ( $line != m/
^
(\S\S\S) # Day of the week
\s+
(\S\S\S) # Month
\s+
(\d?\d) # Day
\s+
(\d\d:\d\d:\d\d) # Time (HH:MM:SS)
\s+
(\d\d\d\d) # Year
$
/);
### Now put the timestamp back into our directives.
### See if we already have a line in logadm_files
$line2 = $psgconf->data_obj('logadm_files')->find("^$log");
if ( defined $line2 ) {
### If we already have a timestamp in the config, just go on.
next if ( $line2 =~ / -P / );
### Search through the arguments to find out where
### to put this timestamp.
my (@a) = split(/\s/, $line2);
for (my $i=1; $i < scalar @a; $i++) {
if ( $a[$i] =~ /^-[ACE]$/ ) {
$i++;
### Loop through the -M 'some cmd' arguments
} elsif ( $a[$i] eq '-M' ) {
do { $i++ } while ( $a[$i] !~ /\'$/ );
} elsif ( $a[$i] ne '-N' ) {
$obj = $line2;
$obj =~ s/ $a[$i]/ -P '$line' $a[$i]/;
$psgconf->data_obj('logadm_files')->replace(
"^$line2",
$obj
);
### Now exit out of this inner for loop...
$i = scalar @a;
}
}
### Since we do not have an entry in logadm_files,
### store the value for use later.
} else {
$psgconf->data_obj('logadm_timestamps')->insert(
{ $log => $line }
);
}
}
}
sub _add_files
{
my ($psgconf, $cmd, @files) = @_;
my ($file, $fullcmd);
foreach $file ( @files ) {
### The logadm command will rewrite the logadm_conf_file
### with the arguments sorted in alphabetical order, so make
### sure we do that the first time.
$fullcmd = ' -C ' . $psgconf->data_obj('logadm_file_cnt')->get();
$fullcmd .= ' -N '
if ( ! -f $file );
$fullcmd .= " -P '" .
$psgconf->data_obj('logadm_timestamps')->find($file) . "'"
if ( $psgconf->data_obj('logadm_timestamps')->exists($file) );
$fullcmd .= " -a '" . $cmd . "'"
if ( defined $cmd );
$fullcmd .= ' -p 1d -z 0';
$psgconf->data_obj('logadm_files')->add ( $file . $fullcmd );
}
}
sub _policy_add_syslog_files
{
my ($self, $psgconf) = @_;
my (@logs);
return
if ($psgconf->data_obj('syslog_enable')->equals('false')
|| $psgconf->data_obj('logadm_enable')->equals('false'));
map {
push @logs, $_ if ( -f $_ );
} keys %{$psgconf->data_obj('syslog')->get()};
&_add_files ($psgconf,
"kill -HUP `cat " . $psgconf->data_obj('pidfile_dir')->get() . "/syslog.pid`",
@logs );
}
sub _policy_add_ftp_files
{
my ($self, $psgconf) = @_;
return
if ($psgconf->data_obj('anon_ftp_enable')->equals('false')
|| $psgconf->data_obj('logadm_enable')->equals('false'));
&_add_files ($psgconf, undef, ( $psgconf->data_obj('log_dir')->get() . '/xferlog' ));
}
sub _policy_add_www_files
{
my ($self, $psgconf) = @_;
my (@logs);
return
if ($psgconf->data_obj('www_enable')->equals('false')
|| $psgconf->data_obj('logadm_enable')->equals('false'));
@logs = (
$psgconf->data_obj('www_log_dir')->get() . '/suexec',
$psgconf->data_obj('www_log_dir')->get() . '/error_log',
$psgconf->data_obj('www_log_dir')->get() . '/access_log'
);
map { push @logs, $_; } values %{$psgconf->data_obj('www_vh_access_log')->get()};
push @logs, $psgconf->data_obj('www_log_dir')->get() . '/ssl_engine_log'
if ( $psgconf->data_obj('www_vh_ssl')->count() );
push @logs, $psgconf->data_obj('www_jk_logfile')->get()
if ( $psgconf->data_obj('www_jk_enable')->equals('true') );
###
### FIXME: Need to add the bluestem and any other logs not in
### the stock psgconf modules. This really screams to be put
### into a method that other Control modules can call from w/i
### one of their policies.
###
&_add_files ( $psgconf,
$psgconf->data_obj('www_apachectl_path')->get() . " graceful > /dev/null 2>&1",
@logs);
}
###############################################################################
###
### new() constructor
###
###############################################################################
sub new {
my ($class, $psgconf) = @_;
my ($self);
$self = {};
bless($self, $class);
$self->{name} = 'logadm';
$self->{enable} = $self->{name} . '_enable';
$self->{packages} = $self->{name} . '_packages';
$psgconf->register_data(
'logadm_enable' => PSGConf::Data::Boolean->new(
'value' => 'false'
),
'logadm_conf_file' => PSGConf::Data::String->new(
'value_abspath' => 1,
'value' => '/etc/logadm.conf'
),
'logadm_file_cnt' => PSGConf::Data::Integer->new(
'value' => 14
),
'logadm_timestamps' => PSGConf::Data::Hash->new(),
'logadm_files' => PSGConf::Data::List->new(
'unique' => 1
)
);
###
### Rotate the syslog/ftp/apache logs. Do not need to do the
### TSM logs as dsmc does it for us (by setting the retention
### in the config files).
###
$psgconf->register_policy($self,
logadm_merge_timestamps => '_policy_merge_timestamps',
logadm_add_syslog_files => '_policy_add_syslog_files',
logadm_add_ftp_files => '_policy_add_ftp_files',
logadm_add_www_files => '_policy_add_www_files'
);
return $self;
}
###############################################################################
###
### decide() method
###
### generate logadm_conf_file based on files specified in psg.conf
###
###############################################################################
sub decide {
my ($self, $psgconf) = @_;
my ($conffile);
return
if ($psgconf->data_obj('logadm_enable')->equals('false'));
### create logadm_conf_file
$psgconf->register_actions(
PSGConf::Action::GenerateFile::Literal->new(
name => $psgconf->data_obj('logadm_conf_file')->get(),
content => join("\n", @{$psgconf->data_obj('logadm_files')->get()}) . "\n",
backup => 0
)
)
}
1;
__END__
=head1 NAME
PSGConf::Control::logadm - psgconf control class for controlling log rotation/pruning for Solaris
=head1 SYNOPSIS
In F<psgconf_modules>:
Control PSGConf::Control::logadm
=head1 DESCRIPTION
The B<PSGConf::Control::logadm> module provides a B<psgconf> control object
for rotating system logs using the logadm facility.
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<logadm_enable>
A B<PSGConf::Data::Boolean> object to enable/disable this feature
=item I<logadm_conf_file>
A B<PSGConf::Data::String> object defining the location of the C<logadm>
config file. Defaults to F</etc/logadm.conf>.
=item I<logadm_file_cnt>
A B<PSGConf::Data::Integer> object for the number of files we need to
keep. The default is 14.
=item I<logadm_files>
A B<PSGConf::Data::List> object of the commands to use to configure
C<logadm>.
=back
The constructor also registers the following policy methods:
=over 4
=item I<logadm_add_syslog_files>
Requests that the C<syslog> files be rotated.
=item I<logadm_add_ftp_files>
Requests that the C<anon_ftp> log files be rotated.
=item I<logadm_add_www_files>
Requests that the C<apache> log files be rotated.
=back
=item decide()
Registers a B<PSGConf::Action::GenerateFile::Literal> Action object to
generate the F</etc/logadm.conf> file.
=back
=head1 SEE ALSO
C<CE<lt>logadm(8)E<gt>>
L<perl>
L<PSGConf>
L<PSGConf::Action::GenerateFile::Literal>
L<PSGConf::Data::Boolean>
L<PSGConf::Data::Hash>
L<PSGConf::Data::Integer>
L<PSGConf::Data::List>
L<PSGConf::Data::String>
L<psgconf-intro>
=cut
syntax highlighted by Code2HTML, v. 0.9.1