#!/usr/bin/ksh93
# script mklvfs.ksh {{{
# by -=GLA=-
# to make some lv and put fs on them
# see also fsgen
# v1.0.0        -=GLA=- ready for general use.
# v1.1.0        -=GLA=- added parameter checks.
# v2.0.0        -=GLA=- added ability to specify disks,
#                       exit on some command failures,
#                       gatekeeper check (in case I add mkvg to this one day).
# v2.1.0        -=GLA=- added -c for chmod and -h for help.
# v2.2.0        -=GLA=- modified some code, added -b for "set -xv".
# v2.2.1        -=GLA=- fixed some stuff.
# v2.2.2        -=GLA=- added some colors just for fun.
# v2.2.3        -=GLA=- mirror lv if put in rootvg.
# v2.2.4        -=GLA=- added umask 022.
# v2.2.5        -=GLA=- added -k to specify umask, default is 022.
# v2.2.6        -=GLA=- colors optional for Blackberry niceness.
# v2.3.0        -=GLA=- removed -k option,
#                       added explicit setting of underlying mountpoint to bin:bin and 555,
#                       replaced some if contructs with boolean conditionals.
#                       other minor changes.
# v2.4.0        -=GLA=- officially added -t option.
#                       added syncvg -l $LV to operations in rootvg.
#                       restricted execution to ksh93.
#                       added execution-time reporting.
#                       rewrote some logic code.
# v2.4.1        -=GLA=- bugfix of vg check and -C
# v2.4.2        -=GLA=- restricted -p argument to number only
#                       minor fix to missing-vg error text
# v2.4.3        -=GLA=- modified -t handling to no default action,
#                       changed usage output
# v2.5.0        -=GLA=- enhanced pre-execution checks
#                       added -n
#                       checks number of disks in rootvg before attempting to mirror
# v2.5.1 -=GLA=-        added -o
#                       minor beautification
#}}}
# predef {{{
start=$(perl -e '$d=time;print "$d\n";')
version=2.5.1
MIRR=t
#}}}
uses() { #{{{
print "
$grn$0$clr version $yel$version$clr
print $yel$0$clr -l ${yel}LVNAME$clr -p ${yel}PP$clr -m ${yel}MOUNTPOINT$clr -v ${yel}VG$clr -t ${yel}FSTYPE$clr [-d ${yel}DISK1[,DISK2,...]$clr] [-u ${yel}USR$clr] [-g ${yel}GRP$clr] [-c ${yel}PERM$clr] [-o ${yel}FSOPTIONS$clr] [-n] [-b] [-C]"
exit 1
} #}}}
usage() { #{{{
print "${grn}SCRIPT$clr $0 version $yel$version$clr"
print "${grn}Purpose:$clr Make a logical volume, then a filesystem, mount it and optionally chown, chmod, set options, etc,"
print "\tparticularly useful with script fsgen for recreating whole sets of fs."
print "${grn}Usage:$clr"
print "$yel$0$clr [-C] -l ${yel}LVNAME$clr -p ${yel}PP$clr -m ${yel}MOUNTPOINT$clr -v ${yel}VGNAME$clr -t ${yel}FSTYPE$clr [-d ${yel}DISKNAMES$clr] [-u ${yel}USERID$clr] [-g ${yel}GROUPID$clr] [-c ${yel}PERMS$clr] [-o ${yel}FSOPTIONS$clr] [-n] [-b]"
print "or $0 -h | -Ch"
print "Where..."
print "${yel}LVNAME$clr is the new logical volume name."
print "${yel}PP$clr is the number of PP for this lv."
print "${yel}MOUNTPOINT$clr is the filesystem to lay on top of the lv."
print "${yel}VGNAME$clr is the target volume group. The vg must exist."
print "${yel}FSTYPE$clr is either jfs or jfs2."
print "${yel}DISKNAMES$clr can be one disk or a comma-separated list, default is all disks in target vg. Optional."
print "${yel}USERID$clr is the user you would like to own MOUNTPOINT. Optional."
print "${yel}GROUPID$clr is the group you would like to own MOUNTPOINT. Optional."
print "${yel}PERMS$clr is the octal (or symbolic) permission string passed directly to chmod. Optional."
print "${yel}FSOPTIONS$clr is a filesystem option string to be used like \"crfs -a options=FSOPTIONS\". Example: rw,cio"
print ' -n skips mirroring of rootvg filesystems. Optional.'
print ' -h prints this text.'
print ' -b turns on debug mode: set -xv for functions'
print ' -C turns on color mode. Using aixterm (or another color-enabled terminal) will allow fancy-shmancy colors. Optional.'
print "See also the script /utc/bin/fsgen\n"
print "Return codes:"
print "1 = usage error"
print "2 = given disk not in given vg"
print "3 = given disk is a gatekeeper"
print "4 = found hdiskpowers but no inq"
print "5 = LVNAME exists"
print "6 = MOUNTPOINT exists"
print "7 = USR does not exist"
print "8 = GRP does not exist"
print ""
print "EXAMPLES:"
print "mklvfs.ksh -l orastagelv -p 128 -m /oracle/stage -t jfs2 -v sapvg -d hdiskpower3,hdiskpower5,hdiskpower11 -u orax28 -g dba"
print "mklvfs.ksh -m /opt/temp -l templv -p 512 -v optvg -t jfs -c 2750"
exit 1
} #}}}
uschk() { # general usage checks {{{
[[ -n $DBUG ]]&&set -xv
[[ -z $LV ]]&&print "${red}ERROR: -l LVNAME not given$clr\n"&&uses
[[ -z $PP ]]&&print "${red}ERROR: -p PP not given$clr\n"&&uses
[[ -z $MNTPT ]]&&print "${red}ERROR: -m MOUNTPOINT not given$clr\n"&&uses
[[ -z $VGNAME ]]&&print "${red}ERROR: -v VGNAME not given$clr\n"&&uses
[[ -z $FSTYPE ]]&&print "${red}ERROR: -t FSTYPE not given$clr\n"&&uses
case $FSTYPE in
        jfs2)
                fstype='-v jfs2 '
                lvtype='-t jfs2'
        ;;
        jfs)
                fstype='-v jfs -a bf=true '
        ;;
        *)print "${red}ERROR: valid options for -t are jfs2 or jfs$clr\n"&&uses
        ;;
