File:  [LON-CAPA] / loncom / build / loncaparestoreconfigurations
Revision 1.13: download - view: text, annotated - select for diffs
Thu May 16 00:20:30 2002 UTC (22 years, 1 month ago) by harris41
Branches: MAIN
CVS tags: version_0_4, stable_2002_july, STABLE, HEAD
BUG 436; cleaning up code; TESTED; supports loncapa.conf; supports
access.conf backwards; documented; mega-fixed; FIXED

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>