#!/bin/sh # # aryzhov@spasu.net # install IBM's cluster-aware middleware into shared disks # # First, source the environmend and check if we aren't chrooted yet. # [ -z "$SID" ] && SID=/tmp/install_config [ X$SubrIsRead = XYes ] || . $SID/Scripts/Misc/!Includes/Subroutines [ X$VarsAreSet = XYes ] || SetJVars SetRootOpts ; [ X$ROOT != X/ ] && exec Chroot_Script $0 $* # # Find the StartStopCheck script # The $SC_INST_CONFIG_FILE variable, along with some other SC_* variables, # is exported by SetSunClusterEnv() defined in Subroutines. # SC_STARTSTOPCHECK_SCRIPT=`dirname $SC_INST_CONFIG_FILE`/Scripts/StartStopCheck [ -f $SC_STARTSTOPCHECK_SCRIPT ] || StartShell "Failed to find $SC_STARTSTOPCHECK_SCRIPT" # # Destination for Start/Stop/Check script whose full name will appear in # Start/Stop/Check properties of almost all cluster resources, # is refined in the text of sript itself. Source and eval it. # MyLocation="" eval `grep '^MyLocation=/' $SC_STARTSTOPCHECK_SCRIPT` [ x$MyLocation != x ] || StartShell "Failed to determine destination for $SC_STARTSTOPCHECK_SCRIPT" echo "\n\n\n\n\t=== Configuring IBM Middleware prerequisites ===\n\n\n" # # IBM preferes to name the node roles "active/passive", unlike # Sun, who preferes to name them primary/secondary. # We shall use both, no confusion expected. # case x$SC_NODE_TYPE in xPRIMARY) NODEROLE=active;; xSECONDARY) NODEROLE=passive;; *) "SC_NODE_TYPE not defined or wrong in cluster configuration" ;; esac # # Directory structure for cluster-shared middleware objects is quite tricky. # Some links cross one, some two directory levels. # Some start under MQHA, sume in the underlying levels. # Just be slow here. put StartShell here for debugging, copy-paste # from the very beginning, and see how the variables look and what's and where # is really created # MQHA_LINK=/MQHA MQHA_REAL_DIR=/global/MQHA STAGING_LINK=/opt/staging DIRS=" $MQHA_REAL_DIR/DB/db2inst1 $MQHA_REAL_DIR/MW1/MGENPH1GM1 $MQHA_REAL_DIR/MW1/MGENPH1BK1 $MQHA_REAL_DIR/MW2/MGENPH1GM2 $MQHA_REAL_DIR/MW2/MGENPH1BK2 " # # Mount points - the disk names are fake here so far, # and will be replaced later as hadware gets discovered # # The order is important, as we shall substitute # the disk_names in disk_size descending order, # i.e. the largest disk will substitute the very first DDD entry # MO=logging,nosuid,forcedirectio vfstab=" /dev/dsk/DDDs1 /dev/rdsk/DDDs1 $MQHA_REAL_DIR/DB ufs 3 no $MO /dev/dsk/DDDs1 /dev/rdsk/DDDs1 $MQHA_REAL_DIR/MW1 ufs 4 no $MO /dev/dsk/DDDs1 /dev/rdsk/DDDs1 $MQHA_REAL_DIR/MW2 ufs 4 no $MO " # # Users # passwd=" mqm:x:1005:100::/export/home/mqm:/bin/ksh wbiadmin:x:1117:100:MB User:/export/home/wbiadmin:/bin/ksh db2admin:x:1113:113::/export/home/db2admin:/usr/bin/ksh db2fenc1:x:1115:115::/export/home/db2fenc1:/usr/bin/sh db2inst1:x:1114:114::/export/home/db2inst1:/usr/bin/ksh " # # We must keep wbiadmin's password hash here. # The corresponding password for DB2 login is defined in IBM's # middleware media/config directories within $JS_MEDIA_DIR/Packages/IBM # shadow=" mqm:NoP:13377:::::: wbiadmin:mfreGHLN8.2vc:13377:::::: db2admin:NoP:13377:::::: db2fenc1:NoP:13377:::::: db2inst1:NoP:13377:::::: " group=" mqm::100:root,hollingl,acain dba::118:wbiadmin mqbrkrs::116:mqm,root,wbiadmin,db2inst1,db2fenc1,hollingl db2adm1::113:root,db2inst1,db2admin,wbiadmin db2fadm1::115:root,db2fenc1 db2grp1::114:db2adm1,db2admin " # # Add entries to real passwd, groups, shadow, # and create the home directories. # Remember, we are in chrooted environment here # for f in passwd shadow group ; do eval "echo \"\$$f\"" | egrep : | while read line ; do name=`echo $line | awk -F: '{print $1}'` egrep -s "^$name:" /etc/$f && continue echo $line >>/etc/$f [ $f = passwd ] && { homedir=`echo $line | awk -F: '{print $6}'` usergrp=`echo $line | awk -F: '{print $3":"$4}'` mkdir -p $homedir touch $homedir/.login $homedir/.profile chown -R $usergrp $homedir/. } done done # # Add commands to "wbiadmin" user's shell profile # to source some env info from "db2inst1" user's home. # That's why we can not "chmod 700" all these apps homes. # WBIHOME=`awk -F: '$1=="wbiadmin" {print $6}' /etc/passwd` [ x$WBIHOME = x ] && StartShell "No home dir for wbiadmin" egrep -s mqsiprofile $WBIHOME/.profile 2>/dev/null || echo "# . /opt/IBM/mqsi/6.0/bin/mqsiprofile . ~db2inst1/sqllib/db2profile echo + Currently configured components are: mqsilist #" >>$WBIHOME/.profile || StartShell "Failed to update $WBIHOME/.profile" chown wbiadmin:mqm $WBIHOME/.profile # # Yeah, relax all those guys home dirs modes, otherwise they won't find each other. # for i in `echo "$passwd" | awk -F: '{print $6}'`; do cd $i || StartShell "Failed to chdir to $i" while [ `pwd` != / ]; do chmod u=rwx,go=rx . ..; cd ..; done done # # Create the directory structure on local (non-shared) filesystems # cd / ln -s $MQHA_REAL_DIR/. $MQHA_LINK || StartShell "Failed to create $MQHA_LINK symlink" for i in $MQHA_REAL_DIR `echo "$vfstab" | awk '{print $3}'`; do mkdir -p $i || StartShell "\n\n\tCould not mkdir $i" done for i in $DIRS; do ln -s $i $MQHA_REAL_DIR/. || StartShell "\n\n\tFailed to create the sublink $i in $MQHA_REAL_DIR/." done # # Find free (not mounted or allocated or metadevices) disks, # add the vfstab entries and substitute the disk names # cp /etc/vfstab /etc/vfstab.pre-`basename $0` echo "$vfstab" | expand | sed '/^ *$/d;s/^ *//' >>/etc/vfstab touch /tmp/A.$$ for MP in `echo "$vfstab" | awk '{print $3}'`; do # # vfstab editing should be done on both nodes # FindFreeDisk # Sets LargestDiskName and LargestDiskSize, defined in Subroutines MPE=`echo $MP | sed 's:/:\\\/:g'` printf " g/ $MPE / s/\/DDDs/\/${LargestDiskName}s/g w q " | expand | sed 's/^ *//;/^ *$/d' | ed -s /etc/vfstab # # We need some handshaking method between the nodes, # for a primary node to signal that she's done with accessing # the shared disks, so the secondary is allowed to mount them. # # For this, we reserve cylinder #0, and start our filesystems # from cylinder #1 only # # Cylinder 0, offset 8192 will contain the full path to mount pont # for a relevant filesystem, terminated with "@" as soon as # the primary node unmounts it # [ x$SC_NODE_TYPE = xPRIMARY ] && { # # Slice the disk that in this loop is the largest unused disk, using fmthard. # We only need Slice 1, and we want to start it from Cylinder 1 (not 0!) till the disk end. # CSZ=`prtvtoc /dev/rdsk/${LargestDiskName}s2 | awk '$3=="sectors/cylinder" {print $2}'` CCN=`expr \( $LargestDiskSize / $CSZ - 1 \) \* $CSZ` echo " 0 0 00 0 0 1 0 00 $CSZ $CCN 2 5 01 0 $LargestDiskSize 3 0 00 0 0 4 0 00 0 0 5 0 00 0 0 6 0 00 0 0 7 0 00 0 0 " | sed '/^ *$/d' | fmthard -s - /dev/rdsk/${LargestDiskName}s2 || StartShell "Error formatting $LargestDiskName" # # Create a normal UFS filesystem on the disk just sliced. # It will turn global after reboot only, even though "global" option added to vfstab in this script. # echo y | newfs /dev/rdsk/${LargestDiskName}s1 || StartShell "Newfs of $LargestDiskName failed" # # To avoid confusion between character abd block devices, and line up at sector edge, # we use an intermediate file in /tmp/ for handshaking tokens. # First, test that disk is readable at all, then mark it. # dd if=/dev/rdsk/${LargestDiskName}s2 bs=1k skip=8 count=1 of=/tmp/A.$$ || StartShell "Failed to dd from $LargestDiskName" echo BusyBusyBusyBusyBusy@Busy | dd of=/tmp/A.$$ while true; do echo BusyBusyBusyBusy@; done | dd of=/tmp/A.$$ bs=1 count=1024 dd if=/tmp/A.$$ of=/dev/rdsk/${LargestDiskName}s2 bs=1k seek=8 count=1 mount $MP || StartShell "Failed to mount $MP - check the changes in vfstab" } [ x$SC_NODE_TYPE = xSECONDARY ] && { # # Check the handshaking token (containing the mount point's path) # that must have been put on this disk by a primary node in the very end of this script # Wait if it's not there, or if "Busy" token is there. No timeouts, secondary will wait forever # if the primary never does his job. # MP_IN=BusyBusyBusy while [ x$MP_IN != x$MP ]; do sleep 300 MP_IN=`dd if=/dev/rdsk/${LargestDiskName}s2 bs=1k skip=8 count=1 | strings | grep @ | head -1 | sed 's/@.*/'/` echo "`date`: Found hanshake label: $MP_IN, waiting for: $MP" done mount $MP || StartShell "Failed to mount $MP on $SC_NODE_TYPE node" } done #/looping on shared mountpoints echo "\n\n=== New vfstab entries:\n" diff /etc/vfstab.pre-`basename $0` /etc/vfstab [ x$SC_NODE_TYPE = xPRIMARY ] && { # # Create the directory structure # for i in $DIRS; do mkdir -p /$i/data /$i/log || StartShell "Failed to make subdirs under /$i" done chown -R mqm:mqm $MQHA_REAL_DIR/M*/. || StartShell "Failed to chown subdirs in $MQHA_REAL_DIR" chmod -R u=rwx,og=rx $MQHA_REAL_DIR/M*/. || StartShell "Failed to chmod subdirs in $MQHA_REAL_DIR" chown -R db2admin:db2grp1 $MQHA_REAL_DIR/D*/. || StartShell "Failed to chown subdirs in $MQHA_REAL_DIR" chmod -R ug=rwx,o=rx $MQHA_REAL_DIR/D*/. || StartShell "Failed to chmod subdirs in $MQHA_REAL_DIR" # # Copy the StartStopCheck script over to the shared media # As we don't have a separate LUN for administration CFS, # the StartStopCheck script will live on a DB LUN # mkdir -p $MQHA_REAL_DIR/DB/SC/Scripts || StartShell "Failed to create $MQHA_REAL_DIR/DB/SC/Scripts" cp $SC_STARTSTOPCHECK_SCRIPT $MQHA_REAL_DIR/DB/SC/Scripts/. || StartShell "Failed to copy $SC_STARTSTOPCHECK_SCRIPT to the shared area" chmod +x $MyLocation } mkdir -p `dirname $MyLocation` || StartShell "Failed to create the parent directory for $MyLocation" ln -s $MQHA_REAL_DIR/DB/SC/Scripts/`basename $SC_STARTSTOPCHECK_SCRIPT` $MyLocation || StartShell "Failed to link $MyLocation" echo "\n\n=== Installing IBM Middleware components ===\n" STAGING_DIR=$JS_PKGS_DIR/IBM_Middleware [ -f $STAGING_DIR/config/system ] || StartShell "No $STAGING_DIR/config/system file" cp /etc/system /etc/system.pre-`basename $0` KPARAMS=`awk '$1=="set" {print $2}' $STAGING_DIR/config/system | cut -d= -f1` # # Remove the previous occurances of the same parameter settings # echo Cleaning up /etc/system... for i in $KPARAMS; do echo "\tOverwriting $i" cp /etc/system /tmp/system.$$ expand /tmp/system.$$ | egrep -iv "^ *set *$i=|^ *set *$i " >/etc/system done cat $STAGING_DIR/config/system >>/etc/system ln -s $STAGING_DIR/. $STAGING_LINK || StartShell "Failed to link $STAGING_LINK" # # Copy the middleware install & configure scripts to local disks. # We need /root directory for this # [ -d /root/. ] || mkdir /root || StartShell "Failed to chdir/create /root" cd $STAGING_LINK/scripts || StartShell "No scripts directory in $STAGING_LINK" echo "\n\n\n\t\t=== Syncing scripts ===\n\n"; ./syncScripts.ksh echo "\n\n\n\t\t=== Installing WMQ ===\n\n"; ./wmq_install.ksh echo "\n\n\n\t\t=== Installing WMB ===\n\n"; ./wmb_install.ksh echo "\n\n\n\t\t=== Installing DB2 ===\n\n"; ./db2_server_install.ksh # SC_Append_Hosts # # For MW components to the DB at istallation time, # we need a valid and active (up) IP address. # The failover address is not available at installation time, # so we set it to $SC_PRIMARY_NODE_ADDR for the installation time, # and change back to a failover address as soon as middleware is shut down here. # [ x$SC_PRIMARY_NODE_ADDR != x ] || StartShell "Could not resolve $SC_PRIMARY_NODE_NAME via $SC_HOSTS_FILE" NGDBNAME=ngdbnode NGDBADDR=`awk '$0~/^[1-9][1-9.]*.*'$NGDBNAME'/ {print $1}' /etc/hosts` [ x$NGDBADDR != x ] || StartShell "Could not resolve $NGDBNAME via /etc/hosts" cp /etc/hosts /etc/hosts.pre-MW printf "g/^$NGDBADDR.*$NGDBNAME/\ns/^$NGDBADDR/$SC_PRIMARY_NODE_ADDR/\nw\nq\n" | ed -s /etc/hosts echo diff /etc/hosts.pre-MW /etc/hosts echo "\n\n=== Configuring the installed middleware for $NODEROLE node ===\n" cd /root/. || StartShell "No /root/. directoty found" echo "\n\n\n\t\t=== Configuring DB2 ===\n\n"; ./createDBenvironment.ksh $NODEROLE [ x$SC_NODE_TYPE = xSECONDARY ] && { # # IMPORTANT!! # # Since MQ and (maybe) MB config scripts from IBM make decision about node role, # not only based on ARG1, but also on the fact that /MQHA/* are present or not, # we must umount the $MQHA_REAL_DIR here for "passive" node. # # It has been previosly mounted, in order to satisfy DB2 config on "passive" # Lee Holingdale will eventually change the IBM install scripts to avoid this mess. # for MP in `echo "$vfstab" | awk '{print $3}'`; do /sbin/mount | awk '{print $1}' | grep "^$MP$" && { umount $MP || StartShell "Failed to umount $MP"; } done } echo "\n\n\n\t\t=== Configuring WMQ ===\n\n"; ./createMQenvironment.ksh $NODEROLE echo "\n\n\n\t\t=== Configuring WMB ===\n\n"; ./createMBenvironment.ksh $NODEROLE [ x$SC_NODE_TYPE = xPRIMARY ] && { echo "\n\n\n\t\t=== Creating MQ objects ===\n\n"; su - mqm ./createMQobjects.ksh } # # # # # # # # # # # # # # # # # We must install and configure Oracle here, as it also decides # whether it's a primary or secondary node, depending on # whether filesystems are mounted or not # echo "\n\n\t===== Installing Oracle Client =====\n" PKGDIR=$JS_MEDIA_DIR/Packages/Oracle/10g/client PKGLIST=" Oracle-sparc-Solaris9 " MakeAdminFile for PKG in $PKGLIST; do pkginfo -d $PKGDIR $PKG | egrep -s $PKG || StartShell "Package $PKG not found in $PKGDIR" pkgadd -nM -a $PKGADMIN_FILE $ROOTOPTS -d $PKGDIR $PKG 2>&1 | grep "Installation of" || StartShell "Installation failed" done cd $STAGING_LINK/scripts || StartShell "No scripts directory in $STAGING_LINK" echo "\n\n\n\t=== Configuring Oracle client ===\n\n"; ./oracle_setup.ksh $NODEROLE # # Source oracle config from the environ # set -x [ -f $JS_HOST_ENV_FILE ] && . $JS_HOST_ENV_FILE [ x$ORA_TNSNAMES_FILE != x ] && echo "$ORA_TNSNAMES_DATA" | egrep -is PORT && echo "$ORA_TNSNAMES_DATA" >$ORA_TNSNAMES_FILE ORA_OWNER=`ls -ld \`dirname $ORA_TNSNAMES_FILE\` | awk '{print $3":"$4}'` chown $ORA_OWNER $ORA_TNSNAMES_FILE || StartShell "Failed to chown $ORA_TNSNAMES_FILE to $ORA_OWNER" WBIADMIN_HOME=`awk -F: '$1=="wbiadmin" {print $6}' /etc/passwd` ORACLE_HOME=`echo $ORA_TNSNAMES_FILE | sed 's:/client/.*$:/client:'` echo "### ORACLE_HOME=$ORACLE_HOME PATH=\$PATH:\$ORACLE_HOME/bin LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib32 export ORACLE_HOME export PATH export LD_LIBRARY_PATH ###" >>$WBIADMIN_HOME/.profile db2inst1_home=`awk -F: '$1=="db2inst1" {print $6}' /etc/passwd` [ x$db2inst1_home = x ] && StartShell "Wrong home for user db2inst1" find /opt/IBM/. $db2inst1_home/. -type f | egrep '/db2ckpw$|/db2aud$' | xargs chown root || StartShell "Failed to chown" find /opt/IBM/. $db2inst1_home/. -type f | egrep '/db2ckpw$|/db2aud$' | xargs chmod 4511 || StartShell "Failed to chmod" find /opt/IBM/. $db2inst1_home/. -type f | egrep '/db2audit.cfg$' | xargs chmod 644 || StartShell "Failed to chmod" find /opt/IBM/. $db2inst1_home/. | egrep '/db2flacc$' | xargs chmod 2511 || StartShell "Failed to chmod" set +x # # # # # # # # # # # # # # # # echo "\n\n\n\t=== Waiting for MW components to complete the bootstrap ===\n"; sleep 15 echo "\n\n\n\t=== Stopping the MW components ===\n\n" RUNNING_MQBROKERS=`ps -eflo user,args | awk '$1=="wbiadmin" && $2~/bipservice/ {print $3}' | sort -u` [ `echo $RUNNING_MQBROKERS | wc -w` -gt 0 ] && su - wbiadmin -c " /bin/sh -c \"for m in `echo $RUNNING_MQBROKERS`; do mqsistop \\\$m; sleep 5; done\" " RUNNING_MQMGRS=`ps -eflo user,args | awk '$1=="mqm" && $3=="-m" {print $4}' | sort -u` [ `echo $RUNNING_MQMGRS | wc -w` -gt 0 ] && su - mqm -c " /bin/ksh -c \" cd . ./environment.ksh for m in `echo $RUNNING_MQMGRS`; do endmqm -w \\\$m; sleep 5; done \" " su - db2inst1 -c db2stop echo "\n\n\n\t=== Waiting for MW components to complete the shutdown ===\n"; sleep 15 [ `ps -eflo user= | awk '$1!="root"' | wc -l` -gt 0 ] && StartShell "\n\n\n\t\tLeftover processes persist\n\n" # # Put the original NGDB address back to /etc/hosts # cp /etc/hosts /etc/hosts.post-MW printf "g/^$SC_PRIMARY_NODE_ADDR.*$NGDBNAME/\ns/^$SC_PRIMARY_NODE_ADDR/$NGDBADDR/\nw\nq\n" | ed -s /etc/hosts echo diff /etc/hosts.post-MW /etc/hosts echo === Unmounting shared filesystems === cd / for MP in `echo "$vfstab" | awk '{print $3}'`; do /sbin/mount | awk '{print $1}' | grep "^$MP$" && { umount $MP || StartShell "Failed to umount $MP"; } [ x$SC_NODE_TYPE = xPRIMARY ] && { # # Release the disk and make it available for use by the secondary node, # putting the mountpoint path, instead of "BysyBusy..." token # CurrentDiskName=`awk '$3=="'$MP'" {print $1}' /etc/vfstab | awk -F/ '{print $NF}' | awk -Fs '{print $1}'` while true; do echo ${MP}@; done | dd of=/tmp/A.$$ bs=1 count=1024 dd if=/tmp/A.$$ of=/dev/rdsk/${CurrentDiskName}s2 bs=1k seek=8 count=1 } done