#!/bin/ksh -
#
# @(#)mk-afs-srv++	1.26 (hursley) 1/15/98
# /afs/hursley.ibm.com/common/src/afs/@cell/asys/usr/local/sbin/mk-afs-srv++/SCCS/s.mk-afs-srv++
#
# NAME		mk-afs-srv++
# AUTHOR	Paul Blackburn <mpb@acm.org>
# PURPOSE	Install additional AFS fileserver
#		(based on hints in Transarc's AFS Installation Guide!)
# USAGE		Normally invoked as part of system installation.
# ASSUMPTIONS   Make sure you have correctly defined AFS installation
#               parameters for your system. The file containing these
#               ($AFSICF) is defined in:
#			${afs_install_base}/usr/local/sbin/mk-afs-cf
#
#		The first AFS fileserver *must* have already been installed.
#		(use mk-afs-srv to install first server.)

X=${afs_install_base}/usr/local/sbin/mk-afs-cf

if [[ ! -f ${X} ]]; then
	echo "${X} not found - fatal error" >&2
	exit 1
fi

# source global config for AFS installation

. ${X}

tstamp "version 1.26 commenced on `date '+%a %d %h %y'`"

# If we are not running on an AFS server then error exit

if [[ -z "${afsserver}" ]]; then
	warning "Check: ${AFSICF}"
	fatal "${HOST} is not defined as an AFS server"
fi

# Check we have AFS admin password.

if [[ -z "${adminpasswd}" ]]; then

# Switch stdout and stderr back to tty to prompt for data:
	exec 1>&3
	exec 2>&4

	getpass "AFS password for admin:"
	adminpasswd=${PASSWORD}
	export adminpasswd

	if [[ -z "${adminpasswd}" ]]; then
		fatal "null adminpasswd"
	fi

	echo "stdout and stderr now being written to ${LOG}"

	exec 4>&2
	exec 3>&1
	exec 1>>${LOG}
	exec 2>&1
fi

# Check AFS installation parameters (already obtained from ${AFSICF})

if [[ -z "${afslicense}" ]]; then
	fatal "afslicense not defined for ${HOST}"
fi

if [[ -z "${afscachevg}" ]]; then
	warning "afscachevg not defined for ${HOST}"
	afscachevg="rootvg"
	warning "defaulting to: ${afscachevg}"
fi

if [[ -z "${afscachename}" ]]; then
	warning "afscachename not defined for ${HOST}"
	afscachename="/usr/vice/cache"
	warning "defaulting to: ${afscachename}"
fi

if [[ -z "${afscachesize}" ]]; then
	warning "afscachesize not defined for ${HOST}"
	afscache="12"
	warning "defaulting to: ${afscache} (MB physical partitions)"
fi

if [[ -z "${afsdoptions}" ]]; then
	warning "afsdoptions not defined for ${HOST}"
	afsdoptions="-stat 2000 -dcache 800 -daemons 3 -volumes 70 -nosettime"
	warning "defaulting to: ${afsdoptions}"
fi

if [[ -z "${afscellname}" ]]; then
	warning "afscellname not defined for ${HOST}."
	X=`echo ${HOSTNAME} | cut -d. -f2-`
	if [[ -z "${X}" ]]; then
		fatal "failed to compute default afscellname"
	fi
	warning "defaulting to: ${X}"
	afscellname=${X}
fi

if [[ -z "${afspartitions}" ]]; then
	warning "afspartitions not defined for ${HOST}"
	afspartitions="rootvg:/vicepa:20"
	warning "defaulting to: ${afspartitions}"
fi

if [[ -z "${afsimageserver}" ]]; then
	warning "afsimageserver not defined for ${HOST}"
	afsimageserver="afsimageserver.aixssc.uk.ibm.com"
	warning "defaulting to: ${afsimageserver}"
fi

tstamp "Check we can reach afsimageserver=${afsimageserver}"
doit "ping ${afsimageserver} 56 1"
if [[ ${retcode} != 0 ]]; then
	fatal "Unable to ping ${afsimageserver}"
fi

if [[ -z "${afsusrbumpsize}" ]]; then
	warning "afsusrbumpsize not defined for ${HOST}"
	warning "defaulting to: 10"
	afsusrbumpsize="10"
fi

if [[ -z "${afsimagedir}" ]]; then
	warning "afsimagedir not defined for ${HOST}"
	afsimagedir="/vol/afs34/tapeimages/$sysname"
	warning "defaulting to: ${afsimagedir}"
