Annotation of loncom/debugging_tools/modify_config_files.pl, revision 1.9
1.1 matthew 1: #!/usr/bin/perl -w
2: #
3: # The LearningOnline Network
4: #
1.9 ! raeburn 5: # $Id: modify_config_files.pl,v 1.8 2008/01/12 21:15:00 raeburn Exp $
1.1 matthew 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:
1.9 ! raeburn 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).
1.1 matthew 42:
43: =head1 DESCRIPTION
44:
1.9 ! raeburn 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:
1.1 matthew 51: The /etc/my.cnf file is modified to set the wait_timeout to 1 year. Backup
1.9 ! raeburn 52: copies of each file are made in /etc, /etc/apt, and /etc/sysconfig/rhn, as
! 53: appropriate.
1.1 matthew 54:
55: =cut
56:
57: use strict;
58: use File::Copy;
1.3 matthew 59: use lib '/home/httpd/lib/perl/';
60: use LONCAPA::Configuration;
61: my $loncapa_config=LONCAPA::Configuration::read_conf('loncapa.conf');
1.1 matthew 62:
1.6 raeburn 63: open(DSH,"$$loncapa_config{'lonDaemons'}/distprobe |");
64: my $dist = <DSH>;
65: chomp($dist);
66: close(DSH);
67:
68: my $yum_status;
1.9 ! raeburn 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: }
1.6 raeburn 78: $yum_status =
79: &update_file('/etc/yum.conf',
80: [{section => 'loncapa-updates-$basearch',
1.1 matthew 81: key => 'name=',
1.6 raeburn 82: value => 'Fedora Core $releasever LON-CAPA $basearch Updates',
83: }, {section => 'loncapa-updates-$basearch',
1.1 matthew 84: key => 'baseurl=',
1.9 ! raeburn 85: value => $loninst.'/fedora/linux/loncapa/$releasever/$basearch',
1.6 raeburn 86: }, {section => 'loncapa-updates-$basearch',
1.5 matthew 87: key => 'gpgcheck=',
1.9 ! raeburn 88: value => $gpgchk,
! 89: }, {section => 'loncapa-updates-$basearch',
! 90: key => 'gpg=',
! 91: value => $gpg,
1.1 matthew 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=',
1.9 ! raeburn 97: value => $loninst.'/fedora/linux/loncapa/$releasever/noarch',
1.5 matthew 98: }, {section => 'loncapa-updates-noarch',
99: key => 'gpgcheck=',
1.9 ! raeburn 100: value => $gpgchk,
! 101: }, {section => 'loncapa-updates-noarch',
! 102: key => 'gpg=',
! 103: value => $gpg,
1.1 matthew 104: }]);
1.9 ! raeburn 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}{gpchk},
! 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}{gpchk},
! 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},);
1.6 raeburn 197: }
198: }
1.1 matthew 199:
1.4 matthew 200: my $mysql_global_status =
201: &update_file('/etc/my.cnf',
1.1 matthew 202: [{section =>'mysqld',
203: key =>'set-variable=wait_timeout=',
204: value =>'31536000', }]);
205:
1.3 matthew 206: my $local_my_cnf = '/home/www/.my.cnf';
207: if (! -e $local_my_cnf) {
1.4 matthew 208: # Create a file so we can do something with it...
1.3 matthew 209: system("touch $local_my_cnf");
210: }
1.4 matthew 211: my $mysql_www_status =
212: &update_file($local_my_cnf,
1.3 matthew 213: [{section =>'client',
214: key =>'user=',
215: value =>'www',},
216: {section =>'client',
217: key =>'password=',
218: value =>$loncapa_config->{'lonSqlAccess'}},]);
219:
1.4 matthew 220: my $exitvalue = 0;
221:
222: if ($mysql_global_status) { $exitvalue = 1; }
223:
224: exit $exitvalue;
1.1 matthew 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)) {
1.4 matthew 232: warn "**** Error: Unable to make backup of $file";
1.1 matthew 233: return 0;
234: }
235: my ($filedata) = &parse_config_file($file);
1.4 matthew 236: if (! ref($filedata)) { warn "**** Error: $filedata"; return 0;}
237: my $modified = 0;
1.1 matthew 238: foreach my $data (@$newdata) {
239: my $section = $data->{'section'};
240: my $key = $data->{'key'};
241: my $value = $data->{'value'};
1.4 matthew 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; }
1.1 matthew 248: }
1.4 matthew 249: return $modified;
1.1 matthew 250: }
251:
252: #################################################################
253: #################################################################
254:
255: =pod
256:
1.9 ! raeburn 257: =over 4
! 258:
! 259: =item &parse_config_file()
1.1 matthew 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:
1.9 ! raeburn 267: =back
! 268:
1.1 matthew 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)) {
1.4 matthew 286: chomp($line);
1.1 matthew 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:
1.9 ! raeburn 307: =over 4
! 308:
1.1 matthew 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:
1.9 ! raeburn 318: =back
! 319:
1.1 matthew 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:
1.9 ! raeburn 361: =over 4
! 362:
! 363: =item &modify_config_file()
1.1 matthew 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:
1.4 matthew 375: Returns: 0 or 1, indicating if the file was modified(1) or not(0).
376:
1.9 ! raeburn 377: =back
1.4 matthew 378:
1.1 matthew 379: =cut
380:
381: #################################################################
382: #################################################################
383: sub modify_config_file {
384: my ($filedata,$section,$newkey,$newvalue)=@_;
1.4 matthew 385: my $modified = 0; # returned value - set to true if the file is modified
1.1 matthew 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/) {
1.4 matthew 408: if ($target->[$i] ne $newline) {
409: $target->[$i]=$newline;
410: $modified = 1;
411: }
1.1 matthew 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.
1.2 matthew 421: if (defined($target->[-1]) && $target->[-1] =~ /^\s*$/) {
1.1 matthew 422: $target->[-1] = $newline;
1.4 matthew 423: $modified = 1;
1.1 matthew 424: } else {
425: push(@$target,$newline);
1.4 matthew 426: $modified = 1;
1.1 matthew 427: }
428: }
429: }
1.4 matthew 430: return $modified;
1.1 matthew 431: }
432:
1.9 ! raeburn 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: }
1.1 matthew 512:
513: #################################################################
514: #################################################################
515:
516: =pod
517:
1.9 ! raeburn 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:
1.1 matthew 531: =back
532:
533: =cut
534:
535: #################################################################
536: #################################################################
1.9 ! raeburn 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>