Раздавать SCSI-ID - хостадаптерам старшие (7,6,5...)
ДИскам - поменьше, в порядке убывания приоритета (2,1,15,14,13...)


Название группы: vg[порядковый номер группы][номер стартового узла]
Минор - совпадающий с названием. 0x0[номер группы][номер узла]000
первый разряд - обязан быть 0, второй - у всех должен быть разным

mkdir /dev/vg31
mknod /dev/vg31/group c 64 0x031000
vgcreate /dev/vg31/group /dev/dsk/c1t8d0 /dev/dsk/c1t9d0

Экспорт группы на другой узел кластера

vhchange -a n /dev/vg31 # Отключить, иначе не экспортирует
vgexport -s -p -m /tmp/vg31 /dev/vg31
  -s - группа будет shared
  -p - preview (оставить оригинал на мете)
  -m mapfile
rcp /tmp/vg31 node2:/tmp/vg31
rlogin node2
mkdir /dev/vg31
mknod /dev/vg31/group c 64 0x031000
vgimport -s -m /tmp/vg31 /dev/vg31

vgchange -c y /dev/vg31 # Отдать кластеру
vhchange -a e /dev/vg31 # Активировать vg монопольно
vhchange -a n /dev/vg31 # Отключить

vgchange -c n /dev/vg31 # Забрать у кластера
vhchange -a y /dev/vg31 # Активировать vg немонопольно


Komandy:

/usr/sbin/cm*

Generaciya konfigura

cd /etc/cmcluster

Wpisat' spisok uzlow w fajl
/etc/cmcluster/cmclnodelist
mos032
mos034


klaster
nodes
packages
services - programma, za nalichiem kotoroj klaster sledit.
Perezapuskaet, skol'ko zakazano raz, esli ona umerla -
paketu delaetsya halt, i on restartuetsya na nowom uzle.
Esli w washem pakete net programm, kotorye startuyut w foregraunde,
nado napisat' programmku monitor - kotoraya sama za nimi sledit,

i swom okonchaniembudet goworit' klasteru - paket nado gasit'



/usr/sbin/cmquerycl -C jj -n mos032 -n mos034

# **********************************************************************
# ********* HIGH AVAILABILITY CLUSTER CONFIGURATION FILE ***************
# ***** For complete details about cluster parameters and how to    ****
# ***** set them, consult the cmquerycl(1m) manpage or your manual. ****
# **********************************************************************

# Enter a name for this cluster.  This name will be used to identify the
# cluster when viewing or manipulating it.

CLUSTER_NAME		cluster1


# Cluster Lock Device Parameters.  This is the volume group that
# holds the cluster lock which is used to break a cluster formation
# tie.  This volume group should not be used by any other cluster
# as cluster lock device.

FIRST_CLUSTER_LOCK_VG		/dev/vg03


# Definition of nodes in the cluster.
# Repeat node definitions as necessary for additional nodes.

NODE_NAME		mos032
  NETWORK_INTERFACE	lan0
    HEARTBEAT_IP		15.188.208.32
  NETWORK_INTERFACE	lan1
  FIRST_CLUSTER_LOCK_PV	/dev/dsk/c1t9d0
# List of serial device file names
# For example:
# SERIAL_DEVICE_FILE	/dev/tty0p0

# Possible standby Network Interfaces for lan0: lan1.

NODE_NAME		mos034
  NETWORK_INTERFACE	lan0
    HEARTBEAT_IP		15.188.208.34
  NETWORK_INTERFACE	lan1
  FIRST_CLUSTER_LOCK_PV	/dev/dsk/c0t9d0
# List of serial device file names
# For example:
# SERIAL_DEVICE_FILE	/dev/tty0p0

# Possible standby Network Interfaces for lan0: lan1.


# Cluster Timing Parmeters (microseconds).

HEARTBEAT_INTERVAL		1000000
NODE_TIMEOUT		2000000


# Configuration/Reconfiguration Timing Parameters (microseconds).

AUTO_START_TIMEOUT	600000000
NETWORK_POLLING_INTERVAL	2000000

# Package Configuration Parameters.
# Enter the maximum number of packages which will be configured in the cluster.
# You can not add packages beyond this limit.
# This parameter is required.
MAX_CONFIGURED_PACKAGES		0



# List of cluster aware Volume Groups. These volume groups will
# be used by package applications via the vgchange -a e command.
# For example:
# VOLUME_GROUP		/dev/vgdatabase.
# VOLUME_GROUP		/dev/vg02.

VOLUME_GROUP		/dev/vg03




cmmakepkg -s paket1.sh
cmmakepkg -p paket1.conf


