#!/bin/sh
# $FiG: config/freebsd/builder01/root/bin/create-and-populate-new-BE-separate-bootpool-rootpool.sh,v 1.1 2019-01-23 13:35:41 trond Exp $
# $BSDnet: config/freebsd/enterprise/root/bin/create-and-populate-new-BE-separate-bootpool-rootpool.sh,v 1.2 2019-01-23 13:46:44 trond Exp $
#set -x

# Specify where to place the typescripts.
#TYPESCRIPT_DIR=/mnt/root/tmp
TYPESCRIPT_DIR=/usr/src

# Specify where the bootpool BE is mounted, typically /bootpool.
BOOTPOOL_ROOT=/bootpool

# Specify where to temporary mount the new BEs, typically /mnt.
DESTDIR=/mnt

# Specify which svn executable to run.
#SVN=/usr/bin/svnlite
SVN=/usr/local/bin/svn

# Ensure / is of type ZFS.
if [ -z "`/bin/df -Tt zfs /`" ]; then
  echo $0: root filesystem must be of type ZFS >/dev/stderr
  exit 69
fi

# Ensure ${BOOTPOOL_ROOT}/boot/loader.conf exists.
if [ ! -f ${BOOTPOOL_ROOT}/boot/loader.conf ]; then
  echo $0: ${BOOTPOOL_ROOT}/boot/loader.conf does not exist >/dev/stderr
  exit 69
fi

# Ensure /usr/src is mounted, be it NFS or local fs.
if [ ! -f /usr/src/Makefile ]; then
  /sbin/mount /usr/src

  if [ ! -f /usr/src/Makefile ]; then
    echo $0: unable to mount /usr/src >/dev/stderr
    exit 69
  fi
fi

# Ensure /usr/obj is mounted, be it NFS or local fs.
if [ ! -d /usr/obj/usr ]; then
  /sbin/mount /usr/obj

  if [ ! -d /usr/obj/usr ]; then
    echo $0: unable to mount /usr/obj >/dev/stderr
    exit 69
  fi
fi

# What's the name of the current bootpool BE?
CURRENT_BOOTPOOL_BE=`/bin/df ${BOOTPOOL_ROOT} | /usr/bin/tail -1 | /usr/bin/awk '{print $1}'`
if [ -z "${CURRENT_BOOTPOOL_BE}" ]; then
  echo "$0: zero length CURRENT_BOOTPOOL_BE" >/dev/stderr
  exit 69
fi

# What's the name of the current rootpool BE?
CURRENT_ROOTPOOL_BE=`/bin/df / | /usr/bin/tail -1 | /usr/bin/awk '{print $1}'`
if [ -z "${CURRENT_ROOTPOOL_BE}" ]; then
  echo "$0: zero length CURRENT_ROOTPOOL_BE" >/dev/stderr
  exit 69
fi

# What's the current date given local time?
CURRENT_DATE=`/bin/date +%Y%m%d`
if [ -z "${CURRENT_DATE}" ]; then
  echo "$0: zero length CURRENT_DATE" >/dev/stderr
  exit 69
fi

# What's the global revision number?
#SVN_REVISION=`/usr/bin/grep 'Revision' /usr/src/svn-info.txt | /usr/bin/cut -d ' ' -f 2`
SVN_REVISION=`${SVN} info --show-item revision /usr/src`
if [ -z "${SVN_REVISION}" ]; then
  echo "$0: zero length SVN_REVISION" >/dev/stderr
  exit 69
fi

# Construct the name of the bootpool snapshot.
NEW_BOOTPOOL_SNAPSHOT="${CURRENT_BOOTPOOL_BE}@r${SVN_REVISION}"

# Get the root of the bootpool BEs.
BOOTPOOL_BE_ROOT=`/usr/bin/dirname ${CURRENT_BOOTPOOL_BE}`
if [ -z "${BOOTPOOL_BE_ROOT}" ]; then
  echo "$0: zero length BOOTPOOL_BE_ROOT" >/dev/stderr
  exit 69
fi

# Get the name of the boot pool.
BOOT_POOL=`echo ${BOOTPOOL_BE_ROOT} | /usr/bin/cut -d / -f 1`
if [ -z "${BOOT_POOL}" ]; then
  echo "$0: zero length BOOT_POOL" >/dev/stderr
  exit 69
fi

# Construct the name of the new bootpool BE.
NEW_BOOTPOOL_BE="${BOOTPOOL_BE_ROOT}/${CURRENT_DATE}-r${SVN_REVISION}"

# Construct the name of the rootpool snapshot.
NEW_ROOTPOOL_SNAPSHOT="${CURRENT_ROOTPOOL_BE}@r${SVN_REVISION}"

# Get the root of the rootpool BEs.
ROOTPOOL_BE_ROOT=`/usr/bin/dirname ${CURRENT_ROOTPOOL_BE}`
if [ -z "${ROOTPOOL_BE_ROOT}" ]; then
  echo "$0: zero length ROOTPOOL_BE_ROOT" >/dev/stderr
  exit 69
fi

# Get the name of the root pool.
ROOT_POOL=`echo ${ROOTPOOL_BE_ROOT} | /usr/bin/cut -d / -f 1`
if [ -z "${ROOT_POOL}" ]; then
  echo "$0: zero length ROOT_POOL" >/dev/stderr
  exit 69
