version 1.8, 2000/12/14 17:38:38
|
version 1.16, 2003/02/03 18:03:52
|
Line 1
|
Line 1
|
#!/usr/bin/perl |
#!/usr/bin/perl |
|
|
# loncaparestoreconfigurations |
# loncaparestoreconfigurations - restore data to new LON-CAPA conf files |
|
# |
|
# $Id$ |
|
# |
|
### |
|
|
# Scott Harrison, 10/25/2000 |
# This tool helps in updating a system. It restores information for |
# Scott Harrison, 12/14/2000 |
# configuration files (.lpmlnew or other backup notations). |
|
|
# This tool helps in updating a system. It restores backed-up |
# By default, the .lpmlsave suffix is used. |
# configuration files (.rpmsave or other backup notations). |
|
|
|
# By default, the .rpmsave suffix is used. |
|
# Alternatively, there can be two other invocations |
# Alternatively, there can be two other invocations |
# Invocation #1: |
# Invocation #1: |
# ARGV[0]=suffix |
# ARGV[0]=suffix |
Line 22
|
Line 23
|
# The time-stamp with the greatest value is |
# The time-stamp with the greatest value is |
# taken as the backup file. |
# taken as the backup file. |
|
|
my $suffix=".rpmsave"; |
# --------------------------------------------- Define program version variable |
my $suffixpragma=""; |
$VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/); |
|
|
|
# ---------------------------------------------- Process command-line arguments |
|
my $suffix='.lpmlsave'; |
|
my $suffixpragma=''; |
if ($ARGV[0] eq 'suffix') { |
if ($ARGV[0] eq 'suffix') { |
$suffix=$ARGV[1] if $suffix=~/^[\.\w]+$/; |
$suffix=$ARGV[1] if $ARGV[1]=~/^[\.\w]+$/; |
} |
} |
elsif ($ARGV[0] eq 'lasttimestamp') { |
elsif ($ARGV[0] eq 'lasttimestamp') { |
$suffixpragma="lasttimestamp"; |
$suffixpragma='lasttimestamp'; |
} |
} |
|
|
|
use strict; # restrict unsafe and poorly coded constructs |
|
|
use strict; |
# ------------------------------------ Configuration files to be concerned with |
|
|
my @special_conf_files=( |
my @special_conf_files=( |
"/etc/httpd/conf/access.conf", |
'/etc/httpd/conf/loncapa.conf', |
"/etc/smb.conf" |
|
); |
); |
|
|
my @generic_conf_files=( |
my %pvar; # store the PerlSetVar variable key/value combinations |
"/home/httpd/lonTabs/hosts.tab", |
|
"/home/httpd/lonTabs/spare.tab", |
|
"/etc/krb.conf", |
|
"/etc/ntp.conf", |
|
); |
|
|
|
my @perlsetvars=("lonHostID","lonRole","lonAdmEMail","lonDefDomain","lonLoadLim","lonExpire"); |
# --------------------------------------------- Process the configuration files |
my %pvar; |
# NOTE that I have structured this processing to make NO assumptions |
foreach (@special_conf_files) { |
# about the processing of each configuration file. So, in terms |
if (/^\/etc\/httpd\/conf\/access.conf$/) { |
# of keeping each file's processing algorithms self-contained, I am not |
if ($suffixpragma eq 'lasttimestamp') { |
# modularizing things (where it is obvious that they might be modularized.) |
$suffix=getsuffix('/etc/httpd/conf/access.conf'); |
CONFLOOP: foreach (@special_conf_files) { |
} |
|
my $template=`/bin/cat /etc/httpd/conf/access.conf`; |
my $lpmlold; # holds information that needs to be read |
my $rpmsave=`/bin/cat /etc/httpd/conf/access.conf$suffix`; |
my $lpmlnew; # holds information that needs to be modified |
`/bin/mv /etc/httpd/conf/access.conf /etc/httpd/conf/access.conf.template`; |
|
foreach my $psv (@perlsetvars) { |
my $lpmlnew_file; # file location of information that needs to be modified |
$rpmsave=~/\nPerlSetVar\s+$psv\s+(\S+)/; |
|
my $pval=$1; |
# ---------------------------------------------------------------- loncapa.conf |
$template=~s/(\nPerlSetVar\s+$psv\s+)\S+/$1$pval/; |
if (/^\/etc\/httpd\/conf\/loncapa.conf$/ and |
$pvar{$psv}=$pval; |
-e '/etc/httpd/conf/loncapa.conf') |
} |
{ |
open OUT,">/etc/httpd/conf/access.conf"; |
if ($suffixpragma eq 'lasttimestamp' and |
print OUT $template; |
-e '/etc/httpd/conf/loncapa.conf') |
close OUT; |
{ |
} |
$suffix=&getsuffix('/etc/httpd/conf/loncapa.conf'); |
if (/^\/etc\/smb.conf$/) { |
unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) |
if ($suffixpragma eq 'lasttimestamp') { |
{ |
$suffix=getsuffix('/etc/smb.conf'); |
next CONFLOOP; |
} |
} |
my $template=`/bin/cat /etc/smb.conf`; |
$lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf'.$suffix); |
foreach my $psv (@perlsetvars) { |
$lpmlnew_file='/etc/httpd/conf/loncapa.conf'; |
$template=~s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge; |
$lpmlnew=&readfile($lpmlnew_file); |
} |
} |
open OUT,">/etc/smb.conf"; |
else |
print OUT $template; |
{ |
close OUT; |
$lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf'); |
} |
$lpmlnew_file='/etc/httpd/conf/loncapa.conf'.$suffix; |
} |
unless (-e $lpmlnew_file) |
|
{ |
|
next CONFLOOP; |
|
} |
|
$lpmlnew=&readfile($lpmlnew_file); |
|
} |
|
while($lpmlold=~/\n\s*PerlSetVar\s+(\S+)\s+(\S+)/mcg) |
|
{ |
|
my $pkey=$1; my $pval=$2; |
|
$pvar{$pkey}=$pval; |
|
} |
|
foreach my $pkey (keys %pvar) |
|
{ |
|
my $pval=$pvar{$pkey}; |
|
$lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/; |
|
} |
|
open(OUT,'>'.$lpmlnew_file) or |
|
die('Cannot open '.$lpmlnew_file.' for output'."\n"); |
|
print(OUT $lpmlnew); |
|
close(OUT); |
|
} |
|
|
|
# ---------------------- smb.conf (probably will be deprecated in 2004 or 2005) |
|
elsif (/^\/etc\/smb.conf$/ and -e "/etc/smb.conf$suffix") |
|
{ |
|
if ($suffixpragma eq 'lasttimestamp') |
|
{ |
|
$suffix=&getsuffix('/etc/smb.conf'); |
|
unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) |
|
{ |
|
next CONFLOOP; |
|
} |
|
$lpmlnew = &readfile('/etc/smb.conf'); |
|
$lpmlnew_file = '/etc/smb.conf'; |
|
} |
|
else |
|
{ |
|
$lpmlnew = &readfile('/etc/smb.conf'.$suffix); |
|
$lpmlnew_file = '/etc/smb.conf'.$suffix; |
|
} |
|
$lpmlnew =~ s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge; |
|
open(OUT,'>'.$lpmlnew_file) or |
|
die('Cannot open '.$lpmlnew_file.' for output'."\n"); |
|
print(OUT $lpmlnew); |
|
close(OUT); |
|
} |
|
elsif (/^\/etc\/samba\/smb.conf$/ and -e "/etc/samba/smb.conf$suffix") |
|
{ |
|
if ($suffixpragma eq 'lasttimestamp') |
|
{ |
|
$suffix = &getsuffix('/etc/samba/smb.conf'); |
|
unless (-e '/etc/samba/smb.conf'.$suffix) |
|
{ |
|
next CONFLOOP; |
|
} |
|
$lpmlnew = &readfile('/etc/samba/smb.conf'); |
|
$lpmlnew_file = '/etc/samba/smb.conf'; |
|
} |
|
else |
|
{ |
|
$lpmlnew = &readfile('/etc/samba/smb.conf'.$suffix); |
|
$lpmlnew_file = '/etc/samba/smb.conf'.$suffix; |
|
} |
|
$lpmlnew =~ s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge; |
|
open(OUT,'>'.$lpmlnew_file) or |
|
die('Cannot open '.$lpmlnew_file.' for output'."\n"); |
|
print(OUT $lpmlnew); |
|
close(OUT); |
|
} |
|
} |
|
|
|
# --------------------------------- getsuffix: get the latest time stamp suffix |
|
# === INPUT: filename without suffix |
|
# === OUTPUT: the latest time stamp suffix; 14 digits YYYYMMDDhhmmss |
|
# === ERROR: cannot read the directory in which the filenames reside |
|
sub getsuffix ($) |
|
{ |
|
my ($file) = @_; |
|
print("$file\n"); |
|
my $dir = $file; $dir =~ s/([^\/]+)$//; |
|
my $filename = $1; |
|
opendir(DIR,$dir) or |
|
die('Cannot open directory '.$dir.' for viewing'."\n"); |
|
my @a = grep {/$filename\.\d{14}/} readdir(DIR); |
|
closedir(DIR); |
|
map {s/$filename\.//;} @a; |
|
my @b = sort {$a<=>$b} @a; |
|
my $suffix = '.'.$b[$#b]; |
|
return($suffix); |
|
} |
|
|
foreach (@generic_conf_files) { |
# -------------------------- readfile: get the file contents in a scalar string |
my $file=$_; |
# === INPUT: filename |
if ($suffixpragma eq 'lasttimestamp') { |
# === OUTPUT: the filename's contents |
$suffix=getsuffix($file); |
# === ERROR: cannot read the file |
} |
# === NOTE: big files will hog computer memory |
if (-e "$file$suffix") { |
sub readfile ($) |
`/bin/mv $file $_.template`; |
{ |
`/bin/cp $file$suffix $file`; |
my ($filename) = @_; |
} |
my $contents = ''; |
} |
open(IN,'<'.$filename) or die ('Cannot read '.$filename."\n"); |
|
while(<IN>) {$contents .= $_;} |
|
close(IN); |
|
return($contents); |
|
} |
|
|
sub getsuffix { |
=pod |
my ($file)=@_; |
|
print "$file\n"; |
=head1 NAME |
my $dir=$file; $dir=~s/([^\/]+)$//; |
|
my $filename=$1; |
B<loncaparestoreconfigurations> - restore data to new LON-CAPA conf files |
opendir(DIR,$dir); |
|
my @a=grep {/$filename\.\d{14}/} readdir DIR; |
=head1 SYNOPSIS |
closedir DIR; |
|
map {s/$filename\.//;} @a; |
perl loncaparestoreconfigurations suffix .lpmlnew |
my @b=sort {$a<=>$b} @a; |
|
my $suffix='.'.$b[$#b]; |
=head1 DESCRIPTION |
return $suffix; |
|
} |
During software upgrades, it is possible that configuration files will change. |
|
It is important to "intelligently" preserve the machine-specific configuration |
|
data. This script is meant to run B<after> the software upgrade. |
|
|
|
For example, consider the configuration file F<loncapa.conf>. |
|
During the software upgrade (not performed by by F<loncapa.conf>), |
|
the following happens: |
|
|
|
loncapa.conf is NOT overwritten |
|
|
|
rather, |
|
|
|
a NEW file B<loncapa.conf.lpmlnew> is GENERATED |
|
(cp UPGRADEDIR/loncapa.conf SYSTEMDIR/loncapa.conf.lpmlnew) |
|
|
|
This script can be described as: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
modifying SYSTEMDIR/loncapa.conf.lpmlnew, and |
|
|
|
=item * |
|
|
|
the modification consists of reading values from the old loncapa.conf and |
|
placing them in loncapa.conf.lpmlnew. |
|
|
|
=back |
|
|
|
Regarding F<loncapa.conf>, for backwards compatibility, this script tries |
|
to read values out of F<access.conf>. |
|
|
|
This script also currently works with F<smb.conf> (a standard Linux |
|
configuration file associated with sharing the Linux filesystem with |
|
Windows machines). |
|
|
|
=head2 Working with the file suffix |
|
|
|
The script is designed to work according to two strategies. |
|
|
|
=over 4 |
|
|
|
=item * B<aggressive update> |
|
|
|
In the aggressive update strategy, two things should happen: |
|
|
|
=over 4 |
|
|
|
=item * The configuration file should be replaced |
|
|
|
Therefore, the system administrator "trusts" the software update process |
|
and this script to handle everything correctly. |
|
|
|
=item * Information should never be lost |
|
|
|
Therefore, a backup copy should be made that is unique to the time |
|
the action is taken and is never overwritten or destroyed by the |
|
automated process. |
|
|
|
=back |
|
|
|
=item * B<passive assistance> |
|
|
|
=over 4 |
|
|
|
=item * The configuration file should not be replaced |
|
|
|
The system administrator does not trust the software update process. |
|
She would rather have a new file "intelligently" generated, and, only |
|
by her direct approval, have the new file substitute the contents |
|
of the current configuration file. |
|
|
|
=item * The script should try to help the system administrator |
|
|
|
Therefore, a new copy is made with the suffix ".lpmlnew". This |
|
new copy is modified with data from the existing configuration file. |
|
The system administrator is prompted (by the rest of the software |
|
upgrade process) to resolve the new changes to the configuration |
|
file. |
|
|
|
=back |
|
|
|
=back |
|
|
|
Correspondingly, |
|
|
|
perl loncaparestoreconfigurations suffix .lpmlnew |
|
|
|
invokes this script in B<passive assistance> mode; whereas |
|
|
|
perl loncaparestoreconfigurations lasttimestamp |
|
|
|
invokes this script in B<aggressive update> mode. |
|
|
|
=head1 AUTHORS |
|
|
|
|
|
This script is free software; you can redistribute it |
|
and/or modify it under the same terms as LON-CAPA itself. |
|
|
|
=cut |