# **********************************************************************
# ****** HIGH AVAILABILITY PACKAGE CONFIGURATION FILE (template) *******
# **********************************************************************
# ******* Note: This file MUST be edited before it can be used. ********
# * For complete details about package parameters and how to set them, *
# * consult the MC/ServiceGuard or MC/LockManager manpages or manuals. *
# **********************************************************************

# Enter a name for this package.  This name will be used to identify the
# package when viewing or manipulating it.  It must be different from
# the other configured package names.

PACKAGE_NAME


# Enter the failover policy for this package. This policy will be used
# to select an adoptive node whenever the package needs to be started.
# The default policy unless otherwise specified is CONFIGURED_NODE.
# This policy will select nodes in priority order from the list of
# NODE_NAME entries specified below.
#
# The alternative policy is MIN_PACKAGE_NODE. This policy will select
# the node, from the list of NODE_NAME entries below, which is
# running the least number of packages at the time this package needs
# to start.

FAILOVER_POLICY			CONFIGURED_NODE


# Enter the failback policy for this package. This policy will be used
# to determine what action to take when a package is not running on
# its primary node and its primary node is capable of running the
# package. The default policy unless otherwise specified is MANUAL.
# The MANUAL policy means no attempt will be made to move the package
# back to its primary node when it is running on an adoptive node.
#
# The alternative policy is AUTOMATIC. This policy will attempt to
# move the package back to its primary node whenever the primary node
# is capable of running the package.

FAILBACK_POLICY			MANUAL


# Enter the names of the nodes configured for this package.  Repeat
# this line as necessary for additional adoptive nodes.
# Order IS relevant.  Put the second Adoptive Node AFTER the first
# one.
# Example : NODE_NAME  original_node
#           NODE_NAME  adoptive_node

NODE_NAME


# Enter the complete path for the run and halt scripts.  In most cases
# the run script and halt script specified here will be the same script,
# the package control script generated by the cmmakepkg command.  This
# control script handles the run(ning) and halt(ing) of the package.
# If the script has not completed by the specified timeout value,
# it will be terminated.  The default for each script timeout is
# NO_TIMEOUT.  Adjust the timeouts as necessary to permit full
# execution of each script.
# Note: The HALT_SCRIPT_TIMEOUT should be greater than the sum of
# all SERVICE_HALT_TIMEOUT specified for all services.

RUN_SCRIPT
RUN_SCRIPT_TIMEOUT		NO_TIMEOUT
HALT_SCRIPT
HALT_SCRIPT_TIMEOUT		NO_TIMEOUT


# Enter the SERVICE_NAME, the SERVICE_FAIL_FAST_ENABLED and the
# SERVICE_HALT_TIMEOUT values for this package.  Repeat these
# three lines as necessary for additional service names.  All
# service names MUST correspond to the service names used by
# cmrunserv and cmhaltserv commands in the run and halt scripts.
#
# The value for SERVICE_FAIL_FAST_ENABLED can be either YES or
# NO.  If set to YES, in the event of a service failure, the
# cluster software will halt the node on which the service is
# running.  If SERVICE_FAIL_FAST_ENABLED is not specified, the
# default will be NO.
#
# SERVICE_HALT_TIMEOUT is represented in the number of seconds.
# This timeout is used to determine the length of time (in
# seconds) the cluster software will wait for the service to
# halt before a SIGKILL signal is sent to force the termination
# of the service.  In the event of a service halt, the cluster
# software will first send a SIGTERM signal to terminate the
# service.  If the service does not halt, after waiting for the
# specified SERVICE_HALT_TIMEOUT, the cluster software will send
# out the SIGKILL signal to the service to force its termination.
# This timeout value should be large enough to allow all cleanup
# processes associated with the service to complete.  If the
# SERVICE_HALT_TIMEOUT is not specified, a zero timeout will be
# assumed, meaning the cluster software will not wait at all
# before sending the SIGKILL signal to halt the service.
#
# Example: SERVICE_NAME                   DB_SERVICE
#          SERVICE_FAIL_FAST_ENABLED      NO
#          SERVICE_HALT_TIMEOUT           300
#
# To configure a service, uncomment the following lines and
# fill in the values for all of the keywords.
#
#SERVICE_NAME                   
#SERVICE_FAIL_FAST_ENABLED      
#SERVICE_HALT_TIMEOUT           


# Enter the network subnet name that is to be monitored for this package.
# Repeat this line as necessary for additional subnet names.  If any of
# the subnets defined goes down, the package will be switched to another
# node that is configured for this package and has all the defined subnets
# available.

#SUBNET