fi

if [[ -z "${afsimagefs}" ]]; then
	warning "afsimagefs not defined for ${HOST}"
	afsimagefs="/vol/afs34"
	warning "defaulting to: ${afsimagefs}"
fi

if [[ -z "${afsimagefssize}" ]]; then
	warning "afsimagefssize not defined for ${HOST}"
	afsimagefssize="4"
	warning "defaulting to: ${afsimagefssize}"
fi

if [[ -z "${afsimagevg}" ]]; then
	warning "afsimagevg not defined for ${HOST}"
	afsimagevg="rootvg"
	warning "defaulting to: ${afsimagevg}"
fi

tstamp "Now, test if AFS already installed before going too far."
tstamp "Check if we have any afsd's running"
ps -ef | fgrep afsd | grep -v grep | awk '{print $2}' >${TF}
if [[ -s ${TF} ]]; then
	warning "There are afsd's running, PIDs are:"
	cat ${TF}
	rm ${TF}
	warning "Put \"exit\" at top of /etc/rc.afs and reboot."
	fatal ".You need to kill afsd's before running ${CMD} again.)"
else
	tstamp "Good news: no afsd running"
fi

# Clean up checks for possible previous partially install...
# Try to be idempotent!

for fs in ${afsimagefs} ${afscachename}; do
	tstamp "Check for existing filesystem: ${fs}"
	doit "lsfs ${fs}"
	if [[ ${retcode} = 0 ]]; then
		doit "umount ${fs}"
		doit "rmfs ${fs}"
	else
		tstamp "Good news: ${fs} not found"
	fi
done

if [[ -L /usr/afsws ]]; then
	doit "rm /usr/afsws"
fi

if [[ -d /afs ]]; then
	doit "rmdir /afs"
fi

if [[ -d /usr/afs ]]; then
	doit "rm -rf /usr/afs"
fi

if [[ -s /etc/rc.afs ]]; then
	doit "rm /etc/rc.afs"
fi
# Phew! Are we ready to start now? :-)

tstamp "AFS Installation Guide page 3-3, section 3.1.2"
tstamp "Make sure we have enough space in /usr for AFS files"

FREE=$(df /usr | tail -1 | awk '{print $3}')

# let's work in 512 byte blocks (because chfs size attribute likes this)

# WANTMB is the number of megabytes we want for AFS in /usr
# and afsusrbumpsize is expressed in Physical Partions (1pp=4mb)

let WANTMB=${afsusrbumpsize}\*4

# rs_aix32 df reports size in KB
# rs_aix41 df reports size in 512-blocks

if [[ ${sysname} = "rs_aix32" ]]; then
	let FREE=${FREE}\*1024/512
fi

let WANT=\(${WANTMB}\*1024\*1024\)/512

if [[ ${WANT} -lt ${FREE} ]]; then
	tstamp "Good news: we have ${WANTMB} PP in /usr for AFS files"
else
	tstamp "Increasing /usr to get ${WANTMB}MB free for AFS files"
	TOTAL=$(df /usr | tail -1 | awk '{print $2}')

	# rs_aix32 df reports size in KB
	# rs_aix41 df reports size in 512-blocks

	if [[ ${sysname} = "rs_aix32" ]]; then
		let TOTAL=${TOTAL}\*1024/512
	fi

	let SIZE=${TOTAL}+${WANT}-${FREE}
	doit "df /usr"
	doit "chfs -a size=${SIZE} /usr"
	if [[ ${retcode} != 0 ]]; then
		fatal "Unable to increase /usr by ${WANTMB}MB"
	fi
	doit "df /usr"
fi

# Create filesystem for AFS install tape compressed tar images

let sizeblocks=${afsimagefssize}\*8192

doit "crfs -v jfs -g${afsimagevg} -a size=${sizeblocks} -m${afsimagefs} -Ayes -prw"
if [[ ${retcode} != 0 ]]; then
	fatal "Unable to create afsimagefs=${afsimagefs} in ${afsimagevg}"
fi
doit "chfs -a mount=true ${afsimagefs}"
doit "chfs -ulocalfs ${afsimagefs}"
doit "mount ${afsimagefs}"

#doit "mkdir -p ${afsimagedir}"

tstamp "Check we have enough freespace for AFS cache and partitions"

VGS=$(lsvg -o)

