File:  [LON-CAPA] / loncom / debugging_tools / modify_config_files.pl
Revision 1.12: download - view: text, annotated - select for diffs
Tue May 31 02:55:15 2011 UTC (12 years, 11 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, HEAD, BZ4492-merge, BZ4492-feature_horizontal_radioresponse, BZ4492-feature_Support_horizontal_radioresponse, BZ4492-Support_horizontal_radioresponse
- set-variable has been deprecated since MySQL 4.02.
  It is no longer supported in 5.5 (where its inclusion in /etc/my.cnf
  causes an error).

    1: #!/usr/bin/perl -w
    2: #
    3: # The LearningOnline Network
    4: #
    5: # $Id: modify_config_files.pl,v 1.12 2011/05/31 02:55:15 raeburn Exp $
    6: #
    7: # Copyright Michigan State University Board of Trustees
    8: #
    9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   10: #
   11: # LON-CAPA is free software; you can redistribute it and/or modify
   12: # it under the terms of the GNU General Public License as published by
   13: # the Free Software Foundation; either version 2 of the License, or
   14: # (at your option) any later version.
   15: #
   16: # LON-CAPA is distributed in the hope that it will be useful,
   17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19: # GNU General Public License for more details.
   20: #
   21: # You should have received a copy of the GNU General Public License
   22: # along with LON-CAPA; if not, write to the Free Software
   23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: # http://www.lon-capa.org/
   28: #
   29: ###
   30: 
   31: =pod
   32: 
   33: =head1 NAME
   34: 
   35: B<modify_config_files.pl>
   36: 
   37: =head1 SYNOPSIS
   38: 
   39: This script modifies /etc/my.cnf and one of: /etc/yum.conf 
   40: (for Fedora/CentOS/Scientific Linux/RHEL5), /etc/apt/sources.list
   41: (for Debian/Ubuntu) and /etc/sysconfig/rhn/sources (for RHEL4). 
   42: 
   43: =head1 DESCRIPTION
   44: 
   45: This script modifies /etc/my.cnf and /etc/yum.conf or /etc/apt/sources
   46: or /etc/sysconfig/rhn/sources to ensure certain parameters are set
   47: properly.  The LON-CAPA yum repositories are added to /etc/yum.conf or
   48: /etc/sysconfig/rhn/sources and the LON-CAPA apt repositories are added to 
   49: /etc/apt/sources.list.
   50: 
   51: The /etc/my.cnf file is modified to set the wait_timeout to 1 year.  Backup
   52: copies of each file are made in /etc, /etc/apt, and /etc/sysconfig/rhn, as 
   53: appropriate.
   54: 
   55: =cut
   56: 
   57: use strict;
   58: use File::Copy;
   59: use lib '/home/httpd/lib/perl/';
   60: use LONCAPA::Configuration;
   61: my $loncapa_config=LONCAPA::Configuration::read_conf('loncapa.conf');
   62: 
   63: open(DSH,"$$loncapa_config{'lonDaemons'}/distprobe |");
   64: my $dist = <DSH>;
   65: chomp($dist);
   66: close(DSH);
   67: 
   68: my $yum_status;
   69: my $loninst = 'http://install.loncapa.org';
   70: my $loninst_re = 'http://install\.loncapa\.org';
   71: if ($dist =~ /^fedora(\d+)$/) {
   72:     my $ver = $1;
   73:     my $gpgchk = '0';
   74:     my $gpg = "$loninst/versions/fedora/RPM-GPG-KEY-loncapa"; 
   75:     if ($ver > 6) {
   76:         $gpgchk = '1';
   77:     }
   78:     $yum_status =  
   79:         &update_file('/etc/yum.conf',
   80:              [{section => 'loncapa-updates-basearch',
   81:                key     => 'name=',
   82:                value   => 'Fedora Core $releasever LON-CAPA $basearch Updates',
   83:            }, {section => 'loncapa-updates-basearch',
   84:                key     => 'baseurl=',
   85:                value   => $loninst.'/fedora/linux/loncapa/$releasever/$basearch',
   86:            }, {section => 'loncapa-updates-basearch',
   87:                key     => 'gpgcheck=',
   88:                value   =>  $gpgchk,
   89:            }, {section => 'loncapa-updates-basearch',
   90:                key     => 'gpg=',
   91:                value   => $gpg,
   92:            }, {section => 'loncapa-updates-noarch',
   93:                key     => 'name=',
   94:                value   => 'Fedora Core $releasever LON-CAPA noarch Updates',
   95:            }, {section => 'loncapa-updates-noarch',
   96:                key     => 'baseurl=',
   97:                value   => $loninst.'/fedora/linux/loncapa/$releasever/noarch',
   98:            }, {section => 'loncapa-updates-noarch',
   99:                key     => 'gpgcheck=',
  100:                value   => $gpgchk,
  101:            }, {section => 'loncapa-updates-noarch',
  102:                key     => 'gpg=',
  103:                value   => $gpg,
  104:            }]);
  105: } elsif ($dist =~ /^(rhes|centos|scientific)(\d+)$/) {
  106:     my $type = $1;
  107:     my $ver = $2;
  108:     my $longver = $ver;
  109:     if ($type eq 'rhes') {
  110:         if ($ver == 4) {
  111:             $longver = '4ES';
  112:         } elsif ($ver == 5) {
  113:             $longver = '5Server';
  114:         }
  115:     }
  116:     my %info = (
  117:                  rhes => {
  118:                            title => 'RHEL',
  119:                            path => 'redhat/linux/enterprise/loncapa',
  120:                            gpg => 'versions/redhat/RPM-GPG-KEY-loncapa',
  121:                            gpgchk => 1,
  122:                          },
  123:                  centos => {
  124:                              title => 'CentOS',
  125:                              path => 'centos/loncapa',
  126:                              gpg => 'versions/centos/RPM-GPG-KEY-loncapa',
  127:                              gpgchk => 1,
  128:                            },
  129:                  scientific => {
  130:                                  title => 'Scientific Linux',
  131:                                  path => 'scientific/loncapa',
  132:                                  gpg => 'versions/scientific/RPM-GPG-KEY-loncapa',
  133:                                  gpgchk => 1,
  134:                                },
  135:                );
  136:     if (ref($info{$type}) eq 'HASH') {
  137:         if ($ver > 4) {
  138:             $yum_status =
  139:                 &update_file('/etc/yum.conf',
  140:                      [{section => 'loncapa-updates-basearch',
  141:                        key     => 'name=',
  142:                        value   => $info{$type}{title}.' $releasever LON-CAPA $basearch Updates',
  143:                       }, {section => "loncapa-updates-basearch",
  144:                           key     => 'baseurl=',
  145:                           value   => "$loninst/$info{$type}{path}/".'$releasever/$basearch',
  146:                       }, {section => 'loncapa-updates-basearch',
  147:                           key     => 'gpgcheck=',
  148:                           value   => $info{$type}{gpgchk},
  149:                       }, {section => 'loncapa-updates-basearch',
  150:                           key     => 'gpgkey=',
  151:                           value   => "$loninst/$info{$type}{gpg}",
  152:                       }, {section => 'loncapa-updates-noarch',
  153:                           key     => 'name=',
  154:                           value   => $info{$type}{title}.' $releasever LON-CAPA noarch Updates',
  155:                       }, {section => 'loncapa-updates-noarch',
  156:                           key     => 'baseurl=',
  157:                           value   => "$loninst/$info{$type}{path}/".'$releasever/noarch',
  158:                       }, {section => 'loncapa-updates-noarch',
  159:                           key     => 'gpgcheck=',
  160:                           value   => $info{$type}{gpgchk},
  161:                       }, {section => 'loncapa-updates-noarch',
  162:                           key     => 'gpgkey=',
  163:                           value   => "$loninst/$info{$type}{gpg}",
  164:                       }]);
  165:         } elsif (($type eq 'rhes') && ($ver == 4)) {
  166:             my %rhn = (
  167:                         basearch => { 
  168:                             regexp => '\s*yum\s+loncapa\-updates\-basearch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/\$ARCH',
  169:                             text => "yum loncapa-updates-basearch $loninst/$info{$type}{path}/$longver/".'$ARCH',
  170:                                     },
  171:                         noarch =>  {
  172:                             regexp => '\s*yum\s+loncapa\-updates\-noarch\s+'.$loninst_re.'/'.$info{$type}{path}.'/'.$longver.'/noarch',
  173:                             text => "yum loncapa-updates-noarch $loninst/$info{$type}{path}/$longver/noarch",
  174:                                    },
  175:                       );
  176:             $yum_status = &update_rhn_source(\%rhn); 
  177:         }
  178:     }
  179: } elsif ($dist =~ /^(debian|ubuntu)\d+$/) {
  180:     my %apt_get_source = (
  181:                            debian5 => {
  182:                                         regexp => '\s*deb\s+'.$loninst_re.'/debian/\s+lenny\s+main',
  183:                                         text   => "deb $loninst/debian/ lenny main",
  184:                                       },
  185:                            ubuntu6 => {
  186:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/\s+dapper\s+main',
  187:                                         text   => "deb $loninst/ubuntu/ dapper main",
  188:                                       },
  189:                            ubuntu8 => {
  190:                                         regexp => '\s*deb\s+'.$loninst_re.'/ubuntu/\s+hardy\s+main',
  191:                                         text   => "deb $loninst/ubuntu/ hardy main",
  192:                                       },
  193:                          );
  194:     my $apt_status;
  195:     if (defined($apt_get_source{$dist})) {
  196:         $apt_status = &update_apt_source($apt_get_source{$dist},);
  197:     }
  198: }
  199: 
  200: my $mysql_global_status =
  201:     &update_file('/etc/my.cnf',
  202:              [{section =>'mysqld',
  203:                key     =>'wait_timeout=',
  204:                value   =>'31536000', }]);
  205: 
  206: my $local_my_cnf = '/home/www/.my.cnf';
  207: if (! -e $local_my_cnf) {
  208:     # Create a file so we can do something with it...
  209:     system("touch $local_my_cnf");
  210: }
  211: my $mysql_www_status =
  212:     &update_file($local_my_cnf,
  213:              [{section =>'client',
  214:                key     =>'user=',
  215:                value   =>'www',},
  216:               {section =>'client',
  217:                key     =>'password=',
  218:                value   =>$loncapa_config->{'lonSqlAccess'}},]);
  219: 
  220: my $exitvalue = 0;
  221: 
  222: if ($mysql_global_status) { $exitvalue = 1; }
  223: 
  224: exit $exitvalue;
  225: 
  226: 
  227: sub update_file {
  228:     my ($file,$newdata) = @_;
  229:     return 1 if (! -e $file);
  230:     my $backup = $file.'.backup';
  231:     if (! copy($file,$backup)) {
  232:         warn "**** Error: Unable to make backup of $file";
  233:         return 0;
  234:     }
  235:     my ($filedata) = &parse_config_file($file);
  236:     if (! ref($filedata)) { warn "**** Error: $filedata"; return 0;}
  237:     my $modified = 0;
  238:     foreach my $data (@$newdata) {
  239:         my $section = $data->{'section'};
  240:         my $key = $data->{'key'};
  241:         my $value = $data->{'value'};
  242:         my $result = &modify_config_file($filedata,$section,$key,$value);
  243:         if ($result) { $modified = 1; }
  244:     }
  245:     if ($modified) {
  246:         my $result = &write_config_file($file,$filedata);
  247:         if (defined($result)) { warn 'Error:'.$result; return 0; }
  248:     }
  249:     return $modified;
  250: }
  251: 
  252: #################################################################
  253: #################################################################
  254: 
  255: =pod
  256: 
  257: =over 4
  258: 
  259: =item &parse_config_file()
  260: 
  261: Read a configuration file in and parse it into an internal data structure.
  262: 
  263: Input: filename
  264: 
  265: Output: array ref $filedata  OR  scalar error message
  266: 
  267: =back 
  268: 
  269: =cut
  270: 
  271: #################################################################
  272: #################################################################
  273: sub parse_config_file {
  274:     my ($file) = @_;
  275:     open(INFILE,$file) || return ('Unable to open '.$file.' for reading');
  276:     my @Input = <INFILE>;
  277:     close(INFILE);
  278:     my @Structure;
  279:     my %Sections;
  280:     while (my $line = shift(@Input)) {
  281:         chomp($line);
  282:         if ($line =~ /^\[([^\]]*)\]/) {
  283:             my $section_id = $1;
  284:             push(@Structure,'__section__'.$section_id);
  285:             while ($line = shift(@Input)) {
  286:                 chomp($line);
  287:                 if ($line =~ /^\[([^\]]*)\]/) {
  288:                     unshift(@Input,$line);
  289:                     last;
  290:                 } else {
  291:                     push(@{$Sections{$section_id}},$line);
  292:                 }
  293:             }
  294:         } else {
  295:             push(@Structure,$line);
  296:         }
  297:     }
  298:     my $filedata = [\@Structure,\%Sections];
  299:     return $filedata;
  300: }
  301: 
  302: #################################################################
  303: #################################################################
  304: 
  305: =pod
  306: 
  307: =over 4
  308: 
  309: =item
  310: 
  311: Write a configuration file out based on the internal data structure returned
  312: by &parse_config_file
  313: 
  314: Inputs: filename, $filedata (the return value of &parse_config_file
  315: 
  316: Returns: undef on success, scalar error message on failure.
  317: 
  318: =back
  319: 
  320: =cut
  321: 
  322: #################################################################
  323: #################################################################
  324: sub write_config_file {
  325:     my ($file,$filedata) = @_;
  326:     my ($structure,$sections) = @$filedata;
  327:     if (! defined($structure) || ! ref($structure)) {
  328:         return 'Bad subroutine inputs';
  329:     }
  330:     open(OUTPUT,'>'.$file) || return('Unable to open '.$file.' for writing');
  331:     for (my $i=0;$i<scalar(@$structure);$i++) {
  332:         my $line = $structure->[$i];
  333:         chomp($line);
  334:         if ($line =~ /^__section__(.*)$/) {
  335:             my $section_id = $1;
  336:             print OUTPUT ('['.$section_id.']'.$/);
  337:             foreach my $section_line (@{$sections->{$section_id}}) {
  338:                 chomp($section_line);
  339:                 print OUTPUT $section_line.$/;
  340:             }
  341:             # Deal with blank lines
  342:             if ($sections->{$section_id}->[-1] =~ /^\s*$/) {
  343:                 # No need to output a blank line at the end if there is one 
  344:                 # already
  345:             } else {
  346:                 print OUTPUT $/;
  347:             }
  348:         } else {
  349:             print OUTPUT $line.$/;
  350:         }
  351:     }
  352:     close OUTPUT;
  353:     return undef;
  354: }
  355: 
  356: #################################################################
  357: #################################################################
  358: 
  359: =pod
  360: 
  361: =over 4
  362: 
  363: =item &modify_config_file()
  364: 
  365: Modifies the internal data structure of a configuration file to include new
  366: sections and/or new configuration directives.
  367: 
  368: Inputs: $filedata (see &parse_config_file
  369: $section, the [section] the new entry is to reside in.  A value of undef will
  370: cause the "outer" section (as in yum.conf) to be updated (or have the new
  371: value prepended).
  372: $newkey: A line which matches this will be replaced with $newkey.$newvalue
  373: $newvalue: The new value to be placed with the new key.
  374: 
  375: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  376: 
  377: =back 
  378: 
  379: =cut
  380: 
  381: #################################################################
  382: #################################################################
  383: sub modify_config_file {
  384:     my ($filedata,$section,$newkey,$newvalue)=@_;
  385:     my $modified = 0;    # returned value - set to true if the file is modified
  386:     my ($structure,$sections) = @$filedata;
  387:     if (! defined($newvalue)) {
  388:         $newvalue = '';
  389:     }
  390:     my $newline = $newkey.$newvalue;
  391:     #
  392:     # Determine which array ref gets the item
  393:     my $target;
  394:     if (defined($section)) {
  395:         if (! exists($sections->{$section})) {
  396:             push(@$structure,'__section__'.$section);
  397:             $sections->{$section}=[];
  398:         }
  399:         $target = $sections->{$section};
  400:     } else {
  401:         $target = $structure;
  402:     }
  403:     #
  404:     # Put the item in or update it.
  405:     my $key_is_new = 1;
  406:     for (my $i=0;$i<scalar(@$target);$i++) {
  407:         if ($target->[$i] =~/^$newkey/) {
  408:             if ($target->[$i] ne $newline) {
  409:                 $target->[$i]=$newline;
  410:                 $modified = 1;
  411:             }
  412:             $key_is_new = 0;
  413:             last;
  414:         }
  415:     }
  416:     if ($key_is_new) {
  417:         if (! defined($section)) {
  418:             unshift(@$target,$newline);
  419:         } else {
  420:             # No need to put things after a blank line.
  421:             if (defined($target->[-1]) && $target->[-1] =~ /^\s*$/) {
  422:                 $target->[-1] = $newline;
  423:                 $modified = 1;
  424:             } else {
  425:                 push(@$target,$newline);
  426:                 $modified = 1;
  427:             }
  428:         }
  429:     }
  430:     return $modified;
  431: }
  432: 
  433: #################################################################
  434: #################################################################
  435: 
  436: =pod
  437: 
  438: =over 4
  439: 
  440: =item &update_rhn_source()
  441: 
  442: Modifies the Red Hat 4 sources file which includes repositories used by up2date 
  443: 
  444: Inputs: 
  445: $rhn_items - a reference to hash of a hash containing the regular expression
  446: to test for, and the text string to append to the file, if an entry for the 
  447: LON-CAPA RHEL repository is missing for two cases:
  448: 
  449: (a) basearch
  450: (b) noarch 
  451: 
  452: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  453: 
  454: =back
  455: 
  456: =cut
  457: 
  458: #################################################################
  459: #################################################################
  460: sub update_rhn_source {
  461:     my ($rhn_items) = @_;
  462:     return 0 if (ref($rhn_items) ne 'HASH');
  463:     return 0 if ((ref($rhn_items->{basearch}) ne 'HASH') || (ref($rhn_items->{noarch}) ne 'HASH'));
  464:     my $file = '/etc/sysconfig/rhn/sources';
  465:     return 0 if (! -e $file);
  466:     my $backup = $file.'.backup';
  467:     if (! copy($file,$backup)) {
  468:         warn "**** Error: Unable to make backup of $file";
  469:         return 0;
  470:     }
  471:     my $result = 0;
  472:     my $fh;
  473:     if (open($fh,"<$file")) {
  474:         my $total = 0;
  475:         my %found;
  476:         foreach my $item (keys(%{$rhn_items})) {
  477:             $found{$item} = 0;
  478:         }
  479:         while(<$fh>) {
  480:             foreach my $item (keys(%{$rhn_items})) {
  481:                 if (ref($rhn_items->{$item}) eq 'HASH') {
  482:                     my $pattern = $rhn_items->{$item}->{regexp};
  483:                     if ($pattern ne '') { 
  484:                         if (m{^$pattern}) {
  485:                             $found{$item} = 1;
  486:                             $total ++;
  487:                         }
  488:                     }
  489:                 }
  490:             }
  491:             last if $total == 2;
  492:         }
  493:         close($fh);
  494:         if ($total < 2) {
  495:             if (open($fh,">>$file")) {
  496:                 foreach my $item (keys(%{$rhn_items})) {
  497:                     unless ($found{$item}) {
  498:                         if (ref($rhn_items->{$item}) eq 'HASH') {
  499:                             if ($rhn_items->{$item}->{text} ne '') {
  500:                                 print $fh "\n".$rhn_items->{$item}->{text}."\n";
  501:                                 $result = 1;
  502:                             }
  503:                         }
  504:                     }
  505:                 }
  506:                 close($fh);
  507:             }
  508:         }
  509:     }
  510:     return $result;
  511: }
  512: 
  513: #################################################################
  514: #################################################################
  515: 
  516: =pod
  517: 
  518: =over 4
  519: 
  520: =item &update_apt_source()
  521: 
  522: Modifies the source.list file which includes repositories used by apt-get
  523: 
  524: Inputs:
  525: $deb_row - a reference to containing the regular expression
  526: to test for, and the text string to append to the file, if an entry for the
  527: LON-CAPA Debian/ or Ubuntu repository is missing.
  528: 
  529: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
  530: 
  531: =back
  532: 
  533: =cut
  534: 
  535: #################################################################
  536: #################################################################
  537: sub update_apt_source {
  538:     my ($deb_row) = @_;
  539:     return 0 if (ref($deb_row) ne 'HASH');
  540:     return 0 if (($deb_row->{regexp} eq '') || ($deb_row->{text} eq ''));
  541:     my $file = '/etc/apt/sources.list';
  542:     return 0 if (! -e $file);
  543:     my $backup = $file.'.backup';
  544:     if (! copy($file,$backup)) {
  545:         warn "**** Error: Unable to make backup of $file";
  546:         return 0;
  547:     }
  548:     my $result = 0;
  549:     my $fh;
  550:     if (open($fh,"<$file")) {
  551:         my $found = 0;
  552:         my $pattern = $deb_row->{regexp};
  553:         while(<$fh>) {
  554:             if (m{^$pattern}) {
  555:                 $found = 1;
  556:                 last;
  557:             }
  558:         }
  559:         close($fh);
  560:         if (!$found) {
  561:             if (open($fh,">>$file")) {
  562:                 print $fh "\n".$deb_row->{text}."\n";
  563:                 close($fh);
  564:                 $result = 1;
  565:             }
  566:         }
  567:     }
  568:     return $result;
  569: }
  570: 

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