# The following keywords (RESOURCE_NAME, RESOURCE_POLLING_INTERVAL, and
# RESOURCE_UP_VALUE) are used to specify Package Resource Dependencies.  To
# define a Package Resource Dependency, a RESOURCE_NAME line with a fully
# qualified resource path name, and one or more RESOURCE_UP_VALUE lines are
# required.  A RESOURCE_POLLING_INTERVAL line (how often in seconds the resource
# is to be monitored) is optional and defaults to 60 seconds.  An operator and
# a value are used with RESOURCE_UP_VALUE to define when the resource is to be
# considered up.  The operators are =, !=, >, <, >=, and <=, depending on the
# type of value.  Values can be string or numeric.  If the type is string, then
# only = and != are valid operators.  If the string contains whitespace, it
# must be enclosed in quotes.  String values are case sensitive.  For example,
#
# 					Resource is up when its value is
# 					--------------------------------
# 	RESOURCE_UP_VALUE	= UP			"UP"
# 	RESOURCE_UP_VALUE	!= DOWN			Any value except "DOWN"
# 	RESOURCE_UP_VALUE	= "On Course"		"On Course"
#
# If the type is numeric, then it can specify a threshold, or a range to
# define a resource up condition.  If it is a threshold, then any operator
# may be used.  If a range is to be specified, then only > or >= may be used
# for the first operator, and only < or <= may be used for the second operator.
# For example,
# 					Resource is up when its value is
# 					--------------------------------
# 	RESOURCE_UP_VALUE     = 5		5		    (threshold)
# 	RESOURCE_UP_VALUE     > 5.1		greater than 5.1    (threshold)
# 	RESOURCE_UP_VALUE     > -5 and < 10	between -5 and 10   (range)
#
# Note that "and" is required between the lower limit and upper limit
# when specifying a range.  The upper limit must be greater than the lower
# limit.  If RESOURCE_UP_VALUE is repeated within a RESOURCE_NAME block, then
# they are inclusively OR'd together.  Package Resource Dependencies may be
# defined by repeating the entire RESOURCE_NAME block.
#
# Example : RESOURCE_NAME               /net/interfaces/lan/status/lan0
# 	    RESOURCE_POLLING_INTERVAL	120
# 	    RESOURCE_UP_VALUE		= RUNNING
# 	    RESOURCE_UP_VALUE		= ONLINE
#
#           Means that the value of resource /net/interfaces/lan/status/lan0
#           will be checked every 120 seconds, and is considered to
#           be 'up' when its value is "RUNNING" or "ONLINE".
#
# Uncomment the following lines to specify Package Resource Dependencies.
#
#RESOURCE_NAME		    
#RESOURCE_POLLING_INTERVAL  
#RESOURCE_UP_VALUE	      [and  ]


# The default for PKG_SWITCHING_ENABLED is YES. In the event of a
# failure, this permits the cluster software to transfer the package
# to an adoptive node.  Adjust as necessary.

PKG_SWITCHING_ENABLED		YES


# The default for NET_SWITCHING_ENABLED is YES.  In the event of a
# failure, this permits the cluster software to switch LANs locally
# (transfer to a standby LAN card).  Adjust as necessary.

NET_SWITCHING_ENABLED		YES


# The default for NODE_FAIL_FAST_ENABLED is NO.  If set to YES,
# in the event of a failure, the cluster software will halt the node
# on which the package is running.  Adjust as necessary.

NODE_FAIL_FAST_ENABLED	NO

cmcheckconf -C jj -P paket1.conf -P paket2.conf

Sozdanie gologo klastera

cmaplyconf -C jj
cmruncl
cmview -v
cmhaltnode mos032
cmrunnode mos032
cmhaltcl

Dobawlenie ili modifikaciya imeyushegosya paketa
cmcheckconf -P paket1.conf
cmaplyconf -P paket1.conf

Ah, da, wse skripty obyazatel'no kopirowat' po wsem uzlam klastera

cmhaltpkg paket1

posle ostanowki paket awtomaticheski disablitsq na uzle, de on umer,
dlq obratnogo enablirowaniq paketa:

cmmodpkg -e paket1
cmmodpkg -n mos032 -e paket1
cmmodpkg -n mos034 -e paket1

cmrunpkg  [ -n mos032 ] paket1


Prosmotr statusa klastera