esac
for VG in $(lsvg); do
        [[ $VG == $VGNAME ]]&&VGMATCH=t&&break
done
[[ $VGMATCH != t ]]&&print "${red}Error: -v VGNAME, volume group $VGNAME not found$clr\n"&&exit 1
print $MNTPT|grep "^/">/dev/null||{ print "${red}Error: -m MOUNTPOINT should be an absolute path$clr\n";exit 1; }
for LVS in $(lsdev -C|awk '/Logical volume/{print$1}');do
        if [[ $LVS == $LV ]];then
                print "${red}Error: -l LVNAME, logical volume $LV already exists$clr"
                exit 5
        fi
done
for FS in $(lsfs|awk '$3~/^\//{print$3}');do
        if [[ $FS == $MNTPT ]];then
                print "${red}Error: -m MOUNTPOINT, filesystem name $FS already exists$clr"
                exit 6
        fi
done
if [[ -n $USR ]];then
        if ! lsuser $USR >/dev/null 2>&1;then
                print "${red}Error: -u USR, userid $USR does not exist$clr"
                exit 7
        fi
fi
if [[ -n $GRP ]];then
        if ! lsgroup $GRP >/dev/null 2>&1;then
                print "${red}Error: -g GRP, groupid $GRP does not exist$clr"
                exit 8
        fi