fi

# Construct the name of the new rootpool BE.
NEW_ROOTPOOL_BE="${ROOTPOOL_BE_ROOT}/${CURRENT_DATE}-r${SVN_REVISION}"

# Run pre-flight checks. This is an interactive step.
/usr/sbin/mergemaster -Fp || exit

# Create the rootpool snapshot and the new rootpool BE.
/sbin/zfs snapshot ${NEW_ROOTPOOL_SNAPSHOT} || exit
/sbin/zfs clone -o mountpoint=${DESTDIR} ${NEW_ROOTPOOL_SNAPSHOT} ${NEW_ROOTPOOL_BE} || exit

# Create the bootpool snapshot and the new bootpool BE.
/sbin/zfs snapshot ${NEW_BOOTPOOL_SNAPSHOT} || exit
/sbin/zfs clone -o mountpoint=${DESTDIR}${BOOTPOOL_ROOT} ${NEW_BOOTPOOL_SNAPSHOT} ${NEW_BOOTPOOL_BE} || exit

# Update vfs.root.mountfrom in ${DESTDIR}${BOOTPOOL_ROOT}/boot/loader.conf to point to the new rootpool BE.
/usr/bin/sed -i '' "s|^vfs\\.root\\.mountfrom=\".*\"\$|vfs.root.mountfrom=\"zfs:${NEW_ROOTPOOL_BE}\"|" ${DESTDIR}${BOOTPOOL_ROOT}/boot/loader.conf || exit

# Merge any changes to the configuration files. This is an interactive step.
/usr/sbin/mergemaster -D ${DESTDIR} -Fi || exit

# Ensure we have somewhere to place the typescripts.
if [ ! -d ${TYPESCRIPT_DIR} ]; then
  /bin/mkdir -p ${TYPESCRIPT_DIR}

  if [ ! -d ${TYPESCRIPT_DIR} ]; then
    echo $0: unable to create ${TYPESCRIPT_DIR} >/dev/stderr
    exit 69
  fi
fi

# Remove previous typescripts.
#/bin/rm -f -- ${TYPESCRIPT_DIR}/make-installworld-installkernel-*.txt ${TYPESCRIPT_DIR}/make-check-old-*.txt ${TYPESCRIPT_DIR}/make-delete-old-*.txt

# Install new world and kernel into the new BE.
/usr/bin/script -at 0 ${TYPESCRIPT_DIR}/make-installworld-installkernel-${CURRENT_DATE}-r${SVN_REVISION}.txt /usr/bin/make -C /usr/src -j `/sbin/sysctl -n hw.ncpu` DESTDIR=${DESTDIR} installworld installkernel || exit

# Check to see if there's something old and outdated.
/usr/bin/script -at 0 ${TYPESCRIPT_DIR}/make-check-old-${CURRENT_DATE}-r${SVN_REVISION}.txt /usr/bin/make -C /usr/src DESTDIR=${DESTDIR} check-old || exit

# Remove any old files.
/usr/bin/script -at 0 ${TYPESCRIPT_DIR}/make-delete-old-${CURRENT_DATE}-r${SVN_REVISION}.txt /usr/bin/make -C /usr/src -D BATCH_DELETE_OLD_FILES DESTDIR=${DESTDIR} delete-old || exit

# Remove any old libraries.
/usr/bin/script -at 0 ${TYPESCRIPT_DIR}/make-delete-old-libs-${CURRENT_DATE}-r${SVN_REVISION}.txt /usr/bin/make -C /usr/src -D BATCH_DELETE_OLD_FILES DESTDIR=${DESTDIR} delete-old-libs || exit

# Check to see if there's still something old and outdated.
/usr/bin/script -at 0 ${TYPESCRIPT_DIR}/make-check-old-${CURRENT_DATE}-r${SVN_REVISION}.txt /usr/bin/make -C /usr/src DESTDIR=${DESTDIR} check-old || exit

# Unmount the NFS mounted filesystems if needed.
if [ "`/bin/df -T /usr/src | /usr/bin/tail -1 | /usr/bin/awk '{print $2}'`" = "nfs" ]; then
  /sbin/umount /usr/src || exit
fi
if [ "`/bin/df -T /usr/obj | /usr/bin/tail -1 | /usr/bin/awk '{print $2}'`" = "nfs" ]; then
  /sbin/umount /usr/obj || exit
fi

# Unconditionally remove any traces of any (false) NFS mounts.
/bin/rm -f -- ${DESTDIR}/var/db/mounttab

# Inherit the mountpoint for the current bootpool BE.
/sbin/zfs inherit mountpoint ${CURRENT_BOOTPOOL_BE} || exit

# Update the mountpoint for the new bootpool BE.
/sbin/zfs set mountpoint=${BOOTPOOL_ROOT} ${NEW_BOOTPOOL_BE} || exit

# Set the bootfs zpool property on the bootpool.
/sbin/zpool set bootfs=${NEW_BOOTPOOL_BE} ${BOOT_POOL} || exit

# Inherit the mountpoint for the new rootpool BE.
/sbin/zfs inherit mountpoint ${NEW_ROOTPOOL_BE} || exit

# Ready to reboot into the new bootpool BE.
echo $0: ready to boot into ${NEW_BOOTPOOL_BE}

# EOF