CLUSTER      STATUS
karelia      up

  NODE         STATUS       STATE
  mos031       up           running

    Network_Parameters:
    INTERFACE    STATUS       PATH         NAME
    PRIMARY      up           8/16/6       lan0
    STANDBY      up           8/20/5/8     lan1

    PACKAGE      STATUS       STATE        PKG_SWITCH   NODE
    pkg28162     up           running      enabled      mos031

      Policy_Parameters:
      POLICY_NAME     CONFIGURED_VALUE
      Failover        configured_node
      Failback        automatic

      Script_Parameters:
      ITEM       STATUS   MAX_RESTARTS  RESTARTS   NAME
      Service    up                  3         0   qwerty
      Subnet     up                                15.188.208.0
      Resource   up                                /system/filesystem/availMb/home
      Resource   up                                /cluster/localNode/status/karelia

      Node_Switching_Parameters:
      NODE_TYPE    STATUS       SWITCHING    NAME
      Primary      up           enabled      mos031       (current)
      Alternate    up           enabled      mos033

  NODE         STATUS       STATE
  mos033       up           running

    Network_Parameters:
    INTERFACE    STATUS       PATH         NAME
    PRIMARY      up           8/16/6       lan0
    STANDBY      up           8/20/5/8     lan1

    PACKAGE      STATUS       STATE        PKG_SWITCH   NODE
    nc           starting     starting     enabled      mos033

      Policy_Parameters:
      POLICY_NAME     CONFIGURED_VALUE
      Failover        configured_node
      Failback        automatic

      Script_Parameters:
      ITEM       STATUS   MAX_RESTARTS  RESTARTS   NAME
      Service    up                  0         0   nc
      Subnet     up                                15.188.208.0
      Resource   up                                /system/filesystem/availMb/home

      Node_Switching_Parameters:
      NODE_TYPE    STATUS       SWITCHING    NAME
      Primary      up           enabled      mos033       (current)
      Alternate    up           enabled      mos031

udalenie paketa

cmdeleteconf -P paket2

/usr/sbin/cmapplyconf   /usr/sbin/cmhaltserv    /usr/sbin/cmrunnode
/usr/sbin/cmcheckconf   /usr/sbin/cmmakepkg     /usr/sbin/cmrunpkg
/usr/sbin/cmdeleteconf  /usr/sbin/cmmigrate     /usr/sbin/cmrunserv
/usr/sbin/cmgetconf     /usr/sbin/cmmodnet      /usr/sbin/cmscancl
/usr/sbin/cmhaltcl      /usr/sbin/cmmodpkg      /usr/sbin/cmviewcl
/usr/sbin/cmhaltnode    /usr/sbin/cmquerycl     /usr/sbin/cmviewconf
/usr/sbin/cmhaltpkg     /usr/sbin/cmruncl

Prosmotr debaga

tail -f /var/adm/syslog/syslog.log

tail -f /etc/cmcluster/paket1.sh.log


Obrashenie s resursami:

Prosmotret' spiski dostupnyh resursow
resls /net/interfaces/lan/status

prosmotret' ih znachenie ya ne znayu kak

poluchit' nastoyashie konfigurniki iz klastera

cmgetconf  -c cluster_name output_filename
cmgetconf  -p package_name output_filename
#"(#) A.11.05         $Revision: 82.3 $ $Date: 98/11/03 10:56:49 $"
# **********************************************************************
# *                                                                    *
# *        HIGH AVAILABILITY PACKAGE CONTROL SCRIPT (template)         *
# *                                                                    *
# *       Note: This file MUST be edited before it can be used.        *
# *                                                                    *
# **********************************************************************

# UNCOMMENT the variables as you set them.

# Set PATH to reference the appropriate directories.
PATH=/sbin:/usr/bin:/usr/sbin:/etc:/bin

# VOLUME GROUP ACTIVATION:
# Specify the method of activation for volume groups.
# Leave the default ("VGCHANGE="vgchange -a e") if you want volume
# groups activated in exclusive mode. This assumes the volume groups have
# been initialized with 'vgchange -c y' at the time of creation.
#
# Uncomment the first line (VGCHANGE="vgchange -a e -q n"), and comment
# out the default, if your disks are mirrored on separate physical paths,
#
# Uncomment the second line (VGCHANGE="vgchange -a e -q n -s"), and comment
# out the default, if your disks are mirrored on separate physical paths,
# and you want the mirror resynchronization to ocurr in parallel with
# the package startup.
#
# Uncomment the third line (VGCHANGE="vgchange -a y") if you wish to
# use non-exclusive activation mode. Single node cluster configurations
# must use non-exclusive activation.
#
# VGCHANGE="vgchange -a e -q n"
# VGCHANGE="vgchange -a e -q n -s"
# VGCHANGE="vgchange -a y"
VGCHANGE="vgchange -a e"		# Default

# VOLUME GROUPS
# Specify which volume groups are used by this package. Uncomment VG[0]=""
# and fill in the name of your first volume group. You must begin with
# VG[0], and increment the list in sequence.
#
# For example, if this package uses your volume groups vg01 and vg02, enter:
#         VG[0]=vg01
#         VG[1]=vg02
#
# The volume group activation method is defined above. The filesystems
# associated with these volume groups are specified below.
#
#VG[0]=""