for vg in ${VGS}; do
	FREE=$(lsvg ${vg} | awk '{if ($4 == "FREE") print $6}')
	WANT=0
	if [[ ${afscachevg} = ${vg} ]]; then
		let WANT=${WANT}+${afscachesize}
	fi
	for i in ${afspartitions}; do
		pvg=$(echo ${i} | awk -F: '{print $1}')
		size=$(echo ${i} | awk -F: '{print $3}')
		if [[ ${pvg} = ${vg} ]]; then
			let WANT=${WANT}+${size}
		fi
	done
	if [[ ${WANT} -gt ${FREE} ]]; then
		error "Not enough freespace in volume group: ${vg}"
		error "We have ${FREE} PPs free but need ${WANT}."
		error "Change ${HOST} AFS install parameters or buy more disk!"
		low_space="true"
	else
		tstamp "Good news: Adequate freespace in volume group:${vg}"
		tstamp "${vg}: we have ${FREE} PPs free and need ${WANT}"
	fi
done

if [[ ! -z "${low_space}" ]]; then
	warning "reduce space allocated to AFS partitions and try again"
	fatal "installation aborted"
fi

tstamp "AFS Installation Guide, page  3-3"
tstamp "Check we can: rsh ${afsfileserver} date"

rsh ${afsfileserver} date 2>&1 >/dev/null </dev/null

if [[ $? != 0 ]]; then
	warning "failed to: rsh ${afsfileserver} date"
	warning "add the following to ~root/.rhosts on ${afsfileserver}:"
	echo "${HOSTNAME} root"
	fatal "install aborted"
fi
	
tstamp "Copy /usr/afs/etc files from primary AFS fileserver"
doit "mkdir -p /usr/afs/etc"
cd /usr/afs/etc
doit "pwd"
doit "< /dev/null rsh ${afsfileserver} \"tar cf - /usr/afs/etc\" \
	| tar -xpvf - "
doit "ls -l"
doit "sync"
doit "sync"
doit "sync"

tstamp "dynamic kernel loader files (get the first tar set from server)"

TAPESET=set1.tar.Z
LOCAL=${afsimagefs}/${TAPESET}
REMOTE=${afsimagedir}/${TAPESET}
doit "tftp -g ${LOCAL} ${afsimageserver} ${REMOTE} image"

tstamp "AFS Installation Guide page 2-6"
doit "mkdir -p /usr/afs/bin"

cd /usr/afs/bin
doit "pwd"
doit "zcat ${LOCAL} | tar xvf -"

if [[ ${retcode} != 0 ]]; then
	fatal "problem un-tar-ing tapeset ${TAPESET}"
fi

tstamp "cd /usr/afs/bin/dkload"
cd /usr/afs/bin/dkload

case ${sysname} in
	rs_aix31 | rs_aix32 )
		tstamp "Installing NFS kernel extensions (for AFS+NFS)"
		doit "/etc/gfsinstall -a /usr/lib/drivers/nfs.ext"
		;;
esac

tstamp "Installing AFS kernel extensions..."
doit "./cfgexport -a export.ext"
doit "./cfgafs -a afs.ext"

tstamp "AFS Installation Guide page 3-3"
tstamp "file server process binaries (get the third tar set from server)"

TAPESET=set3.tar.Z
LOCAL=${afsimagefs}/${TAPESET}
REMOTE=${afsimagedir}/${TAPESET}
doit "tftp -g ${LOCAL} ${afsimageserver} ${REMOTE} image"

cd /usr/afs
doit "pwd"
doit "zcat ${LOCAL} | tar xvf -"

if [[ ${retcode} != 0 ]]; then
	fatal "problem un-tar-ing tapeset ${TAPESET}"
fi

tstamp "AFS Installation Guide page 3-7"
tstamp "Set up AFS partitions"

for i in ${afspartitions}; do
	vg=$(echo ${i} | awk -F: '{print $1}')
	name=$(echo ${i} | awk -F: '{print $2}')
	size=$(echo ${i} | awk -F: '{print $3}')
	let sizeblocks=${size}\*8192
	doit "crfs -v jfs -g${vg} -a size=${sizeblocks} -m${name} -Ayes -prw"
	doit "chfs -a mount=true ${name}"
	doit "chfs -ulocalfs ${name}"
	doit "mount ${name}"
done

tstamp "AFS Installation Guide page 3-9"
tstamp "Virtual file system entry for AFS /etc/vfs?"
fgrep afs /etc/vfs > /dev/null
if [[ $? = 0 ]]; then
	tstamp "We already have AFS entry in /etc/vfs"
else
	  tstamp "Adding AFS entry to /etc/vfs..."
	  echo \
