xcat-core/xCAT/postscripts/db2install

737 lines
18 KiB
Perl
Executable File

#!/usr/bin/perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#(C)IBM Corp
#
#-----------------------------------------------------------------------------
=head1 db2install
This postscript installs and sets up db2 on a client machine, usually a Service Node
or a login node. This script can only be used to automatically install an
AIX 6.1 or 7.1, or a Linux Redhat5 or Redhat6 Client.
Note: the db2 code must be in a mountable directory defined by the
db2installloc attribute in the site table.
The perl-DBD-DB2 code should have been installed during the xCAT install from
the AIX or Linux xCAT deps package for AIX6.1 or 7.1 or Redhat5 or Redhat 6.
More information can be obtained from the xCAT http://xcat.svn.sourceforge.net/viewvc/xcat/xcat-core/trunk/xCAT-client/share/doc/xCAT2SetupDB2.pdf.
Needs export MASTER=site.master
export DB2INSTALLLOC=site.db2installlloc
export DATABASELOC=site.databaseloc
export INSTALLDIR=site.installdir
export XCATDPORT=site.xcatdport
export NODE=<mynodename>
=cut
#-----------------------------------------------------------------------------
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
# if AIX - make sure we include perl 5.8.2 in INC path.
# Needed to find perl dependencies shipped in deps tarball.
if ($^O =~ /^aix/i)
{
use lib "/usr/opt/perl5/lib/5.8.2/aix-thread-multi";
use lib "/usr/opt/perl5/lib/5.8.2";
use lib "/usr/opt/perl5/lib/site_perl/5.8.2/aix-thread-multi";
use lib "/usr/opt/perl5/lib/site_perl/5.8.2";
}
use lib "$::XCATROOT/lib/perl";
use strict;
use IO::Socket;
use File::Path;
use Expect;
use xCAT::Utils;
use xCAT::NetworkUtils;
use xCAT::MsgUtils;
my $useSocketSSL = eval { require IO::Socket::SSL; };
if ($useSocketSSL)
{
require IO::Socket::SSL;
}
# MAIN
my $rc = 0;
my $msg = "";
my $cmd;
# setup some important variable
$::osname = `uname`;
chomp $::osname;
$::sdate = `/bin/date`;
chomp $::sdate;
$::hname = `hostname`;
chomp $::hname;
$::MN = $ENV{'MASTER'}; # as known by the node
$::databaseloc = $ENV{'DATABASELOC'}; # directory for db instance
my $installdir = $ENV{'INSTALLDIR'}; # installdir
# check to see if the databaseloc attribute is in the installdir attribute
# directory path. If it is error out and send something to syslog
my @installlocdir = split '/', $installdir; # get base of installdir
my @dblocdir = split '/',$::databaseloc; # get base of database
if ($installlocdir[1] eq $dblocdir[1] ) { # if they match,error
my $msg="db2install:The site databaseloc attribute is set to the directory or a sub-directory of the site table installloc or installdir attribute or the default of /install. This is not a supported configuration.";
`logger -t xcat -p local4.err $msg`;
exit(1);
}
if ($::osname eq 'AIX')
{
$::installdb2dir = "/opt/IBM/db2/V9.7"; # default
}
else
{ # linux
$::installdb2dir = "/opt/ibm/db2/V9.7"; # default
}
my $msg;
# check to see if db2 already installed and configured, if so
# skip the install
my $db2install = $::installdb2dir;
$db2install .= "\/instance";
if (!(-e ($db2install)))
{ # not already installed
$::db2installloc = $ENV{'DB2INSTALLLOC'};
if (!$::db2installloc)
{
$::db2installloc = "/mntdb2";
}
chomp $::db2installloc;
$::db2installloc =~
s/^(\'|\")(.*)(\"|\')$/$2/; # remove any surrounding quotes
# startNFS
$rc = &startNFS;
# mount the db2 directory to get to the db2 code to install
$rc = &mountdb2code;
# install db2
if ($rc == 0)
{
$rc = &installdb2code;
if ($rc != 0)
{
$msg = "db2install:Error installing DB2. Cannot continue. \n";
`logger -t xcat -p local4.err $msg`;
&unmountdb2code;
exit(1);
}
# unmount the db2 directory install directory
&unmountdb2code;
}
else
{
$msg =
"db2install:Cannot mount the site.db2installloc directory to get the db2 code to install. Setup cannot continue.\n";
`logger -t xcat -p local4.err $msg`;
exit(1);
}
}
else
{
$msg = "db2install:DB2 is already installed. Will skip installation. \n";
`logger -t xcat -p local4.info $msg`;
}
# get the cfgloc file,if linux should be in /etc/xcat/cfgloc.db2 from xcatserver
# postscript
$rc = &getcfgloc;
if ($rc != 0)
{ # could not get the cfgloc file, cannot continue
$msg =
"db2install:Cannot get the cfgloc file from the MN. Client setup cannot continue. \n";
`logger -t xcat -p local4.err $msg`;
exit 1;
}
# setup the db2 Client for xCAT and start xCAT on the DB2 database
&rundb2sqlsetup;
exit 0;
#
# Subroutines
#
# run the command
sub runcmd
{
my ($cmd) = @_;
my $rc = 0;
$cmd .= ' 2>&1';
# my $outref = [];
# @$outref = `$cmd`;
$::outref = [];
$::outref = `$cmd`;
if ($?)
{
$rc = $? >> 8;
if ($rc > 0)
{
my $msg = "db2install:$cmd returned rc=$rc $::outref\n";
`logger -t xcat -p local4.info $msg`;
return 1;
}
}
return 0;
}
#####################################################
#
# getcfgloc
# Get DB cfgloc file
#
#####################################################
sub getcfgloc
{
my $msg;
my $filename = "/etc/xcat/cfgloc";
my $cfgsave = "/etc/xcat/cfgloc.db2";
if (-e $cfgsave)
{
my $cmd = " cp $cfgsave $filename ";
xCAT::Utils->runcmd($cmd, 0);
if ($::RUNCMD_RC != 0)
{
$msg = "db2install: $cmd failed.\n";
`logger -t xcat -p local4.err $msg`;
return 1;
}
}
else
{ # file not there get it from the MN
my $response = &getresponse("xcat_cfgloc");
if (defined($response))
{
my $fd;
&runcmd("mkdir -p /etc/xcat");
open($fd, '>', $filename);
print $fd $response;
close($fd);
# set the permissions
my $cmd = "chmod 600 $filename > /dev/null 2>&1";
&runcmd($cmd);
}
else
{
$msg = "db2install: Could not get cfgloc file.\n";
`logger -t xcat -p local4.err $msg`;
return 1;
}
# get the info
my $xcatcfg;
my $cfgl;
open($cfgl, "<", $filename);
$xcatcfg = <$cfgl>;
close($cfgl);
chomp $xcatcfg;
my ($hdr, $instance, $password) = split('\|', $xcatcfg);
if ($hdr =~ /^DB2:/)
{
return 0;
}
else
{
$msg = "db2install: cfgloc file not for DB2.\n";
`logger -t xcat -p local4.err $msg`;
return 1;
}
}
return 0;
}
#####################################################
#
# startNFS
# Makes sure NFS is running
#
#####################################################
sub startNFS
{
my $rc = 0;
if (xCAT::Utils->isLinux())
{
my $os = xCAT::Utils->osver();
if ($os =~ /sles.*/)
{
$rc = xCAT::Utils->startService("nfs");
$rc = xCAT::Utils->startService("nfsserver");
}
else
{
$rc = xCAT::Utils->startService("nfs");
}
}
else
{ #AIX
$rc = xCAT::Utils->startService("nfsd");
}
if ($rc != 0)
{
return 1;
}
return $rc;
}
#####################################################
#
# mountdb2code
# mount the directory from the db2server that contains
# the db2 code
#
#####################################################
sub mountdb2code
{
my $msg;
my $rc;
my $server;
my $db2installloc = $ENV{'DB2INSTALLLOC'};
if (!($db2installloc))
{
$db2installloc = "/mntdb2"; # set default
}
# determine server and mount location
if (grep /:/, $db2installloc)
{
my ($hostname, $newinstallloc) = split ":", $db2installloc;
if ($hostname)
{ # hostname set in /installloc attribute
$server = $hostname; # set server for mount
$::installloc = $newinstallloc; #set path for mount point
}
}
else
{
$server = $::MN;
$::installloc = $db2installloc;
}
# mount the install directory from the installloc location
# make the directory to mount on-- same name
if (!(-e $::installloc))
{
mkpath($::installloc);
}
# check to see if already mounted
my $mounted = xCAT::Utils->isMounted($::installloc);
if ($mounted == 0)
{ # not mounted
# need to mount the directory
my $cmd;
if ($ENV{'USENFSV4ONAIX'} && ($ENV{'USENFSV4ONAIX'} =~ /1|Yes|yes|YES|Y|y/))
{
$cmd = "mount -o vers=4 $server:$::installloc $::installloc";
}
else
{
$cmd = "mount $server:$::installloc $::installloc";
}
$rc = &runcmd($cmd);
}
return $rc;
}
#####################################################
#
# installdb2code
# installs the db2 code from the mounted server
#
#####################################################
sub installdb2code
{
my $msg;
my $rc = 0;
my $installcode;
my $installcode1 = "$::installloc/ese/db2_install";
my $installcode2 = "$::installloc/server/db2_install";
my $installcode3 = "$::installloc/wser/db2_install";
my $installcode4 = "$::installloc/wse/db2_install";
if ((!(-e $installcode1)) && (!(-e $installcode2)) && (!(-e $installcode3)) && (!(-e $installcode4)))
{
$msg = "db2install:Install code does not exist. Cannot install DB2 code.\n";
`logger -t xcat -p local4.err $msg`;
exit 1;
}
# pick the correct install directory
if (-e $installcode1 ) {
$installcode=$installcode1;
} else {
if (-e $installcode2 ) {
$installcode=$installcode2;
} else {
if (-e $installcode3 ) {
$installcode=$installcode3;
} else {
$installcode=$installcode4;
}
}
}
my $expect_log = "/tmp/xcatexpect.log";
$msg =
"db2install:Starting DB2 install. Monitor progress in $expect_log on the node. \n";
`logger -t xcat -p local4.info $msg`;
my $db2sql;
my $timeout = 1000; #sets Expect default timeout, 0 accepts immediately
my $timeout; # null says wait forever
my $pwd_sent = 0;
my $dir_prompt = 'Do you want';
my $product_prompt = " to exit";
my $debug = 0;
if ($::VERBOSE)
{
$debug = 1;
}
$db2sql = new Expect;
#
# -re $dir_prompt
# Installation of products - /opt/ibm/db2/V9.7
#
# Do you want to choose a different directory to install [yes/no] ?
#
# -re $product_prompt
# Specify one of the following keywords to install DB2 products.
# ESE
# CLIENT
# RTCL
#
#
# disable command echoing
#$db2sql->slave->stty(qw(sane -echo));
# restart timeout
$db2sql->restart_timeout_upon_receive(1);
#
# exp_internal(1) sets exp_internal debugging
# to STDERR.
#
#$db2sql->exp_internal(1);
$db2sql->exp_internal($debug);
#
# log_stdout(0) prevent the program's output from being shown.
#
#$db2sql->log_stdout(1);
$db2sql->log_stdout($debug);
#
# log session
#
#$db2sql->log_file($expect_log);
$db2sql->log_file($expect_log);
my $spawncmd;
$spawncmd = "$installcode";
unless ($db2sql->spawn($spawncmd))
{
$msg = "db2install:Unable to run $spawncmd to create database.\n";
`logger -t xcat -p local4.err $msg`;
exit 1;
}
#
# setup input to db2_install
#
my @result = $db2sql->expect(
$timeout,
[
$dir_prompt,
sub {
$db2sql->send("no\r");
$db2sql->clear_accum();
$db2sql->exp_continue();
}
],
[
$product_prompt,
sub {
$db2sql->send("CLIENT\r");
$db2sql->exp_continue();
}
]
);
##########################################
# Expect error - report and quit
##########################################
if (defined($result[1]))
{
my $errmsg = $result[1];
$db2sql->soft_close();
$msg = "db2install:Installing DB2 results = $errmsg.\n";
`logger -t xcat -p local4.info $msg`;
}
$db2sql->soft_close();
$msg = "db2install:Ending DB2 install.\n";
`logger -t xcat -p local4.info $msg`;
return $rc;
}
#####################################################
#
# unmountdb2code
# unmounts the directory from the db2server that contains
# the db2 code
#
#####################################################
sub unmountdb2code
{
my $msg;
my $rc = 0;
my $cmd;
# need to un mount the directory
if ($::osname eq 'AIX')
{
$cmd = "unmount $::installloc";
}
else
{
$cmd = "umount $::installloc";
}
$rc = &runcmd($cmd);
return $rc;
}
#####################################################
#
# rundb2sqlsetup
# runs the db2sqlsetup script and sets up xCAT/DB2 Client
#
#####################################################
sub rundb2sqlsetup
{
my $msg;
my $rc = 0;
my $cmd;
my $filename = "/etc/xcat/cfgloc";
# get the info
my $xcatcfg;
my $cfgl;
open($cfgl, "<", $filename);
$xcatcfg = <$cfgl>;
close($cfgl);
chomp $xcatcfg;
my ($database, $instance, $password) = split('\|', $xcatcfg);
if ($::databaseloc) {
if (!(-e $::databaseloc)) { # if it does not exist, create it
&runcmd("mkdir -p $::databaseloc");
}
$cmd =
"DATABASELOC=$::databaseloc XCATDB2SERVER=$::MN XCATDB2PW=$password $::XCATROOT/bin/db2sqlsetup -i -C";
} else {
$cmd =
"XCATDB2SERVER=$::MN XCATDB2PW=$password $::XCATROOT/bin/db2sqlsetup -i -C";
}
$msg = "db2install:Running Client setup. \"$::XCATROOT/bin/db2sqlsetup -i -C\"\n";
`logger -t xcat -p local4.info $msg`;
$rc = &runcmd($cmd);
$msg = "db2install: Client setup finished.\n";
`logger -t xcat -p local4.info $msg`;
return $rc;
}
#####################################################
#
# getresponse
# Request info from xcatd on the management node
#
# - uses SSL socket on port 3001 to connect to MN xcatd
# to make the request for info
#
#####################################################
sub getresponse
{
my ($req) = @_;
my $msg;
my $port = $ENV{'XCATDPORT'};
my $node = $ENV{'NODE'};
# open listener connection to wait for check from management node
my $lpid = &openlistener();
# open a socket to request data
my $sock =
IO::Socket::SSL->new(
PeerAddr => $::MN,
PeerPort => $port,
Proto => 'tcp',
);
# try a few more times
my $times = 1;
while (!$sock)
{
sleep(2);
$times++;
$sock =
IO::Socket::SSL->new(
PeerAddr => $::MN,
PeerPort => $port,
Proto => 'tcp',
);
if ($times == 5)
{
last;
}
}
unless ($sock)
{
$msg = "db2install: Cannot connect to host \'$::MN\'\n";
`logger -t xcat -p local4.err $msg`;
print $msg;
return undef;
}
# request must be in XML format
print $sock "<xcatrequest>\n";
print $sock " <command>getcredentials</command>\n";
print $sock " <arg>$req</arg>\n";
print $sock " <callback_port>300</callback_port>\n";
print $sock "</xcatrequest>\n";
#TODO - do we have to try again after waiting for a bit????
my $response = '';
my $line;
while (defined($line = <$sock>))
{
# skip xml tags
next if ($line =~ /^\s*</);
# once we get to serverdone we have the whole response
if ($line =~ m/<\/serverdone>/)
{
last:
}
$response .= $line;
}
close($sock);
#print "resp = \'$response\'\n";
kill 2, $lpid;
if ($response)
{
return $response;
}
return undef;
}
#####################################################
#
# openlistener
# - fork a child process to respond to a check from the MN
#
#####################################################
sub openlistener
{
my $node = $ENV{'NODE'};
# fork a child process to open a socket to listen for communication
# from the server
my $pid = xCAT::Utils->xfork;
unless (defined $pid)
{
# fork failed
$msg = "db2install: Could not fork process.\n";
`logger -t xcat -p local4.err $msg`;
#print $msg;
return undef;
}
if ($pid != 0)
{
# This is the parent process, just return
return $pid;
}
my $listener =
IO::Socket::INET->new(
LocalPort => '300',
Proto => 'tcp',
Listen => '64',
Reuse => 1
);
unless ($listener)
{
my $msg = "db2install: Cannot open socket on \'$node\'\n";
`logger -t xcat -p local4.err $msg`;
print $msg;
exit 1;
}
# xcatd sends a quick req to see if we are really asking
# for info - this listener checks for the req and says ok
my $client;
while ($client = $listener->accept())
{
# $client is the new connection
my $text = <$client>;
# see if we got "CREDOKBYYOU?"
if ($text =~ /CREDOKBYYOU?/)
{
print $client "CREDOKBYME";
close($client);
close($listener);
exit 0;
}
close($client);
}
close($client);
close($listener);
exit 0;
}