# FILESYSTEMS
# Specify the filesystems which are used by this package. Uncomment
# LV[0]=""; FS[0]=""; FS_MOUNT_OPT[0]="" and fill in the name of your first
# logical volume, filesystem and mount option for the file system. You must
# begin with LV[0], FS[0] and FS_MOUNT_OPT[0] and increment the list in
# sequence.
#
# For example, if this package uses the file systems pkg1a and pkg1b,
# which are mounted on the logical volumes lvol1 and lvol2 with read and
# write options enter:
#          LV[0]=/dev/vg01/lvol1; FS[0]=/pkg1a; FS_MOUNT_OPT[0]="-o rw"
#          LV[1]=/dev/vg01/lvol2; FS[1]=/pkg1b; FS_MOUNT_OPT[1]="-o rw"
#
# The filesystems are defined as triplets of entries specifying the logical
# volume, the mount point and the mount options for the file system. Each
# filesystem will be fsck'd prior to being mounted. The filesystems will be
# mounted in the order specified during package startup and will be unmounted
# in reverse order during package shutdown. Ensure that volume groups
# referenced by the logical volume definitions below are included in
# volume group definitions above.
#
#LV[0]=""; FS[0]=""; FS_MOUNT_OPT[0]=""

# FILESYSTEM UNMOUNT COUNT
# Specify the number of unmount attempts for each filesystem during package
# shutdown.  The default is set to 1.
LV_UMOUNT_COUNT=1

# IP ADDRESSES
# Specify the IP and Subnet address pairs which are used by this package.
# Uncomment IP[0]="" and SUBNET[0]="" and fill in the name of your first
# IP and subnet address. You must begin with IP[0] and SUBNET[0] and
# increment the list in sequence.
#
# For example, if this package uses an IP of 192.10.25.12 and a subnet of
# 192.10.25.0 enter:
#          IP[0]=192.10.25.12
#          SUBNET[0]=192.10.25.0 # (netmask=255.255.255.0)
#
# Hint: Run "netstat -i" to see the available subnets in the Network field.
#
# IP/Subnet address pairs for each IP address you want to add to a subnet
# interface card.  Must be set in pairs, even for IP addresses on the same
# subnet.
#
#IP[0]=""
#SUBNET[0]=""

# SERVICE NAMES AND COMMANDS.
# Specify the service name, command, and restart parameters which are
# used by this package. Uncomment SERVICE_NAME[0]="", SERVICE_CMD[0]="",
# SERVICE_RESTART[0]="" and fill in the name of the first service, command,
# and restart parameters. You must begin with SERVICE_NAME[0], SERVICE_CMD[0],
# and SERVICE_RESTART[0] and increment the list in sequence.
#
# For example:
#          SERVICE_NAME[0]=pkg1a
#          SERVICE_CMD[0]="/usr/bin/X11/xclock -display 192.10.25.54:0"
#          SERVICE_RESTART[0]=""  # Will not restart the service.
#
#          SERVICE_NAME[1]=pkg1b
#          SERVICE_CMD[1]="/usr/bin/X11/xload -display 192.10.25.54:0"
#          SERVICE_RESTART[1]="-r 2"   # Will restart the service twice.
#
#          SERVICE_NAME[2]=pkg1c
#          SERVICE_CMD[2]="/usr/sbin/ping"
#          SERVICE_RESTART[2]="-R" # Will restart the service an infinite
#                                    number of times.
#
# Note: No environmental variables will be passed to the command, this
# includes the PATH variable. Absolute path names are required for the
# service command definition.  Default shell is /usr/bin/sh.
#
#SERVICE_NAME[0]=""
#SERVICE_CMD[0]=""
#SERVICE_RESTART[0]=""

# DTC manager information for each DTC.
# Example: DTC[0]=dtc_20
#DTC_NAME[0]=


# START OF CUSTOMER DEFINED FUNCTIONS

# This function is a place holder for customer define functions.
# You should define all actions you want to happen here, before the service is
# started.  You can create as many functions as you need.

function customer_defined_run_cmds
{
# ADD customer defined run commands.
: # do nothing instruction, because a function must contain some command.

	test_return 51
}

# This function is a place holder for customer define functions.
# You should define all actions you want to happen here, before the service is
# halted.

function customer_defined_halt_cmds
{
# ADD customer defined halt commands.
: # do nothing instruction, because a function must contain some command.
	test_return 52
}

# END OF CUSTOMER DEFINED FUNCTIONS


# START OF RUN FUNCTIONS


