#!/bin/sh # Last Update: 03 November 2011 # Designed by: Dusan U. Baljevic (dusan.baljevic@ieee.org) # Coded by: Dusan U. Baljevic (dusan.baljevic@ieee.org) # # Copyright 2011-2014 Dusan Baljevic # # 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 3 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, see . # # Designed for simple boot disk mirroring for LVM on HP-UX servers # with agile or legacy devices # # Usage: $0 -a|-l [-d] [-h] [-p PRIMARYDISK] -m ALTERNATEDISK" # -a Use agile DSF # -l Use legacy DSF # -h Help menu # -p disk4|c0t2t3 Define primary (agile|legacy) boot disk # -m disk6|c3t4d0 Define alternate (agile|legacy) boot disk # -a|-l -d -m disk6|c3t4d0 Remove mirror from alternate (agile|legacy) boot disk # Set path to reasonable environment # PATH=/usr/bin:/bin:/sbin:/usr/sbin:/usr/sam/lbin; export PATH umask 022 # Define default variables # ALTDISK="" NPRIDISK="" NALTDISK="" TYPEFLAG="" TMPFILE="/tmp/idf$$" DATE="$(date '+%Y%m%d')" BOOTCONF="/stand/bootconf" BOOTCONFTMP="/var/tmp/bootconf-$DATE" BOOTC="/tmp/bootconf$$" AUTOFILE="/tmp/auto$$" HWARCH="$(uname -m | grep -i ia64 2>/dev/null)" OSREL="$(uname -r)" OSVER="$(uname -s)" DELETE="NO" ERRNO=0 MYCOMM="$(basename $0)" helpfile () { echo "USAGE: $MYCOMM -a|-l [-h] [-d] [-p PRIMARYDISK] [-m ALTERNATEDISK] -a Use agile DSF -l Use legacy DSF -h Help menu -p disk4|c0t2t3 Define primary (agile|legacy) boot disk -m disk6|c3t4d0 Define alternate (agile|legacy) boot disk -a|-l -d -m disk6|c3t4d0 Remove mirror from alternate (agile|legacy) boot disk " echo "EXAMPLE1: $MYCOMM -a -p disk4 -m disk23" echo "EXAMPLE2: $MYCOMM -l" echo "EXAMPLE3: $MYCOMM -l -p c0t2t1 -m c3t4d0" echo "EXAMPLE4: $MYCOMM -a -m disk5" echo "EXAMPLE5: $MYCOMM -a -d -m disk5" echo "EXAMPLE6: $MYCOMM -l -d -m c4t2t1" } # The default Device Special File format is legacy in HP-UX 11i v1 and v2, # and agile in 11i v3 # case $OSREL in *11.1*|*11.2*) DEVRDIR="/dev/rdsk" DEVDIR="/dev/dsk" ;; *11.3*) DEVRDIR="/dev/rdisk" DEVDIR="/dev/disk" ;; esac # If O/S is not HP-UX, exit with warning # if [ "$OSVER" != "HP-UX" ] then echo "ERROR: Not an HP-UX server" exit 1 fi # In most cases, root volume group is named vg00, # but it can be any other name. Better to check it: # VGR="$(lvlnboot -v | awk '/Boot Definitions for Volume Group/ {print $NF}' | sed -e 's/:$//g' -e 's/\/dev\///g')" if [ "$VGR" ] then VGROOT="$VGR" else VGROOT="vg00" fi while getopts adhlp:m: option do case $option in a) PRIDISK="disk3" ALTDISK="disk4" DEVRDIR="/dev/rdisk" DEVDIR="/dev/disk" SLICE="_p2" SLICEHPSP="_p3" TYPEFLAG="YES" ;; d) DELETE="YES" ;; l) PRIDISK="c0t0d0" ALTDISK="c1t0d0" DEVRDIR="/dev/rdsk" DEVDIR="/dev/dsk" SLICE="s2" SLICEHPSP="s3" TYPEFLAG="YES" ;; p) NPRIDISK=${OPTARG} ;; m) NALTDISK=${OPTARG} ;; h) helpfile exit 0 ;; *) helpfile exit 1 ;; esac done if [ ! "$TYPEFLAG" ] then echo "ERROR: Missing flag \"-l\" or \"-a\"" echo helpfile exit 1 fi # If PA-RISC architecture, there are no slices on boot disks # Likewise, mkboot(1m) command uses "-e -l" only on IA64 # if [ ! "$HWARCH" ] then SLICE="" SLICEHPSP="" BOOTSTR="" else BOOTSTR="-e -l" fi if [ "$NPRIDISK" ] then echo "INFO: Setting primary boot disk to $NPRIDISK" PRIDISK="$NPRIDISK" fi if [ "$NALTDISK" ] then echo "INFO: Setting alternate boot disk to $NALTDISK" ALTDISK="$NALTDISK" fi LVMMIRRNO="$(lvmadm -l |egrep "disk|dsk" | wc -l)" if [ "$DELETE" = "YES" ] then if [ ! "$ALTDISK" ] then echo "ERROR: Alternate boot disk for removing mirror not defined" exit 1 else echo "INFO: You selected alternate boot disk $ALTDISK for removing mirror" fi for i in $(vgdisplay -v $VGROOT | grep -i " lv name" | awk '{print $3}') do if [ "$LVMMIRRNO" -gt 1 ] then NEWLVMMIRRNO="$(expr $LVMMIRRNO - 2)" else NEWLVMMIRRNO=0 fi lvreduce -m $NEWLVMMIRRNO $i ${DEVDIR}/${ALTDISK}${SLICE} if [ $? -eq 0 ] then echo "PASS: Removal of mirror on logical volume \"${i}\" completed successfully" else echo "ERROR: Removal of mirror on logical volume \"${i}\" failed" ERRNO="$(expr $ERRNO + 1)" fi done echo "INFO: Running lvlnboot to remove alternate boot path for $ALTDISK..." vgreduce $VGROOT ${DEVDIR}/${ALTDISK}${SLICE} lvrmboot -s $VGROOT if [ $? -eq 0 ] then echo "PASS: \"lvrmboot -s $VGROOT\" completed successfully" else echo "ERROR: \"lvrmboot -s $VGROOT\" failed" ERRNO="$(expr $ERRNO + 1)" fi DUMPDEV="$(vginfo -d | awk '/"'$VGROOT'"/ {print}')" for list in `echo $DUMPDEV` do lvrmboot -d $DUMPDEV $VGROOT if [ $? -eq 0 ] then echo "PASS: \"lvrmboot -d $DUMPDEV\" completed successfully" else echo "ERROR: \"lvrmboot -d $DUMPDEV\" failed" ERRNO="$(expr $ERRNO + 1)" fi done # lvrmboot -r $VGROOT # if [ $? -eq 0 ] # then # echo "PASS: \"lvrmboot -r $VGROOT\" completed successfully" # else # echo "ERROR: \"lvrmboot -r $VGROOT\" failed" # ERRNO="$(expr $ERRNO + 1)" # fi lvlnboot -R /dev/$VGROOT if [ $? -eq 0 ] then echo "PASS: lvlnboot update completed successfully" else echo "ERROR: lvlnboot update reported errors" ERRNO="$(expr $ERRNO + 1)" fi pvcreate -f ${DEVRDIR}/${ALTDISK}${SLICE} egrep -v "${DEVDIR}/${ALTDISK}${SLICE}" $BOOTCONF >$BOOTC if [ $? -eq 0 ] then cp -p $BOOTCONF $BOOTCONFTMP cp $BOOTC $BOOTCONF if [ $? -eq 0 ] then rm -f $BOOTC $BOOTCONFTMP 2>/dev/null else mv $BOOTCONFTMP $BOOTCONF ERRNO="$(expr $ERRNO + 1)" echo "ERROR: $BOOTCONF update failed - check manually" fi fi if [ "$HWARCH" ] then echo "INFO: Clearing the partition table on ${DEVRDIR}/$ALTDISK..." idisk -Rw ${DEVRDIR}/$ALTDISK if [ $ERRNO -gt 0 ] then echo "ERROR: Clearing the partition table on ${DEVRDIR}/$ALTDISK failed" else echo "PASS: Clearing the partition table on ${DEVRDIR}/$ALTDISK completed successfully" fi fi if [ $ERRNO -gt 0 ] then echo "ERROR: Removal of mirror on boot disk ${DEVRDIR}/$ALTDISK failed" echo "INFO: Please check the setup manually" exit 1 else echo "PASS: Removal of mirror on boot disk ${DEVRDIR}/$ALTDISK completed successfully" fi exit 0 else if [ ! "$ALTDISK" ] then echo "ERROR: Alternate disk for mirroring not defined" exit 1 else echo "INFO: You selected alternate disk $ALTDISK for mirroring" fi fi for i in $(vgdisplay -v $VGROOT | grep -i " lv name" | awk '{print $3}') do echo "INFO: Checking logical volume $i in volume group $VGROOT" STALE="$(lvdisplay -v ${i} | grep -i stale)" if [ "$STALE" = "" ] then echo "PASS: Logical volume $i does not have stale extents" else echo "ERROR: Logical volume $i has stale extents" exit 1 fi done if [ "$HWARCH" ] then echo "INFO: Partitioning disk $ALTDISK..." # echo "3 #EFI 500MB #HPUX 100% #HPSP 400MB" > $TMPFILE print '3\nEFI 500MB\nHPUX 100%\nHPSP 400MB' > $TMPFILE if [ $? -ne 0 ] then echo "ERROR: Cannot create partition file for disk $ALTDISK" exit 1 fi /usr/bin/echo yes | idisk -f $TMPFILE -w ${DEVRDIR}/$ALTDISK if [ $? -ne 0 ] then echo "ERROR: Cannot partition disk $ALTDISK" exit 1 else echo "PASS: $ALTDISK partitioned successfully" rm $TMPFILE 2>/dev/null fi echo "INFO: Installing device special files (DSF) for $ALTDISK partitions..." insf -e if [ $? -ne 0 ] then echo "ERROR: DSFs for $ALTDISK not installed" exit 1 else echo "PASS: DSFs for $ALTDISK installed successfully" fi fi pvcreate -f -B ${DEVRDIR}/${ALTDISK}${SLICE} if [ $? -ne 0 ] then echo "ERROR: Cannot install boot headers onto disk $ALTDISK" exit 1 else echo "PASS: Installed boot headers onto disk $ALTDISK" fi echo "INFO: Extending volume group $VGROOT by adding disk ${ALTDISK}${SLICE}..." vgextend $VGROOT ${DEVDIR}/${ALTDISK}${SLICE} if [ $? -ne 0 ] then echo "ERROR: Cannot extend volume group $VGROOT" exit 1 else echo "PASS: Volume group $VGROOT extended successfully" fi echo "INFO: Making $ALTDISK a bootable disk..." mkboot $BOOTSTR ${DEVRDIR}/$ALTDISK if [ $? -ne 0 ] then echo "ERROR: Failed to set $ALTDISK a bootable disk" exit 1 else echo "PASS: $ALTDISK set as bootable successfully" fi if [ ! "$HWARCH" ] then mkboot -b /usr/sbin/diag/lif/updatediaglif -p ISL -p AUTO -p HPUX -p PAD -p LABEL ${DEVRDIR}/$ALTDISK fi echo "INFO: Setting low-quorum on $PRIDISK and $ALTDISK..." mkboot -a "hpux -lq" ${DEVRDIR}/$ALTDISK mkboot -a "hpux -lq" ${DEVRDIR}/$PRIDISK # Copy autoboot file from the original boot disk to alternate disk # #efi_cp -d ${DEVRDIR}/${PRIDISK}${SLICE} -u /EFI/HPUX/AUTO $AUTOFILE #if [ $? -eq 0 ] #then # efi_cp -d ${DEVRDIR}/${ALTDISK}${SLICE} $AUTOFILE /EFI/HPUX/AUTO # #fi for i in $(vgdisplay -v $VGROOT | grep -i " lv name" | awk '{print $3}') do NEWLVMMIRRNO="$LVMMIRRNO" lvextend -m $NEWLVMMIRRNO $i ${DEVDIR}/${ALTDISK}${SLICE} if [ $? -eq 0 ] then echo "PASS: Mirroring of logical volume \"${i}\" completed successfully" else echo "ERROR: Mirroring of logical volume \"${i}\" failed" echo "INFO: Please check the incomplete setup now" rm $TMPFILE $AUTOFILE 2>/dev/null exit 1 fi done echo "INFO: Running lvlnboot to include alternate boot path for $ALTDISK..." lvlnboot -R /dev/$VGROOT if [ $? -eq 0 ] then echo "PASS: lvlnboot update completed successfully" else echo "ERROR: lvlnboot update reported errors" echo "INFO: Please check the incomplete setup now" rm $TMPFILE $AUTOFILE 2>/dev/null exit 1 fi echo "INFO: Running setboot to set alternate boot path for $ALTDISK..." setboot -a ${DEVRDIR}/$ALTDISK echo "INFO: Adding $ALTDISK into $BOOTCONF..." if [ ! -s "$BOOTCONF" ] then echo "ERROR: $BOOTCONF empty or does not exist" echo "INFO: Check it immediately (both boot disks must be listed in the file)" echo "INFO: The required entry for alternate disk is \"l ${DEVDIR}/${ALTDISK}${SLICE}\"" else echo "l ${DEVDIR}/${ALTDISK}${SLICE}" >> $BOOTCONF fi if [ "$HWARCH" ] then echo "INFO: Initializing ${DEVRDIR}/${ALTDISK}${SLICEHPSP} with an EFI file system" efi_fsinit -d ${DEVRDIR}/${ALTDISK}${SLICEHPSP} fi rm $TMPFILE $AUTOFILE 2>/dev/null echo "PASS: LVM mirroring on disk $ALTDISK completed successfully" exit 0