Annotation of loncom/build/loncaparestoreconfigurations, revision 1.14
1.1 harris41 1: #!/usr/bin/perl
2:
1.13 harris41 3: # loncaparestoreconfigurations - restore data to new LON-CAPA conf files
4: #
1.14 ! harris41 5: # $Id: loncaparestoreconfigurations,v 1.13 2002/05/16 00:20:30 harris41 Exp $
1.13 harris41 6: #
7: # YEAR=2000
8: # 10/25, 12/14 Scott Harrison
9: # YEAR=2002
10: # Scott Harrison, 05/15
11: #
12: ###
1.1 harris41 13:
1.13 harris41 14: # This tool helps in updating a system. It restores information for
15: # configuration files (.lpmlsave or other backup notations).
1.8 harris41 16:
1.13 harris41 17: # By default, the .lpmlsave suffix is used.
1.8 harris41 18: # Alternatively, there can be two other invocations
19: # Invocation #1:
20: # ARGV[0]=suffix
21: # ARGV[1]=.bak
22: # Invocation #2:
23: # ARGV[0]=lasttimestamp
24:
25: # The criteria for the lasttimestamp is that the
26: # file suffix is a '.' followed by a 14-digit
27: # time-stamp (YYYYMMDDhhmmss).
28: # The time-stamp with the greatest value is
29: # taken as the backup file.
30:
1.13 harris41 31: # --------------------------------------------- Define program version variable
1.14 ! harris41 32: $VERSION = sprintf("%d.%02d", q$Revision: 1.13 $ =~ /(\d+)\.(\d+)/);
1.13 harris41 33:
34: # ---------------------------------------------- Process command-line arguments
35: my $suffix='.lpmlsave';
36: my $suffixpragma='';
1.8 harris41 37: if ($ARGV[0] eq 'suffix') {
1.11 harris41 38: $suffix=$ARGV[1] if $ARGV[1]=~/^[\.\w]+$/;
1.8 harris41 39: }
40: elsif ($ARGV[0] eq 'lasttimestamp') {
1.13 harris41 41: $suffixpragma='lasttimestamp';
1.8 harris41 42: }
1.1 harris41 43:
1.13 harris41 44: use strict; # restrict unsafe and poorly coded constructs
1.1 harris41 45:
1.13 harris41 46: # ------------------------------------ Configuration files to be concerned with
1.1 harris41 47: my @special_conf_files=(
1.13 harris41 48: '/etc/httpd/conf/loncapa.conf',
49: '/etc/httpd/conf/access.conf',
1.1 harris41 50: );
51:
1.13 harris41 52: my %pvar; # store the PerlSetVar variable key/value combinations
53:
54: # --------------------------------------------- Process the configuration files
55: # NOTE that I have structured this processing to make NO assumptions
56: # about the processing of each configuration file. So, in terms
57: # of keeping each file's processing algorithms self-contained, I am not
58: # modularizing things (where it is obvious that they might be modularized.)
59: CONFLOOP: foreach (@special_conf_files) {
60:
61: my $lpmlold; # holds information that needs to be read
62: my $lpmlnew; # holds information that needs to be modified
63:
64: my $lpmlnew_file; # file location of information that needs to be modified
65:
66: # ------------------------------------------- access.conf (becoming deprecated)
67: if (/^\/etc\/httpd\/conf\/access.conf$/ and
68: -e '/etc/httpd/conf/access.conf') {
69: if ($suffixpragma eq 'lasttimestamp' and
70: -e '/etc/httpd/conf/access.conf'.$suffix) {
71: $suffix=&getsuffix('/etc/httpd/conf/access.conf');
72: unless (-e '/etc/httpd/conf/access.conf'.$suffix) {
73: next CONFLOOP;
74: }
75: $lpmlold="\n".&readfile('/etc/httpd/conf/access.conf'.$suffix);
76: $lpmlnew_file='/etc/httpd/conf/access.conf';
77: $lpmlnew=&readfile($lpmlnew_file);
78: }
79: else {
80: $lpmlold="\n".&readfile('/etc/httpd/conf/access.conf');
81: $lpmlnew_file='/etc/httpd/conf/access.conf'.$suffix;
82: unless (-e $lpmlnew_file) {
83: next CONFLOOP;
84: }
85: $lpmlnew=&readfile($lpmlnew_file);
86: }
87: while($lpmlold=~/\n\s*PerlSetVar\s+(\S+)\s+(\S+)/mcg) {
88: my $pkey=$1; my $pval=$2;
89: $lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/;
90: $pvar{$pkey}=$pval;
91: }
92: }
1.1 harris41 93:
1.13 harris41 94: # ---------------------------------------------------------------- loncapa.conf
95: elsif (/^\/etc\/httpd\/conf\/loncapa.conf$/ and
96: -e '/etc/httpd/conf/loncapa.conf') {
97: if ($suffixpragma eq 'lasttimestamp' and
98: -e '/etc/httpd/conf/loncapa.conf') {
99: $suffix=&getsuffix('/etc/httpd/conf/loncapa.conf');
100: unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) {
101: next CONFLOOP;
102: }
103: $lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf'.$suffix);
104: $lpmlnew_file='/etc/httpd/conf/loncapa.conf';
105: $lpmlnew=&readfile($lpmlnew_file);
1.8 harris41 106: }
1.13 harris41 107: else {
108: $lpmlold="\n".&readfile('/etc/httpd/conf/loncapa.conf');
109: $lpmlnew_file='/etc/httpd/conf/loncapa.conf'.$suffix;
110: unless (-e $lpmlnew_file) {
111: next CONFLOOP;
1.12 harris41 112: }
1.13 harris41 113: $lpmlnew=&readfile($lpmlnew_file);
114: }
115: while($lpmlold=~/\n\s*PerlSetVar\s+(\S+)\s+(\S+)/mcg) {
116: my $pkey=$1; my $pval=$2;
117: $pvar{$pkey}=$pval;
118: }
119: foreach my $pkey (keys %pvar) {
120: my $pval=$pvar{$pkey};
121: $lpmlnew=~s/(\n\s*PerlSetVar\s+$pkey\s+)\S+/$1$pval/;
1.2 harris41 122: }
1.13 harris41 123: open(OUT,'>'.$lpmlnew_file) or
124: die('Cannot open '.$lpmlnew_file.' for output'."\n");
125: print(OUT $lpmlnew);
126: close(OUT);
1.5 harris41 127: }
1.13 harris41 128:
129: # -------------------------------------------------------------------- smb.conf
130: elsif (/^\/etc\/smb.conf$/ and -e "/etc/smb.conf$suffix") {
1.8 harris41 131: if ($suffixpragma eq 'lasttimestamp') {
1.13 harris41 132: $suffix=&getsuffix('/etc/smb.conf');
133: unless (-e '/etc/httpd/conf/loncapa.conf'.$suffix) {
134: next CONFLOOP;
135: }
136: $lpmlnew=&readfile('/etc/smb.conf');
137: $lpmlnew_file='/etc/smb.conf';
1.8 harris41 138: }
1.13 harris41 139: else {
140: $lpmlnew=&readfile('/etc/smb.conf'.$suffix);
141: $lpmlnew_file='/etc/smb.conf'.$suffix;
142: }
143: $lpmlnew=~s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge;
144: open(OUT,'>'.$lpmlnew_file) or
145: die('Cannot open '.$lpmlnew_file.' for output'."\n");
146: print(OUT $lpmlnew);
147: close(OUT);
1.12 harris41 148: }
1.13 harris41 149: elsif (/^\/etc\/samba\/smb.conf$/ and -e "/etc/samba/smb.conf$suffix") {
1.12 harris41 150: if ($suffixpragma eq 'lasttimestamp') {
1.13 harris41 151: $suffix=&getsuffix('/etc/samba/smb.conf');
152: unless (-e '/etc/samba/smb.conf'.$suffix) {
153: next CONFLOOP;
154: }
155: $lpmlnew=&readfile('/etc/samba/smb.conf');
156: $lpmlnew_file='/etc/samba/smb.conf';
1.12 harris41 157: }
1.13 harris41 158: else {
159: $lpmlnew=&readfile('/etc/samba/smb.conf'.$suffix);
160: $lpmlnew_file='/etc/samba/smb.conf'.$suffix;
161: }
162: $lpmlnew=~s/\{\{\{\{\[(.*?)\]\}\}\}\}/$pvar{$1}/ge;
163: open(OUT,'>'.$lpmlnew_file) or
164: die('Cannot open '.$lpmlnew_file.' for output'."\n");
165: print(OUT $lpmlnew);
166: close(OUT);
1.3 harris41 167: }
1.8 harris41 168: }
169:
1.13 harris41 170: # --------------------------------- getsuffix: get the latest time stamp suffix
171: # === INPUT: filename without suffix
172: # === OUTPUT: the latest time stamp suffix; 14 digits YYYYMMDDhhmmss
173: # === ERROR: cannot read the directory in which the filenames reside
1.8 harris41 174: sub getsuffix {
175: my ($file)=@_;
1.13 harris41 176: print("$file\n");
1.8 harris41 177: my $dir=$file; $dir=~s/([^\/]+)$//;
178: my $filename=$1;
1.13 harris41 179: opendir(DIR,$dir) or
180: die('Cannot open directory '.$dir.' for viewing'."\n");
181: my @a=grep {/$filename\.\d{14}/} readdir(DIR);
182: closedir(DIR);
1.8 harris41 183: map {s/$filename\.//;} @a;
184: my @b=sort {$a<=>$b} @a;
185: my $suffix='.'.$b[$#b];
1.13 harris41 186: return($suffix);
187: }
188:
189: # -------------------------- readfile: get the file contents in a scalar string
190: # === INPUT: filename
191: # === OUTPUT: the filename's contents
192: # === ERROR: cannot read the file
193: # === NOTE: big files will hog computer memory
194: sub readfile {
195: my ($filename)=@_;
196: my $contents='';
197: open(IN,'<'.$filename) or die ('Cannot read '.$filename."\n");
198: while(<IN>) {$contents.=$_;}
199: close(IN);
200: return($contents);
1.1 harris41 201: }
1.13 harris41 202:
203: =pod
204:
205: =head1 NAME
206:
207: B<loncaparestoreconfigurations> - restore data to new LON-CAPA conf files
208:
209: =head1 SYNOPSIS
210:
211: perl loncaparestoreconfigurations suffix .lpmlnew
212:
213: =head1 DESCRIPTION
214:
215: During software upgrades, it is possible that configuration files will change.
216: It is important to "intelligently" preserve the machine-specific configuration
217: data. This script is meant to run B<after> the software upgrade.
218:
219: For example, consider the configuration file F<loncapa.conf>.
220: During the software upgrade (not performed by by F<loncapa.conf>),
221: the following happens:
222:
223: loncapa.conf is NOT overwritten
224:
225: rather,
226:
227: a NEW file B<loncapa.conf.lpmlnew> is GENERATED
228: (cp UPGRADEDIR/loncapa.conf SYSTEMDIR/loncapa.conf.lpmlnew)
229:
230: This script can be described as:
231:
232: =over 4
233:
234: =item *
235:
236: modifying SYSTEMDIR/loncapa.conf.lpmlnew, and
237:
238: =item *
239:
240: the modification consists of reading values from the old loncapa.conf and
241: placing them in loncapa.conf.lpmlnew.
242:
243: =back
244:
245: Regarding F<loncapa.conf>, for backwards compatibility, this script tries
246: to read values out of F<access.conf>.
247:
248: This script also currently works with F<smb.conf> (a standard Linux
249: configuration file associated with sharing the Linux filesystem with
250: Windows machines).
251:
252: =head2 Working with the file suffix
253:
254: The script is designed to work according to two strategies.
255:
256: =over 4
257:
258: =item * B<aggressive update>
259:
260: In the aggressive update strategy, two things should happen:
261:
262: =over 4
263:
264: =item * The configuration file should be replaced
265:
266: Therefore, the system administrator "trusts" the software update process
267: and this script to handle everything correctly.
268:
269: =item * Information should never be lost
270:
271: Therefore, a backup copy should be made that is unique to the time
272: the action is taken and is never overwritten or destroyed by the
273: automated process.
274:
275: =back
276:
277: =item * B<passive assistance>
278:
279: =over 4
280:
281: =item * The configuration file should not be replaced
282:
283: The system administrator does not trust the software update process.
284: She would rather have a new file "intelligently" generated, and, only
285: by her direct approval, have the new file substitute the contents
286: of the current configuration file.
287:
288: =item * The script should try to help the system administrator
289:
290: Therefore, a new copy is made with the suffix ".lpmlnew". This
291: new copy is modified with data from the existing configuration file.
292: The system administrator is prompted (by the rest of the software
293: upgrade process) to resolve the new changes to the configuration
294: file.
295:
296: =back
297:
298: =back
299:
300: Correspondingly,
301:
302: perl loncaparestoreconfigurations suffix .lpmlnew
303:
304: invokes this script in B<passive assistance> mode; whereas
305:
306: perl loncaparestoreconfigurations lasttimestamp
307:
308: invokes this script in B<aggressive update> mode.
309:
310: =head1 AUTHORS
311:
312: Scott Harrison
313:
314: This module is free software; you can redistribute it
315: and/or modify it under the same terms as LON-CAPA itself.
316:
317: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>