function activate_volume_group
{
for I in ${VG[@]}
do
	if [[ "${VGCHANGE}" = "vgchange -a y" ]]
	then
        	print "$(date '+%b %e %X') - Node \"$(hostname)\": Activating volume group $I with non-exclusive option."
	else
        	print "$(date '+%b %e %X') - \"$(hostname)\": Activating volume group $I with exclusive option."
	fi

	$VGCHANGE $I
	test_return 1

	# If the -s option has been specified, then we perform
	# the resynchronization as a background task
	#
	if [[ ${VGCHANGE#*-s} != ${VGCHANGE} ]]
	then
	    {
		if /sbin/vgsync $I
		then
		    print "$(date '+%b %e %X') - Node \"$(hostname)\": Resynchronized volume group $I"
		else
		    print "$(date '+%b %e %X') - Node \"$(hostname)\": Resynchronization of volume group $I encountered an error"
		fi
	    } &
	fi
done
}

# For each {file system/logical volume} pair, fsck the file system
# and mount it.

function check_and_mount
{
integer R=0

for I in ${LV[@]}
do
	if [[ $(mount -p | awk '$1 == "'$I'"') = "" ]]
	then
		RLV[$R]="${I%/*}/r${I##*/}"

            	if [ -x /usr/sbin/fstyp ]
            	then
               		fstype[$R]=$(fstyp $I)
		fi
		(( R = $R + 1 ))
	fi
done

# Verify that there is at least one file system to check and what type.
if [[ ${RLV[@]} != "" ]]
then
	print -n "$(date '+%b %e %X') - Node \"$(hostname)\": "
	print "Checking filesystems:"
	print ${LV[@]} | tr ' ' '\012' | sed -e 's/^/   /'

	# If there is more than one filesystem type being checked
	# then each filesystem is check individually.
	#
	R=$(print ${fstype[*]} | tr ' ' '\012' | sort -u | wc -l)
	if (( R > 1 ))
	then
	    R=0
	    while (( R < ${#RLV[*]} ))
	    do
		case ${fstype[$R]} in

		    hfs)	fsck -F hfs -P ${RLV[$R]}
				test_return 2
				;;

		    vxfs)	fsck -F vxfs -y ${RLV[$R]}
				test_return 2
				;;

		    unk*)	fsck ${RLV[$R]}
				test_return 2
				;;

		    *)		if [[ ${fstype[$R]} = "" ]]
				then
				    fsck ${RLV[$R]}
				else
				    fsck -F ${fstype[$R]} ${RLV[$R]}
				fi
				test_return 2
				;;
		esac
		(( R = R + 1 ))
	    done

	# If there is only one filesystem type being checked, then
	# multiple invocations of fsck can be avoided. All filesystems
	# are specified on the command line to one fsck invocation.
	#
	else
	    case ${fstype} in

		hfs)	fsck -F hfs -P ${RLV[@]}
			test_return 2
			;;

		vxfs)	fsck -F vxfs -y ${RLV[@]}
			test_return 2
			;;

		unk*)	fsck ${RLV[@]}
			test_return 2
			;;

		*)	if [[ ${fstype} = "" ]]
			then
			    fsck ${RLV[@]}
			else
			    fsck -F ${fstype} ${RLV[@]}
			fi
			test_return 2
			;;
	    esac
	fi
fi

integer F=0
for I in ${LV[@]}
do
	if [[ $(mount | grep -e $I" ") = "" ]]
	then
		print "$(date '+%b %e %X') - Node \"$(hostname)\": Mounting $I at ${FS[$F]}"
		mount ${FS_MOUNT_OPT[$F]} $I ${FS[$F]}
		test_return 3
	else
		print "$(date '+%b %e %X') - Node \"$(hostname)\": WARNING:  File system \"${FS[$F]}\" was already mounted."
	fi
	(( F = $F + 1 ))
done
}

# For each {IP address/subnet} pair, add the IP address to the subnet
# using cmmodnet(1m).

