1#!/bin/sh 2# 3# Copyright (c) 2016 Will Andrews 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer 11# in this position and unchanged. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27# $FreeBSD$ 28# 29## 30# Install a boot environment using the current FreeBSD source tree. 31# Requires a fully built world & kernel. 32# 33# Non-base tools required: beadm, pkg 34# 35# In a sandbox for the new boot environment, this script also runs etcupdate 36# and pkg upgrade automatically in the sandbox. Upon successful completion, 37# the system will be ready to boot into the new boot environment. Upon 38# failure, the target boot environment will be destroyed. In all cases, the 39# running system is left untouched. 40# 41## Usage: 42# beinstall [optional world/kernel flags e.g. KERNCONF] 43# 44## User modifiable variables - set these in the environment if desired. 45# If not empty, 'pkg upgrade' will be skipped. 46NO_PKG_UPGRADE="${NO_PKG_UPGRADE:-""}" 47# Config updater - 'etcupdate' and 'mergemaster' are supported. Set to an 48# empty string to skip. 49CONFIG_UPDATER="${CONFIG_UPDATER:-"etcupdate"}" 50# Flags for etcupdate if used. 51ETCUPDATE_FLAGS="${ETCUPDATE_FLAGS:-"-F"}" 52# Flags for mergemaster if used. 53MERGEMASTER_FLAGS="${MERGEMASTER_FLAGS:-"-iFU"}" 54 55 56######################################################################## 57## Constants 58ETCUPDATE_CMD="etcupdate" 59MERGEMASTER_CMD="mergemaster" 60 61## Functions 62cleanup() { 63 [ -z "${cleanup_commands}" ] && return 64 echo "Cleaning up ..." 65 for command in ${cleanup_commands}; do 66 ${command} 67 done 68} 69 70errx() { 71 cleanup 72 echo "error: $*" 73 exit 1 74} 75 76rmdir_be() { 77 chflags -R noschg ${BE_MNTPT} 78 rm -rf ${BE_MNTPT} 79} 80 81cleanup_be() { 82 beadm destroy -F ${BENAME} 83} 84 85update_mergemaster() { 86 mergemaster -m $(pwd) -D ${BE_MNTPT} -t ${BE_MM_ROOT} ${MERGEMASTER_FLAGS} 87} 88 89update_etcupdate() { 90 etcupdate -s $(pwd) -D ${BE_MNTPT} ${ETCUPDATE_FLAGS} || return $? 91 etcupdate resolve -D ${BE_MNTPT} 92} 93 94 95cleanup_commands="" 96trap 'errx "Interrupt caught"' HUP INT TERM 97 98[ "$(whoami)" != "root" ] && errx "Must be run as root" 99 100[ ! -f "Makefile.inc1" ] && errx "Must be in FreeBSD source tree" 101objdir=$(make -V .OBJDIR 2>/dev/null) 102[ ! -d "${objdir}" ] && errx "Must have built FreeBSD from source tree" 103 104if [ -d .git ] ; then 105 commit_time=$(git show --format='%ct' 2>/dev/null | head -1) 106 [ $? -ne 0 ] && errx "Can't lookup git commit timestamp" 107 commit_ts=$(date -r ${commit_time} '+%Y%m%d.%H%M%S') 108elif [ -d .svn ] ; then 109 commit_ts=$( svn info | awk '/Last Changed Date/ {print $4 "." $5}' | tr -d :- ) 110 [ $? -ne 0 ] && errx "Can't lookup Subversion commit timestamp" 111else 112 errx "Unable to determine sandbox type" 113fi 114 115commit_ver=$(${objdir}/bin/freebsd-version/freebsd-version -u 2>/dev/null) 116[ -z "${commit_ver}" ] && errx "Unable to determine FreeBSD version" 117 118BENAME="${commit_ver}-${commit_ts}" 119 120BE_TMP=$(mktemp -d /tmp/beinstall.XXXXXX) 121[ $? -ne 0 -o ! -d ${BE_TMP} ] && errx "Unable to create mountpoint" 122[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="rmdir_be ${cleanup_commands}" 123BE_MNTPT=${BE_TMP}/mnt 124BE_MM_ROOT=${BE_TMP}/mergemaster # mergemaster will create 125mkdir -p ${BE_MNTPT} 126 127beadm create ${BENAME} >/dev/null || errx "Unable to create BE ${BENAME}" 128[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="cleanup_be ${cleanup_commands}" 129 130beadm mount ${BENAME} ${BE_TMP}/mnt || errx "Unable to mount BE ${BENAME}." 131 132echo "Mounted ${BENAME} to ${BE_MNTPT}, performing install/update ..." 133make $* DESTDIR=${BE_MNTPT} installkernel || errx "Installkernel failed!" 134make $* DESTDIR=${BE_MNTPT} installworld || errx "Installworld failed!" 135 136if [ -n "${CONFIG_UPDATER}" ]; then 137 "update_${CONFIG_UPDATER}" 138 [ $? -ne 0 ] && errx "${CONFIG_UPDATER} failed!" 139fi 140 141BE_PKG="chroot ${BE_MNTPT} env ASSUME_ALWAYS_YES=true pkg" 142if [ -z "${NO_PKG_UPGRADE}" ]; then 143 ${BE_PKG} update || errx "Unable to update pkg" 144 ${BE_PKG} upgrade || errx "Unable to upgrade pkgs" 145fi 146 147beadm unmount ${BENAME} || errx "Unable to unmount BE" 148rmdir_be 149beadm activate ${BENAME} || errx "Unable to activate BE" 150echo 151beadm list 152echo 153echo "Boot environment ${BENAME} setup complete; reboot to use it." 154