#!/usr/bin/perl # Copyright 2004 Revolution Linux # Benoit des Ligneris # Copyright (c) 2003, The Board of Trustees of the University of Illinois. # All rights reserved. # Copyright 2002 International Business Machines # Sean Dague # Copyright (c) 2002-2007 The Trustees of Indiana University. # All rights reserved. # # $Id: install_cluster 7035 2008-06-17 02:31:41Z valleegr $ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # This is the oscar installation program. It must be called with # one argument which is the installation network device use strict; use Cwd qw(chdir cwd); use lib cwd() . "/lib"; use vars qw($VERSION); use OSCAR::Logger; use OSCAR::OCA::OS_Detect; use OSCAR::SystemSanity; use POSIX; use Carp; use File::Basename; use Getopt::Long; use OSCAR::Env qw ( oscar_home_env ); my $cli = ''; my $selector = ''; my $build = ''; my $define = ''; my $network = ''; my $db = ''; my $adapter; my $help = ''; my $bootscript = ''; GetOptions ('help' => \$help, 'cli' => \$cli, 'opkgselector=s' => \$selector, 'buildimage=s' => \$build, 'defineclients=s' => \$define, 'networkclients=s' => \$network, 'database|d=s' => \$db, 'bootscript=s' => \$bootscript); #If we get a --help flag if($help) { print "Usage: install_cluster [OPTION] adapter Starts the OSCAR install process. By default, install_cluster uses the Graphical mode. --cli Runs the program in command line mode. --opkgselector file Passes the file into the selector stage of the install. That stage will not ask for user input. --buildimage file Passes the file into the build stage of the install. That stage will not ask for user input. --defineclients file Passes the file into the define clients stage of the install. That stage will not ask for user input. --networkclients file Passes the file into the setup network stage of the install. That stage will not ask for user input. --database file Passes the database type to determine what database is used for the OSCAR installation. (e.g., --database mysql, --database pgsql) --bootscript file Passes the file to confirm the client nodes have booted with their new images into the main cli. --help Display this help and exit.\n"; exit 0; } #Create and environment variable to let everyone know what kind of interface #we are going to use if($cli) { $ENV{OSCAR_UI} = "cli"; oscar_log_subsection("Setting env variable OSCAR_UI to cli"); } else { $ENV{OSCAR_UI} = "gui"; oscar_log_subsection("Setting env variable OSCAR_UI to gui"); } #Put the full pathname on there since this will change directories my $cwd = cwd(); $selector = $cwd . "/$selector" if($selector !~ /^\// && $selector ne ''); $build = $cwd . "/$build" if ($build !~ /^\// && $build ne ''); $define = $cwd . "/$define" if ($define !~ /^\// && $define ne ''); $network = $cwd . "/$network" if ($network !~/^\// && $network ne ''); $bootscript = $cwd . "/$bootscript" if ($bootscript !~/^\// && $bootscript ne ''); my $adapter = shift; $ENV{OSCAR_HEAD_INTERNAL_INTERFACE}=$adapter; # Validate OSCAR_HOME environment variable and write /etc/profile.d files &oscar_home_env(); # First of all, we do some system checking if ( system("./scripts/system-sanity") ) { die "ERROR: There are basic system configuration issues (see log).\n"; } print "System checked\n"; # Now check to see if there is an $ENV{OSCAR_HOME} directory, and if # so, if we're in it. if (! -d $ENV{OSCAR_HOME}) { die("ERROR: The environment variable \$OSCAR_HOME was set, but the directory that it points to ($ENV{OSCAR_HOME}) does not exist!"); } if (!chdir($ENV{OSCAR_HOME})) { die("ERROR: The environment variable \$OSCAR_HOME was set, but could not change into the directory that it points to ($ENV{OSCAR_HOME})!"); } # Default database type is mysql if --database( or -d) option is not # given $ENV{OSCAR_DB} = "mysql:"; if($db) { # convert all the inputs to the lowercase characters $ENV{OSCAR_DB} = lc($db); } # Switch to have symlink(oda.pm) point to the right database # module(mysql.pm, pgsql.pm, or anything else) according to the given # --database option. my $lib_dir = "$ENV{OSCAR_HOME}/lib/OSCAR"; unlink "$lib_dir/oda.pm"; my $oda_dir = "$ENV{OSCAR_HOME}/packages/oda"; unlink "$oda_dir/prereq.cfg"; if( $ENV{OSCAR_DB} eq "pg" || $ENV{OSCAR_DB} eq "pgsql" || $ENV{OSCAR_DB} eq "postgresql" ){ $ENV{OSCAR_DB} = "pgsql:"; system("ln -s $lib_dir/ODA/pgsql.pm $lib_dir/oda.pm"); system("ln -s $oda_dir/prereqs/pgsql.cfg $oda_dir/prereq.cfg"); # If postmaster is not running and pgsql rpm is not installed, # we assume that pgsql is not installed yet. $ENV{OSCAR_DB} .= "new" if !system("ps -ef | grep postmaster > /dev/null 2>&1") && !system("rpm -qa | grep postgresql > /dev/null 2>&1"); }else{ system("ln -s $lib_dir/ODA/mysql.pm $lib_dir/oda.pm"); system("ln -s $oda_dir/prereqs/mysql.cfg $oda_dir/prereq.cfg"); } # Get OSCAR's version my $oscar_version; my $oscar_version_script = $ENV{OSCAR_HOME} ."/" . "scripts/get-oscar-version.sh"; my $oscar_version_file = $ENV{OSCAR_HOME} . "/" . "VERSION"; # Use the scripty-foo to get oscar version information. if ( -e "$oscar_version_file" ) { my $cmd = "$oscar_version_script $oscar_version_file --full"; open(CMD, "$cmd|") or die "ERROR: failed to get oscar version '$cmd' - $!"; $oscar_version = ; chomp($oscar_version); close(CMD); } else { die("ERROR: OSCAR VERSION file missing '$oscar_version_file' - aborting!"); } # Once here, we know that $ENV{OSCAR_HOME} is set, it exists, we can # get in it, and we have successfully read the VERSION file from it. # So we should be good to go for the rest of the installation. # Set perl to autoflush all output $| = 1; # Setup to capture all stdout/stderr my $oscar_log_dir = "/var/log/oscar"; if (! -d $oscar_log_dir ) { print "$oscar_log_dir does not exist, we create it\n"; mkdir ($oscar_log_dir); } my $oscar_logfile = $oscar_log_dir . "/oscarinstall.log"; # EF: Fix for bug #244: multiple oscarinstall.log files # The current (and latest) log file is oscarinstall.log. Old log files # get a number appended (eg. oscarinstall.log_27), starting with _1 # and increasing with each new invocation of install_cluster. # Date stamp added to output. if (-e $oscar_logfile) { my $indx = 1; # more old logs around? my @ologs = glob("$oscar_logfile"."_*"); @ologs = map { if (/_(\d+)$/) { $1 } } @ologs; @ologs = sort { $a <=> $b; } @ologs; if (@ologs) { $indx = $ologs[$#ologs] + 1; } !system("mv $oscar_logfile $oscar_logfile"."_$indx") or die "Could not rename $oscar_logfile : $!"; } if (!open (STDOUT,"| tee $oscar_logfile") || !open(STDERR,">&STDOUT")) { die("ERROR: Cannot tee stdout/stderr into the OSCAR logfile: ". "$oscar_logfile\n\nAborting the install.\n\n"); } # First output banner my $date=`date`; chomp($date); oscar_log_section("Running OSCAR install_cluster script $date"); # Fix to make multi lingualness work $ENV{LANG} = "C"; $ENV{LC_ALL} = "C"; $ENV{LANGUAGE} = "C"; $ENV{LC_COLLATE} = "C"; $ENV{LC_CTYPE} = "C"; $ENV{LC_MESSAGES} = "C"; $ENV{LC_MONETARY} = "C"; $ENV{LC_NUMERIC} = "C"; $ENV{LC_TIME} = "C"; # Check to see if this is a supported platform oscar_log_subsection("Checking if this is a supported platform"); my $os = OSCAR::OCA::OS_Detect::open(); if (!$os) { print("ERROR: This is an unsupported system. Specifically, no module in OSCAR/OCA/OS_Detect positively identified this as a supported system.\n"); die("Cannot continue"); } # add entries to path that we know we will need $ENV{PATH} = $ENV{PATH} . ':/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin'; # TJN (10/4/2005): Note, a fairly evil, totally non-obvious issue # occurs if you have /tftpboot setup as a symlink, # e.g., /tftpboot -> /var/tftpboot/, and remove 'tftp-server'. # What happens is the '/tftpboot' dir (symlink) gets removed! # This is b/c '/tftpboot' is part of the RPM file manifest for # tftp-server (at least as of v0.33-3 it does). # # Adding a sanity check after the RPM removes to check for this case! croak "\nError: \'/tftpboot\' is gone!" if(! -d "/tftpboot" ); # Run the wizard_prep script my $cmd = "cd $ENV{OSCAR_HOME}/scripts && ./wizard_prep"; oscar_log_subsection("Running: \"$cmd\""); !system($cmd) or die("Oscar Wizard preparation script failed to complete ($cmd)"); oscar_log_subsection("Successfully ran wizard_prep"); # # HORRIBLE HACK ALERT -- FIXING MANDRAKE SNAFU # #print __FILE__,":",__LINE__,":INC:",join(", ",@INC),"\n"; my %incs = map { $_ => 1 } @INC; foreach ( `perl -e 'print "\$_\n" foreach \@INC'` ) { chomp; eval "use lib \"$_\"" unless $incs{$_}; } undef %incs; #print __FILE__,":",__LINE__,":INC:",join(", ",@INC),"\n"; oscar_log_section("Prerequisites installed"); # Print some environment information oscar_log_subsection("OSCAR version: $oscar_version"); my $hostname = (uname)[1]; my ($shorthostname) = split(/\./,$hostname,2); my $dnsdomainname = `dnsdomainname`; chomp($dnsdomainname); oscar_log_subsection("Command line invocation: $0 $adapter " . join(" ", @ARGV)); oscar_log_subsection("Hostname: $shorthostname"); oscar_log_subsection("DNS domain name: $dnsdomainname"); oscar_log_subsection("Network interface: $adapter"); oscar_log_subsection("Linux distribution: $os->{distro} $os->{distro_version}"); oscar_log_subsection("Kernel version: " . (uname)[2]); oscar_log_subsection("Architecture: $os->{arch}"); oscar_log_subsection("Running in directory: " . cwd()); oscar_log_subsection("PATH: " . $ENV{PATH}); # Now start the execution chdir("scripts") or die("Couldn't chdir to scripts") if ($ENV{OSCAR_UI} eq "gui"); chdir("scripts/cli") or die("Couldn't chdir to scripts/cli") if ($ENV{OSCAR_UI} eq "cli"); # Only setup what we have to get to the OSCAR wizard. All the rest of # server prep is going to be driven after the first panel of # questions. if ($ENV{OSCAR_UI} eq "cli") { $cmd = "./main_cli"; $cmd = $cmd . " --opkgselector $selector" if $selector; $cmd = $cmd . " --buildimage $build" if $build; $cmd = $cmd . " --defineclients $define" if $define; $cmd = $cmd . " --networkclients $network" if $network; $cmd = $cmd . " --bootscript $bootscript" if $bootscript; $cmd = $cmd . " $adapter"; } else { $cmd = "./oscar_wizard install"; } oscar_log_subsection("Running: \"$cmd\""); !system("$cmd 2>&1") or die("Oscar Wizard failed to run successfully"); oscar_log_subsection("Successfully ran oscar_wizard"); oscar_log_subsection("Successfully ran OSCAR install_cluster script"); # All done.