function add_ip_address
{
integer S=0
integer error=0

for I in ${IP[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Adding IP address $I to subnet ${SUBNET[$S]}"
	XX=$( cmmodnet -a -i $I ${SUBNET[$S]} 2>&1 )
	if (( $? != 0 ))
	then
                if [[ $(echo $XX | grep "heartbeat IP") != "" ]]
                then
                        # IP has been configured as a heartbeat IP address.
                        print "$XX" >> $0.log
                        (( error = 1 ))
                else
                        YY=$( netstat -in | awk '$4 == "'${I}'"')
                        if [[ -z $YY ]]
                        then
                                print "$XX" >> $0.log
                                print "\tERROR:  Failed to add IP $I to subnet ${SUBNET[$S]}"
                                (( error = 1 ))
                        else
                                print "\tWARNING:  IP $I is already configured on the subnet ${SUBNET[$S]}"
                        fi
                fi
	fi
	(( S = $S + 1 ))
done

if (( error != 0 ))
then

# `let 0` is used to set the value of $? to 1. The function test_return
# requires $? to be set to 1 if it has to print error message.

        let 0
        test_return 4
fi

}

# Own and reset the DTC connections

function get_ownership_dtc
{
for I in ${DTC_NAME[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Assigning Ownership of the DTC $I"
	dtcmodifyconfs -o $I
	test_return 5

	for J in ${IP[@]}
	do
		print "$(date '+%b %e %X') - Node \"$(hostname)\": Resetting the DTC connections to IP address $J"
		dtcdiag -Q $J -q -f $I
		test_return 6
	done
done
}


# For each {service name/service command string} pair, start the
# service command string at the service name using cmrunserv(1m).

function start_services
{
integer C=0
for I in ${SERVICE_NAME[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Starting service $I using"
	print "   \"${SERVICE_CMD[$C]}\""
            #
            # Check if cmrunserv should be called the old
            # way without a restart count.
            #
	if [[ "${SERVICE_RESTART[$C]}" = "" ]]
	then
	    cmrunserv $I ">> $0.log 2>&1 ${SERVICE_CMD[$C]}"
	else
	    cmrunserv ${SERVICE_RESTART[$C]} $I ">> $0.log 2>&1 ${SERVICE_CMD[$C]}"
	fi
	test_return 8
	(( C = $C + 1 ))
done
}

# END OF RUN FUNCTIONS.



# START OF HALT FUNCTIONS

# Halt each service using cmhaltserv(1m).

function halt_services
{
for I in ${SERVICE_NAME[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Halting service $I"
	cmhaltserv $I
	test_return 9
done
}

# Disown the DTC.

function disown_dtc
{
for I in ${DTC_NAME[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Disowning the DTC $I"
	dtcmodifyconfs -d $I
	test_return 11
done
}

# For each IP address/subnet pair, remove the IP address from the subnet
# using cmmodnet(1m).

function remove_ip_address
{
integer S=0
integer error=0

for I in ${IP[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Remove IP address $I from subnet ${SUBNET[$S]}"
	XX=$( cmmodnet -r -i $I ${SUBNET[$S]} 2>&1 )
	if (( $? != 0 ))
	then
		echo $XX | grep "is not configured on the subnet"
		if (( $? != 0 ))
		then
			print "$XX" >> $0.log
			(( error = 1 ))
		fi
	fi
	(( S = $S + 1 ))
done
if (( $error != 0 ))
then

# `let 0` is used to set the value of $? to 1. The function test_return
# requires $? to be set to 1 if it has to print error message.

	let 0
	test_return 12
fi
}

# Unmount each logical volume.

function umount_fs
{
integer UM_CNT=${LV_UMOUNT_COUNT:-1}

if [[ $UM_CNT < 1 ]]
then
   UM_CNT=1
fi

for I in $(print ${LV[@]} | awk '{ for(i=NF; i>0; i--) print $i }')
do
	mount | grep -e $I" " > /dev/null 2>&1
	if (( $? == 0 ))
	then
		print "$(date '+%b %e %X') - Node \"$(hostname)\": Unmounting filesystem on $I"
		print "\tWARNING:   Running fuser to remove anyone using the file system directly."
		UM_COUNT=$UM_CNT
		while (( $UM_COUNT > 0 ))
		do
		fuser -ku $I
		umount $I
		if (( $? == 0 ))
		then
			(( UM_COUNT = 0 ))
		else
			if (( $UM_COUNT == 1 ))
			then
				let 0
				test_return 13
			fi
			(( UM_COUNT = $UM_COUNT - 1 ))
			sleep 1
			if (( $UM_COUNT > 0 ))
			then
				print "\t$(date '+%b %e %X') - Unmount failed, trying again."
			fi
		fi
		done
	fi
done
}


function deactivate_volume_group
{
for I in ${VG[@]}
do
	print "$(date '+%b %e %X') - Node \"$(hostname)\": Deactivating volume group $I"
	vgchange -a n $I
	test_return 14
done
}

# END OF HALT FUNCTIONS.

# FUNCTIONS COMMON TO BOTH RUN AND HALT.

# Test return value of functions and exit with NO RESTART if bad.
# Return value of 0 - 50 are reserved for use by Hewlett-Packard.
# System administrators can use numbers above 50 for return values.
function test_return
{
if (( $? != 0 ))
then
	case $1 in
		1)
		print "\tERROR:  Function activate_volume_group"
		print "\tERROR:  Failed to activate $I"
		deactivate_volume_group
		exit 1
		;;

		2)
		print "\tERROR:  Function check_and_mount"
		print "\tERROR:  Failed to fsck one of the logical volumes."
		exit_value=1
		;;

		3)
		print "\tERROR:  Function check_and_mount"
		print "\tERROR:  Failed to mount $I to ${FS[$F]}"
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		4)
		print "\tERROR:  Function add_ip_address"
		print "\tERROR:  Failed to add IP address to subnet"
		remove_ip_address
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		5)
		print "\tERROR:  Function get_ownership_dtc"
		print "\tERROR:  Failed to own $I"
		disown_dtc
		remove_ip_address
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		6)
		print "\tERROR:  Function get_ownership_dtc"
		print "\tERROR:  Failed to switch $I"
		disown_dtc
		remove_ip_address
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		8)
		print "\tERROR:  Function start_services"
		print "\tERROR:  Failed to start service ${SERVICE_NAME[$C]}"
		halt_services
		customer_defined_halt_cmds
		disown_dtc
		remove_ip_address
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		9)
		print "\tFunction halt_services"
		print "\tWARNING: Failed to halt service $I"
		;;

		11)
		print "\tERROR:  Function disown_dtc"
		print "\tERROR:  Failed to disown $I from ${SUBNET[$S]}"
		exit_value=1
		;;

		12)
		print "\tERROR:  Function remove_ip_address"
		print "\tERROR:  Failed to remove $I"
		exit_value=1
		;;

		13)
		print "\tERROR:  Function umount_fs"
		print "\tERROR:  Failed to unmount $I"
		exit_value=1
		;;

		14)
		print "\tERROR:  Function deactivate_volume_group"
		print "\tERROR:  Failed to deactivate $I"
		exit_value=1
		;;

		51)
		print "\tERROR:  Function customer_defined_run_cmds"
		print "\tERROR:  Failed to RUN customer commands"
		halt_services
		customer_defined_halt_cmds
		disown_dtc
		remove_ip_address
		umount_fs
		deactivate_volume_group
		exit 1
		;;

		52)
		print "\tERROR:  Function customer_defined_halt_cmds"
		print "\tERROR:  Failed to HALT customer commands"
		exit_value=1
		;;

		*)
		print "\tERROR:  Failed, unknown error."
		;;
	esac