"afs     4       none                    none                    remote"\
	  >> /etc/vfs
fi

tstamp "AFS Installation Guide page 3-9"
tstamp "Replacing AIX fsck with AFS fsck"
echo "NB NEVER run standard fsck on an AFS fileserver. It discards AFS volumes."
doit "cd /sbin/helpers; mv v3fshelper v3fshelper.noafs"
doit "cp /usr/afs/bin/v3fshelper /sbin/helpers/v3fshelper"

tstamp "AFS Installation Guide page 5-16"
tstamp "Setup /etc/rc.afs"
doit "mk-afs-rc"

tstamp "Add a call to /etc/rc.afs in /etc/inittab unless it's already there"

egrep "^rcafs:" /etc/inittab > /dev/null
if [[ $? != 0 ]]; then
	tstamp "Changing /etc/inittab to start AFS..."
	sed '/rctcpip/a\
rcafs:2:wait:/etc/rc.afs > /dev/console 2>&1  \# Start AFS Daemons' \
	/etc/inittab > /etc/inittab.new
	doit "mv /etc/inittab /etc/inittab.bak"
	doit "mv /etc/inittab.new /etc/inittab"
	doit "chmod 600 /etc/inittab"
	doit "fgrep rcafs /etc/inittab"
fi

tstamp "AFS Installation Guide, page 3-10"

doit "/usr/afs/bin/bosserver -noauth &"
doit "sleep 60; # wait for bosserver to startup"
doit "/usr/afs/bin/bos status ${HOST}"
doit "bos listhosts ${HOSTNAME}"

tstamp "Check the system type of ${afssystemcontrolmachine}"
tstamp "is the same as ${HOST} before adding bos upclient process"

X=$(< /dev/null rsh ${afssystemcontrolmachine} "/usr/afsws/bin/fs sysname" | cut -d\' -f2)
tstamp "${afssystemcontrolmachine} is ${X}, ${HOST} is ${sysname}"

if [[ "${X}" = "${sysname}" ]]; then
	tstamp "creating bos upclient process"
	doit "bos create ${HOST} upclient simple \"/usr/afs/bin/upclient \
	${afssystemcontrolmachine} -clear /usr/afs/bin\" -cell ${afscellname}"
else
	tstamp "bos upclient process not created: not same sysname"
fi

doit "bos create ${HOST} runntp simple /usr/afs/bin/runntp -cell ${afscellname}"

doit "bos create ${HOST} fs fs /usr/afs/bin/fileserver \
	/usr/afs/bin/volserver /usr/afs/bin/salvager -cell ${afscellname}"

tstamp "AFS Installation Guide, page 3-14"
tstamp "Loading Client Files"

doit "mk-afs-cli"

tstamp "AFS Installation Guide, page 3-15"

tstamp "/usr/afs/bin/klog -principal admin -password \${adminpasswd}"

/usr/afs/bin/klog -principal admin -password ${adminpasswd}

if [[ $? != 0 ]]; then
	fatal "failed to klog"
fi

tstamp "Turn on authorization checking"
doit "tokens"
doit "bos setauth ${HOST} on -cell ${afscellname}"

tstamp "Restart bosserver"
doit "bos restart ${HOST} -bosserver -cell ${afscellname}"

doit "bos status ${HOST} -long"
doit "tokens"

tstamp "Protecting Sensitive AFS Directories"
tstamp "AFS Installation Guide, page 2-74"

doit "chmod 755 /usr/afs"
doit "chmod 755 /usr/afs/bin"
doit "chmod 700 /usr/afs/db"
doit "chmod 755 /usr/afs/etc"
doit "chmod 600 /usr/afs/etc/KeyFile"
doit "chmod 600 /usr/afs/etc/UserList"
doit "chmod 700 /usr/afs/local"
doit "chmod 755 /usr/afs/logs"

T=/tmp/${CMD}.mail.$$
cat <<eeooff >${T}
Greetings,
The initial AFS fileserver installation has completed on ${HOST}.
You will find a log of this process in:

        ${LOG}

No database functions have been configured (eg: kaserver, ptserver, vlserver),
execute mk-afs-dbsm to add these functions.
--
Sincerely,
${CMD} program
eeooff
doit "mail -s \"${HOST}: ${CMD} completed\" ${NOTIFY} <${T}"
cat ${T}
rm ${T}

doit "/usr/afsws/bin/unlog; # Do not leave tokens hanging around!"
tstamp "completed"