fi
} #}}}
defc() { # define colors {{{
yel=""
red=""
grn=""
blu=""
unl=""
clr=""
} #}}}
dskchk() { # disk checks {{{
[[ -n $DBUG ]]&&set -xv
if [[ -n $DISKLIST ]]; then
#       if [[ $dtype = "power" ]]; then # {{{
#               gateks=$(inq|awk -F: '$2~/EMC/&&$NF<20000{print$1}'|sed 's#/dev/r##')
#               for diskn in $DISKLIST; do
#                       for gk in $gateks; do
#                               [[ $diskn = $gk ]]&&print "$red$diskn is a gatekeeper! Please specify another disk.$clr"&&exit 3
#                       done
#               done
#       fi
#       if lspv|grep power; then
#               dtype="power"
#               if [[ ! -x /usr/local/bin/inq ]]; then
#                       print "${red}Found EMC disks but no /usr/local/bin/inq executable!$clr"
#                       print "${red}Better see about fixing this machine.$clr"
#                       exit 4
#       fi
#       else
#               dtype="scsi"
#       fi #}}}
        vgpv=$(lsvg -p $VGNAME|awk '/^hdisk/{printf($1" ")}END{printf("\n")}')
        for diskn in $DISKLIST; do
                for pv in $vgpv; do
                        [[ $diskn = $pv ]]&&found="$found$diskn "
                done
        done
        if [[ $found != $DISKLIST ]]; then
                print "${red}ERROR: one or more user-supplied disks not found in $VGNAME"
                print "your list:\t$DISKLIST"
                print "found disks:\t$found$clr"
                exit 2
        fi
fi
} #}}}
doit() { #{{{
[[ -n $DBUG ]]&&set -xv
print "${grn}EXECUTING$clr: /usr/sbin/mklv -y $LV$lvtype -a e -e x -w n $VGNAME $PP $DISKLIST"
/usr/sbin/mklv -y $LV$lvtype -a e -e x -w n $VGNAME $PP $DISKLIST||{ print "${red}FAILED during mklv, aborting$clr";exit $?; }
if [[ $VGNAME == rootvg ]];then
        let rvgd=$(lsvg rootvg|awk '/^TOTAL PVs/{print$3}')
        if (( $rvgd == 1 ));then
                MIRR=f
        fi
        if [[ $MIRR == t ]];then
                print "${grn}EXECUTING$clr: /etc/mklvcopy ${LV}2"
                /etc/mklvcopy ${LV}2||{ print "${red}FAILED during /etc/mklvcopy, aborting$clr";exit $?; }
                print "${grn}EXECUTING$clr: /usr/sbin/syncvg -l $LV"
                /usr/sbin/syncvg -l $LV||{ print "${red}FAILED during /usr/sbin/syncvg, aborting$clr";exit $?; }
        fi
fi
print "${grn}EXECUTING$clr: /usr/sbin/crfs ${fstype}-d ${LV}-A yes -m $MNTPT -a options=$FSOPT"
/usr/sbin/crfs ${fstype}-d ${LV}-A yes -m $MNTPT -a options=$FSOPT||{ print "${red}FAILED during crfs, aborting$clr";exit $?; }
print "${grn}EXECUTING$clr: /usr/bin/chown bin.bin $MNTPT"
/usr/bin/chown bin.bin $MNTPT||{ print "${red}FAILED during chown, aborting$clr";exit $?; }
print "${grn}EXECUTING$clr: /usr/bin/chmod 555 $MNTPT"
/usr/bin/chmod 555 $MNTPT||{ print "${red}FAILED during chmod, aborting$clr";exit $?; }
print "${grn}EXECUTING${clr}: /usr/sbin/mount $MNTPT"
/usr/sbin/mount $MNTPT||{ print "${red}FAILED during mount, aborting$clr";exit $?; }
if [[ -n $USR ]]; then
        print "${grn}EXECUTING$clr: /usr/bin/chown $USR $MNTPT"
        if ! /usr/bin/chown $USR $MNTPT; then
                print "${red}FAILED during chown, continuing...\nError code: $?$clr"
        else
                CUSR=X
        fi
fi
if [[ -n $GRP ]]; then
        print "${grn}EXECUTING$clr: /usr/bin/chgrp $GRP $MNTPT"
        if ! /usr/bin/chgrp $GRP $MNTPT; then
                print "${red}FAILED during chgrp, continuing...\nError code: $?$clr"
        else
                CGRP=X
        fi
fi
if [[ -n $PERM ]]; then
        print "${grn}EXECUTING$clr: /usr/bin/chmod $PERM $MNTPT"
        if ! /usr/bin/chmod $PERM $MNTPT; then
                print "${red}FAILED during chmod, continuing...\nError code: $?$clr"
        else
                CMOD=X
        fi
fi
print "${grn}DONE!$clr"
} #}}}
while getopts "hbl:p#m:v:d:u:g:c:Ct:no:" option; do #{{{
        case $option in
                C)defc;;
                h)usage;;
                b)DBUG=Y
                set -xv;;
                l)LV="$OPTARG ";;
                p)PP=$OPTARG;;
                m)MNTPT=$OPTARG;;
                v)VGNAME=$OPTARG;;
                d)DISKLIST="$(print $OPTARG|sed 's/,$//;s/,/ /g') ";;
                u)USR=$OPTARG;;
                g)GRP=$OPTARG;;
                c)PERM=$OPTARG;;
                t)FSTYPE=$OPTARG;;
                n)MIRR=f;;
                o)FSOPT=$OPTARG;;
                *)print "${red}Error: Illegal option$clr\n"
                usage;;
        esac
done #}}}
print "Starting $0 version $unl$version$clr"
uschk
dskchk
doit
elapsed=$(($(perl -e '$d=time;print "$d\n";')-$start))
print "elapsed time: $elapsed seconds"