1462819bbSWill Andrews#!/bin/sh 2462819bbSWill Andrews# 3462819bbSWill Andrews# Copyright (c) 2016 Will Andrews 4462819bbSWill Andrews# All rights reserved. 5462819bbSWill Andrews# 6462819bbSWill Andrews# Redistribution and use in source and binary forms, with or without 7462819bbSWill Andrews# modification, are permitted provided that the following conditions 8462819bbSWill Andrews# are met: 9462819bbSWill Andrews# 1. Redistributions of source code must retain the above copyright 10462819bbSWill Andrews# notice, this list of conditions and the following disclaimer 11462819bbSWill Andrews# in this position and unchanged. 12462819bbSWill Andrews# 2. Redistributions in binary form must reproduce the above copyright 13462819bbSWill Andrews# notice, this list of conditions and the following disclaimer in the 14462819bbSWill Andrews# documentation and/or other materials provided with the distribution. 15462819bbSWill Andrews# 16462819bbSWill Andrews# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17462819bbSWill Andrews# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18462819bbSWill Andrews# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19462819bbSWill Andrews# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20462819bbSWill Andrews# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21462819bbSWill Andrews# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22462819bbSWill Andrews# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23462819bbSWill Andrews# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24462819bbSWill Andrews# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25462819bbSWill Andrews# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26462819bbSWill Andrews# 27462819bbSWill Andrews# $FreeBSD$ 28462819bbSWill Andrews# 29462819bbSWill Andrews## 30462819bbSWill Andrews# Install a boot environment using the current FreeBSD source tree. 31462819bbSWill Andrews# Requires a fully built world & kernel. 32462819bbSWill Andrews# 33462819bbSWill Andrews# Non-base tools required: beadm, pkg 34462819bbSWill Andrews# 35462819bbSWill Andrews# In a sandbox for the new boot environment, this script also runs etcupdate 36462819bbSWill Andrews# and pkg upgrade automatically in the sandbox. Upon successful completion, 37462819bbSWill Andrews# the system will be ready to boot into the new boot environment. Upon 38462819bbSWill Andrews# failure, the target boot environment will be destroyed. In all cases, the 39462819bbSWill Andrews# running system is left untouched. 40462819bbSWill Andrews# 41462819bbSWill Andrews## Usage: 42462819bbSWill Andrews# beinstall [optional world/kernel flags e.g. KERNCONF] 43462819bbSWill Andrews# 44462819bbSWill Andrews## User modifiable variables - set these in the environment if desired. 45462819bbSWill Andrews# If not empty, 'pkg upgrade' will be skipped. 46462819bbSWill AndrewsNO_PKG_UPGRADE="${NO_PKG_UPGRADE:-""}" 47462819bbSWill Andrews# Config updater - 'etcupdate' and 'mergemaster' are supported. Set to an 48462819bbSWill Andrews# empty string to skip. 49462819bbSWill AndrewsCONFIG_UPDATER="${CONFIG_UPDATER:-"etcupdate"}" 50462819bbSWill Andrews# Flags for etcupdate if used. 51462819bbSWill AndrewsETCUPDATE_FLAGS="${ETCUPDATE_FLAGS:-"-F"}" 52462819bbSWill Andrews# Flags for mergemaster if used. 53462819bbSWill AndrewsMERGEMASTER_FLAGS="${MERGEMASTER_FLAGS:-"-iFU"}" 54462819bbSWill Andrews 55462819bbSWill Andrews 56462819bbSWill Andrews######################################################################## 57462819bbSWill Andrews## Constants 58462819bbSWill AndrewsETCUPDATE_CMD="etcupdate" 59462819bbSWill AndrewsMERGEMASTER_CMD="mergemaster" 60462819bbSWill Andrews 61462819bbSWill Andrews## Functions 62462819bbSWill Andrewscleanup() { 63462819bbSWill Andrews [ -z "${cleanup_commands}" ] && return 64462819bbSWill Andrews echo "Cleaning up ..." 65462819bbSWill Andrews for command in ${cleanup_commands}; do 66462819bbSWill Andrews ${command} 67462819bbSWill Andrews done 68462819bbSWill Andrews} 69462819bbSWill Andrews 70462819bbSWill Andrewserrx() { 71462819bbSWill Andrews cleanup 72*fc3bfe91SEitan Adler echo "error: $@" 73462819bbSWill Andrews exit 1 74462819bbSWill Andrews} 75462819bbSWill Andrews 76462819bbSWill Andrewsrmdir_be() { 77462819bbSWill Andrews chflags -R noschg ${BE_MNTPT} 78462819bbSWill Andrews rm -rf ${BE_MNTPT} 79462819bbSWill Andrews} 80462819bbSWill Andrews 81462819bbSWill Andrewscleanup_be() { 82462819bbSWill Andrews beadm destroy -F ${BENAME} 83462819bbSWill Andrews} 84462819bbSWill Andrews 85462819bbSWill Andrewsupdate_mergemaster() { 86462819bbSWill Andrews mergemaster -m $(pwd) -D ${BE_MNTPT} -t ${BE_MM_ROOT} ${MERGEMASTER_FLAGS} 87462819bbSWill Andrews} 88462819bbSWill Andrews 89462819bbSWill Andrewsupdate_etcupdate() { 90462819bbSWill Andrews etcupdate -s $(pwd) -D ${BE_MNTPT} ${ETCUPDATE_FLAGS} || return $? 91462819bbSWill Andrews etcupdate resolve -D ${BE_MNTPT} 92462819bbSWill Andrews} 93462819bbSWill Andrews 94462819bbSWill Andrews 95462819bbSWill Andrewscleanup_commands="" 96462819bbSWill Andrewstrap 'errx "Interrupt caught"' HUP INT TERM 97462819bbSWill Andrews 98462819bbSWill Andrews[ "$(whoami)" != "root" ] && errx "Must be run as root" 99462819bbSWill Andrews 100462819bbSWill Andrews[ ! -f "Makefile.inc1" ] && errx "Must be in FreeBSD source tree" 101462819bbSWill Andrewsobjdir=$(make -V .OBJDIR 2>/dev/null) 102462819bbSWill Andrews[ ! -d "${objdir}" ] && errx "Must have built FreeBSD from source tree" 103462819bbSWill Andrews 1047d4a3185SWill Andrews# May be a worktree, in which case .git is a file, not a directory. 1057d4a3185SWill Andrewsif [ -e .git ] ; then 106462819bbSWill Andrews commit_time=$(git show --format='%ct' 2>/dev/null | head -1) 107462819bbSWill Andrews [ $? -ne 0 ] && errx "Can't lookup git commit timestamp" 108462819bbSWill Andrews commit_ts=$(date -r ${commit_time} '+%Y%m%d.%H%M%S') 109462819bbSWill Andrewselif [ -d .svn ] ; then 110*fc3bfe91SEitan Adler if [ -e /usr/bin/svnlite ]; then 111*fc3bfe91SEitan Adler svn=/usr/bin/svnlite 112*fc3bfe91SEitan Adler elif [ -e /usr/local/bin/svn ]; then 113*fc3bfe91SEitan Adler svn=/usr/local/bin/svn 1141ff30c6aSBrad Davis else 115*fc3bfe91SEitan Adler errx "Unable to find subversion" 1161ff30c6aSBrad Davis fi 117*fc3bfe91SEitan Adler commit_ts="$( "$svn" info --show-item last-changed-date | sed -e 's/\..*//' -e 's/T/./' -e 's/-//g' -e s'/://g' )" 118462819bbSWill Andrews [ $? -ne 0 ] && errx "Can't lookup Subversion commit timestamp" 119462819bbSWill Andrewselse 120*fc3bfe91SEitan Adler errx "Unable to determine source control type" 121462819bbSWill Andrewsfi 122462819bbSWill Andrews 123462819bbSWill Andrewscommit_ver=$(${objdir}/bin/freebsd-version/freebsd-version -u 2>/dev/null) 124462819bbSWill Andrews[ -z "${commit_ver}" ] && errx "Unable to determine FreeBSD version" 125462819bbSWill Andrews 126462819bbSWill AndrewsBENAME="${commit_ver}-${commit_ts}" 127462819bbSWill Andrews 128462819bbSWill AndrewsBE_TMP=$(mktemp -d /tmp/beinstall.XXXXXX) 129462819bbSWill Andrews[ $? -ne 0 -o ! -d ${BE_TMP} ] && errx "Unable to create mountpoint" 130462819bbSWill Andrews[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="rmdir_be ${cleanup_commands}" 131462819bbSWill AndrewsBE_MNTPT=${BE_TMP}/mnt 132462819bbSWill AndrewsBE_MM_ROOT=${BE_TMP}/mergemaster # mergemaster will create 133462819bbSWill Andrewsmkdir -p ${BE_MNTPT} 134462819bbSWill Andrews 135462819bbSWill Andrewsbeadm create ${BENAME} >/dev/null || errx "Unable to create BE ${BENAME}" 136462819bbSWill Andrews[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="cleanup_be ${cleanup_commands}" 137462819bbSWill Andrews 138462819bbSWill Andrewsbeadm mount ${BENAME} ${BE_TMP}/mnt || errx "Unable to mount BE ${BENAME}." 139462819bbSWill Andrews 140462819bbSWill Andrewsecho "Mounted ${BENAME} to ${BE_MNTPT}, performing install/update ..." 141*fc3bfe91SEitan Adlermake "$@" DESTDIR=${BE_MNTPT} installkernel || errx "Installkernel failed!" 142*fc3bfe91SEitan Adlermake "$@" DESTDIR=${BE_MNTPT} installworld || errx "Installworld failed!" 143462819bbSWill Andrews 144462819bbSWill Andrewsif [ -n "${CONFIG_UPDATER}" ]; then 145462819bbSWill Andrews "update_${CONFIG_UPDATER}" 146462819bbSWill Andrews [ $? -ne 0 ] && errx "${CONFIG_UPDATER} failed!" 147462819bbSWill Andrewsfi 148462819bbSWill Andrews 149462819bbSWill AndrewsBE_PKG="chroot ${BE_MNTPT} env ASSUME_ALWAYS_YES=true pkg" 150462819bbSWill Andrewsif [ -z "${NO_PKG_UPGRADE}" ]; then 151462819bbSWill Andrews ${BE_PKG} update || errx "Unable to update pkg" 152462819bbSWill Andrews ${BE_PKG} upgrade || errx "Unable to upgrade pkgs" 153462819bbSWill Andrewsfi 154462819bbSWill Andrews 155462819bbSWill Andrewsbeadm unmount ${BENAME} || errx "Unable to unmount BE" 156462819bbSWill Andrewsrmdir_be 157462819bbSWill Andrewsbeadm activate ${BENAME} || errx "Unable to activate BE" 158462819bbSWill Andrewsecho 159462819bbSWill Andrewsbeadm list 160462819bbSWill Andrewsecho 161462819bbSWill Andrewsecho "Boot environment ${BENAME} setup complete; reboot to use it." 162