fi
}

# END OF FUNCTIONS COMMON TO BOTH RUN AND HALT

#-------------------MAINLINE Control Script Code Starts Here-----------------
#
# FUNCTION STARTUP SECTION.

typeset MIN_VERSION="A.10.03"  # Minimum version this control script works on

integer exit_value=0
typeset CUR_VERSION

#
# Check that this control script is being run on a A.10.03 or later release
# of MC/ServiceGuard or MC/LockManager.  The control scripts are forward
# compatible but are not backward compatible because newer control
# scripts use commands and option not available on older releases.

CUR_VERSION="$(/usr/bin/what /usr/lbin/cmcld | /usr/bin/grep "Date" | \
                            /usr/bin/egrep '[AB]\...\...|NTT\...\...' | \
			    cut -f2 -d" ")"

if [[ "${CUR_VERSION}" = ""  ]] || \
                              [[ "${CUR_VERSION#*.}" < "${MIN_VERSION#*.}" ]]
then
    print "ERROR:  Mismatched control script version ($MIN_VERSION).  You cannot run"
    print "\ta version ${MIN_VERSION} control_script on a node running pre"
    print "\t${MIN_VERSION} MC/ServiceGuard or MC/LockManager software"
    exit 1
fi

# Test to see if we are being called to run the package, or halt the package.

if [[ $1 = "start" ]]
then
	print "\n\t########### Node \"$(hostname)\": Starting package at $(date) ###########"

	activate_volume_group

	check_and_mount

	add_ip_address

	get_ownership_dtc

	customer_defined_run_cmds

	start_services


# Check exit value

	if (( $exit_value == 1 ))
	then
		print "\n\t########### Node \"$(hostname)\": Package start failed  at $(date) ###########"
		exit 1
	else
		print "\n\t########### Node \"$(hostname)\": Package start completed  at $(date) ###########"
		exit 0
	fi

elif [[ $1 = "stop" ]]
then
	print "\n\t########### Node \"$(hostname)\": Halting package at $(date) ###########"


	halt_services

	customer_defined_halt_cmds

	disown_dtc

	remove_ip_address

	umount_fs

	deactivate_volume_group

# Check exit value
	if (( $exit_value == 1 ))
	then
		print "\n\t########### Node \"$(hostname)\": Package halt failed at $(date) ###########"
		exit 1
	else
		print "\n\t########### Node \"$(hostname)\": Package halt completed at $(date) ###########"
		exit 0
	fi

fi











Популярность: 81, Last-modified: Sat, 21 Jul 2001 03:26:01 GmT