#!/bin/ksh # # This script is unsupported by Hewlett-Packard. Use at your own risk. # # ignite_mirror.ksh # # last modified: 12/27/2000 # # This script will mirror the root volume group automatically as part of # Qwest's Ignite/UX process for installing new systems. This script requires # the following prior to being run: # 1. Only 1 disks for vg00 # 2. Both primary and mirror boot disks set as primary and alternate # boot paths in the prom # 3. Primary and alternate boot disks to be on different IO paths (for HA) # 4. Mirror/UX # 5. Both disks are the same size # # If these five conditions are not met, this script will NOT run # # usage: ignite_mirror.ksh # # **************************************************************************** # change history # MEJ = Ed Jones, Hewlett-Packard ASE # MEJ 05/12/2000 - initially created for HP-UX 11.00 / IUX B.2.3.205 # MEJ 05/23/2000 - added function check_lvol_extents # - added function compare_disk_sizes # MEJ 06/01/2000 - changed check of different controller from # hardware path to cxtydz where x should be different # created new function check_diff_controllers # MEJ 06/09/2000 - added offline diag load into LIF for both boot # disks via mkboot # MEJ 12/27/2000 - added support for HP-UX 11.11 (11i) # checks for Mirror/UX as fileset rather than bundle # **************************************************************************** # # **************************************************************************** # treat undefined variables as errors, not NULL...should always be done in # scripts running as root set -u # just to be safe... umask 022 export PATH=/bin:/usr/bin:/sbin:/usr/sbin KERNEL_BITS=$(getconf KERNEL_BITS) OS_VERSION=$(uname -r) # **************************************************************************** function check_mirrordisk { print;print "Checking for MirrorDisk/UX....." swlist -l fileset @ 127.0.0.1 | grep "^ LVM.LVM-MIRROR-RUN" result=$? if [[ $result -ne 0 ]]; then print "MirrorDisk/UX software NOT installed.....aborting" exit 1 iux_return=1 else print "MirrorDisk/UX software installed" print fi } # end function check_mirrordisk # **************************************************************************** # **************************************************************************** function find_root_vg { print "Finding name of root volume group (almost always vg00)....." ROOT_VG=$(grep "/stand" /etc/fstab | awk '{print $1}' | awk -F\/ '{print $3}') if [[ -z $ROOT_VG ]]; then print "Failed to find root volume group.....aborting" exit 1 iux_return=1 else print "Root volume group found to be named $ROOT_VG" print fi } # end function find_root_vg # **************************************************************************** # **************************************************************************** function check_single_root_disk { # this function does not bother to make sure the disk isn't already set up # in a PVG. If it is, the following check will fail even though it's the # same disk just repeated twice. this assumption is fine for Qwest's Ignite # install process print "Checking number of disks in $ROOT_VG prior to mirroring....." NUM_ROOT_DISKS=$(vgdisplay -v vg00 | grep "PV Name" | wc -l) if [[ $NUM_ROOT_DISKS -ne 1 ]]; then print "Number of disks in $ROOT_VG prior to mirroring not 1....aborting" exit 1 iux_return=1 else print "Number of disks in $ROOT_VG prior to mirroring is 1" print fi } # end function check_single_root_disk # **************************************************************************** # **************************************************************************** function find_boot_paths { print "Finding primary and alternate boot paths....." PRIMARY_PATH=$(setboot | grep "Primary bootpath :" | awk '{print $4}') ALTERNATE_PATH=$(setboot | grep "Alternate bootpath :" | awk '{print $4}') print "Primary path found to be $PRIMARY_PATH" print "Alternate path found to be $ALTERNATE_PATH" print } # end function find_boot_paths # **************************************************************************** # **************************************************************************** function find_device_names { print "Deriving device files from hardware paths" print PRIMARY_BLOCK_DEVICE=$(ioscan -fun -H $PRIMARY_PATH | grep dsk | awk '{print $1}') PRIMARY_RAW_DEVICE=$(ioscan -fun -H $PRIMARY_PATH | grep dsk | awk '{print $2}') ALTERNATE_BLOCK_DEVICE=$(ioscan -fun -H $ALTERNATE_PATH | grep dsk | awk '{print $1}') ALTERNATE_RAW_DEVICE=$(ioscan -fun -H $ALTERNATE_PATH | grep dsk | awk '{print $2}') } # end function find_device_names # **************************************************************************** # **************************************************************************** function check_diff_controllers { print "Checking if primary and alternate paths on different controllers....." PRIMARY_PATH_CONTROLLER=$(echo $PRIMARY_BLOCK_DEVICE | awk -F / '{print $4}' | cut -c 1-2) ALTERNATE_PATH_CONTROLLER=$(echo $ALTERNATE_BLOCK_DEVICE | awk -F / '{print $4}' | cut -c 1-2) print "Primary path controller found to be $PRIMARY_PATH_CONTROLLER" print "Alternate path controller found to be $ALTERNATE_PATH_CONTROLLER" if [[ $PRIMARY_PATH_CONTROLLER = $ALTERNATE_PATH_CONTROLLER ]]; then print "Primary and alternate paths on same controller.....aborting" exit 1 iux_return=1 else print "Primary and alternate paths on different controllers" print fi } # end function check_diff_controllers # **************************************************************************** # **************************************************************************** function compare_disk_sizes { PRIMARY_DISK_SIZE=$(diskinfo -b $PRIMARY_RAW_DEVICE) ALTERNATE_DISK_SIZE=$(diskinfo -b $ALTERNATE_RAW_DEVICE) print "Checking that alternate path is at least same size as primary....." if [[ $ALTERNATE_DISK_SIZE -lt $PRIMARY_DISK_SIZE ]]; then print "Alternate path is not of sufficient size.....aborting" print exit 1 iux_return=1 else print "Alternate path is of sufficient size to hold the mirror" print fi } # end function compare_disk_sizes # **************************************************************************** # **************************************************************************** function mirror_root_vg { print "All pre-conditions met, begining mirroring process....." print "Generating list of all lvols in $ROOT_VG....." LVOLS=$(vgdisplay -v $ROOT_VG | grep "LV Name" | awk '{print $3}') #LVOLS="/dev/vg00/lvol1" print "Pvcreating alternate boot disk for LVM....." pvcreate -B -f $ALTERNATE_RAW_DEVICE result=$? if [[ $result -ne 0 ]]; then print "pvcreate process failed.....aborting" exit 1 iux_return=1 else print "pvcreate process succeeded" fi print "Writing boot area to alternate boot disk....." mkboot $ALTERNATE_RAW_DEVICE result=$? if [[ $result -ne 0 ]]; then print "mkboot process failed.....aborting" exit 1 iux_return=1 else print "mkboot process succeeded" fi print "Updating AUTO file in LIF area to set autoboot flag....." print mkboot -a "hpux -lq" $ALTERNATE_RAW_DEVICE result=$? if [[ $result -ne 0 ]]; then print "set autoboot flag process failed.....aborting" exit 1 iux_return=1 else print "set autoboot flag process succeeded" fi print "Adding offline diagnostics in LIF areas on both boot disks....." print if [[ $KERNEL_BITS -eq 32 ]]; then mkboot -b /usr/sbin/diag/lif/updatediaglif -p ISL -p HPUX -p LABEL -p AUTO $PRIMARY_RAW_DEVICE result1=$? mkboot -b /usr/sbin/diag/lif/updatediaglif -p ISL -p HPUX -p LABEL -p AUTO $ALTERNATE_RAW_DEVICE result2=$? if [[ ($result1 -ne 0) || ($result2 -ne 0) ]]; then print "32 bit offline diag load failed.....aborting" print exit 1 iux_return=1 else print "32 bit offline diag load succeeded" print fi elif [[ $KERNEL_BITS -eq 64 ]]; then mkboot -b /usr/sbin/diag/lif/updatediaglif2 -p ISL -p HPUX -p LABEL -p AUTO $PRIMARY_RAW_DEVICE result1=$? mkboot -b /usr/sbin/diag/lif/updatediaglif2 -p ISL -p HPUX -p LABEL -p AUTO $ALTERNATE_RAW_DEVICE result2=$? if [[ ($result1 -ne 0) || ($result2 -ne 0) ]]; then print "64 bit offline diag load failed.....aborting" print exit 1 iux_return=1 else print "64 bit offline diag load succeeded" print fi fi # we're going to use physical volume groups (PVGs) for our disks as a matter # of cleanliness print "Adding primary disk to PVG Primary....." vgextend -g Primary $ROOT_VG $PRIMARY_BLOCK_DEVICE result=$? if [[ $result -ne 0 && $result -ne 2 ]]; then print "Failed to add primary disk to PVG Primary....aborting" exit 1 iux_return=1 else print "Added primary disk to PVG Primary" print fi print "Adding mirror disk to PVG Mirror....." vgextend -g Mirror $ROOT_VG $ALTERNATE_BLOCK_DEVICE result=$? if [[ $result -ne 0 ]]; then print "Failed to add primary disk to PVG Primary....aborting" exit 1 iux_return=1 else print "Added primary disk to PVG Primary" print fi print "Changing mirror policy for each lvol in $ROOT_VG to PVG-strict....." for lvol in $LVOLS; do lvchange -s g $lvol result=$? if [[ $result -ne 0 ]]; then print "Failed to change mirror policy for $lvol....aborting" exit 1 iux_return=1 else print "Changed mirror policy for $lvol" print fi done print "Extending each lvol in $ROOT_VG to alternate disk....." for lvol in $LVOLS; do print "Mirroring $lvol - this could take some time....." lvextend -m 1 $lvol result=$? if [[ $result -ne 0 ]]; then print "Failed to mirror $lvol....aborting" exit 1 iux_return=1 else check_lvol_extents $lvol if [[ $LVOL_MIRROR_STATUS = "success" ]]; then print "Mirror for $lvol succeeded" print else print "PEs for $lvol not symmetric....aborting" fi fi done } # end function mirror_root_vg # **************************************************************************** # **************************************************************************** function final_cleanup { print "Running lvlnboot -R to setup LVM links for both boot disks....." lvlnboot -R /dev/$ROOT_VG result=$? if [[ $result -ne 0 ]]; then print "Failed to recover LVM links for boot devices.....aborting" exit 1 iux_return=1 else print "Added LVM links for boot devices" print fi # The following probably isn't needed since 11.00 automatically does # a vgcfgbackup after each LVM modification, but it can't hurt... print "Running vgcfgbackup to backup config info for $ROOT_VG....." vgcfgbackup $ROOT_VG result=$? if [[ $result -ne 0 ]]; then print "Failed to backup $ROOT_VG configuration.....aborting" exit 1 iux_return=1 else print "Backup for $ROOT_VG configuration succeeded" print fi print "Mirror process for $ROOT_VG complete" print } # end final_cleanup # **************************************************************************** # **************************************************************************** function check_lvol_extents { # This function will check the logical extent (LE) to physical extent (PE) # mapping across disks. If a logical extent does not map to the same physical # extent number across disks, then this script will return an error. # strictly speaking this is not a real problem, but using PVGs and # verifying that the PEs match across disks is a very quick check to # see if all the LVs are mirrored properly. It's sort of like a very # quick checksum operation. typeset lvol=$1 LVOL_MIRROR_STATUS=$(lvdisplay -v $lvol | awk ' #get number of LE $1 ~ /Current/ && $2 ~ /LE/ { num_extents=$3 } NF == 7 { PE1 = $3 PE2 = $6 } END { if ( PE1 != PE2 ) print "failed" else print "success" } ') } # end function check_lvol_extents # **************************************************************************** #### Main script # check to make sure this system meets the conditions for this script before # we attempt to mirror check_mirrordisk find_root_vg check_single_root_disk find_boot_paths find_device_names check_diff_controllers compare_disk_sizes mirror_root_vg final_cleanup