version 1.3, 2000/10/26 00:28:43
|
version 1.14, 2002/07/27 22:39:56
|
Line 1
|
Line 1
|
#!/usr/bin/perl |
#!/usr/bin/perl |
|
|
# loncaparestoreconfigurations |
# loncaparestoreconfigurations - restore data to new LON-CAPA conf files |
|
# |
|
# $Id$ |
|
# |
|
# YEAR=2000 |
|
# 10/25, 12/14 Scott Harrison |
|
# YEAR=2002 |
|
# Scott Harrison, 05/15 |
|
# |
|
### |
|
|
# This tool helps in updating a system. It takes a list of |
# This tool helps in updating a system. It restores information for |
# .rpmsave files and restores them. |
# configuration files (.lpmlsave or other backup notations). |
|
|
# Scott Harrison, 10/25/2000 |
# By default, the .lpmlsave suffix is used. |
|
# Alternatively, there can be two other invocations |
|
# Invocation #1: |
|
# ARGV[0]=suffix |
|
# ARGV[1]=.bak |
|
# Invocation #2: |
|
# ARGV[0]=lasttimestamp |
|
|
use strict; |
# The criteria for the lasttimestamp is that the |
|
# file suffix is a '.' followed by a 14-digit |
|
# time-stamp (YYYYMMDDhhmmss). |
|
# The time-stamp with the greatest value is |
|
# taken as the backup file. |
|
|
|
# --------------------------------------------- Define program version variable |
|
$VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/); |
|
|
|
# ---------------------------------------------- Process command-line arguments |
|
my $suffix='.lpmlsave'; |
|
my $suffixpragma=''; |
|
if ($ARGV[0] eq 'suffix') { |
|
$suffix=$ARGV[1] if $ARGV[1]=~/^[\.\w]+$/; |
|
} |
|
elsif ($ARGV[0] eq 'lasttimestamp') { |
|
$suffixpragma='lasttimestamp'; |
|
} |
|
|
|
use strict; # restrict unsafe and poorly coded constructs |
|
|
|
# ------------------------------------ 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/httpd/conf/access.conf', |
); |
); |
|
|
my @generic_conf_files=( |
my %pvar; # store the PerlSetVar variable key/value combinations |
"/home/httpd/lonTabs/hosts.tab", |
|
"/home/httpd/lonTabs/spare.tab", |
# --------------------------------------------- Process the configuration files |
"/etc/krb.conf", |
# NOTE that I have structured this processing to make NO assumptions |
"/etc/ntp.conf" |
# about the processing of each configuration file. So, in terms |
); |
# of keeping each file's processing algorithms self-contained, I am not |
|
# modularizing things (where it is obvious that they might be modularized.) |
|
CONFLOOP: foreach (@special_conf_files) { |
|
|
|
my $lpmlold; # holds information that needs to be read |
|
my $lpmlnew; # holds information that needs to be modified |
|
|
foreach (@special_conf_files) { |
my $lpmlnew_file; # file location of information that needs to be modified |
if (/^\/etc\/httpd\/conf\/access.conf$/) { |
|
my $template=`/bin/cat /etc/httpd/conf/access.conf`; |
# ------------------------------------------- access.conf (becoming deprecated) |
my $rpmsave=`/bin/cat /etc/httpd/conf/access.conf.rpmsave`; |
if (/^\/etc\/httpd\/conf\/access.conf$/ and |
`/bin/mv /etc/httpd/conf/access.conf /etc/httpd/conf/access.conf.template`; |
-e '/etc/httpd/conf/access.conf') { |
my @perlsetvars=("lonHostID","lonRole","lonAdmEMail","lonDefDomain","lonLoadLim","lonExpire"); |
if ($suffixpragma eq 'lasttimestamp' and |
foreach my $psv (@perlsetvars) { |
-e '/etc/httpd/conf/access.conf'.$suffix) { |
$rpmsave=~/\nPerlSetVar\s+$psv\s+(\S+)/; |
$suffix=&getsuffix('/etc/httpd/conf/access.conf'); |
my $pval=$1; |
unless (-e '/etc/httpd/conf/access.conf'.$suffix) { |
$template=~s/(\nPerlSetVar\s+$psv\s+)\S+/$1$pval/; |
next CONFLOOP; |
} |
} |
open OUT,">/etc/httpd/conf/access.conf"; |
$lpmlold="\n".&readfile('/etc/httpd/conf/access.conf'.$suffix); |
print OUT $template; |
$lpmlnew_file='/etc/httpd/conf/access.conf'; |
close OUT; |
$lpmlnew=&readfile($lpmlnew_file); |
|
} |
|
else { |
|
$lpmlold="\n".&readfile('/etc/httpd/conf/access.conf'); |
|
$lpmlnew_file='/etc/httpd/conf/access.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; |
|
$lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/; |
|
$pvar{$pkey}=$pval; |
|
} |
|
} |
|
|
|
# ---------------------------------------------------------------- loncapa.conf |
|
elsif (/^\/etc\/httpd\/conf\/loncapa.conf$/ and |
|
-e '/etc/httpd/conf/loncapa.conf') { |
|
if ($suffixpragma eq 'lasttimestamp' and |
|
-e '/etc/httpd/conf/loncapa.conf') { |
|
$suffix=&getsuffix('/etc/httpd/conf/loncapa.conf'); |
|
unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) { |
|
next CONFLOOP; |
|
} |
|
$lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf'.$suffix); |
|
$lpmlnew_file='/etc/httpd/conf/loncapa.conf'; |
|
$lpmlnew=&readfile($lpmlnew_file); |
|
} |
|
else { |
|
$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); |
} |
} |
} |
|
|
|
foreach (@generic_conf_files) { |
# -------------------------------------------------------------------- smb.conf |
if (-e "$_.rpmsave") { |
elsif (/^\/etc\/smb.conf$/ and -e "/etc/smb.conf$suffix") { |
`/bin/mv $_ $_.template`; |
if ($suffixpragma eq 'lasttimestamp') { |
`/bin/mv $_.rpmsave $_`; |
$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); |
|
} |
|
|
|
# -------------------------- readfile: get the file contents in a scalar string |
|
# === INPUT: filename |
|
# === OUTPUT: the filename's contents |
|
# === ERROR: cannot read the file |
|
# === NOTE: big files will hog computer memory |
|
sub readfile { |
|
my ($filename)=@_; |
|
my $contents=''; |
|
open(IN,'<'.$filename) or die ('Cannot read '.$filename."\n"); |
|
while(<IN>) {$contents.=$_;} |
|
close(IN); |
|
return($contents); |
|
} |
|
|
|
=pod |
|
|
|
=head1 NAME |
|
|
|
B<loncaparestoreconfigurations> - restore data to new LON-CAPA conf files |
|
|
|
=head1 SYNOPSIS |
|
|
|
perl loncaparestoreconfigurations suffix .lpmlnew |
|
|
|
=head1 DESCRIPTION |
|
|
|
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 |
|
|
|
Scott Harrison |
|
|
|
This module is free software; you can redistribute it |
|
and/or modify it under the same terms as LON-CAPA itself. |
|
|
|
=cut |