xref: /freebsd/tools/build/beinstall.sh (revision fc3bfe916e603950f509aeec656fa7112646971d)
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
104# May be a worktree, in which case .git is a file, not a directory.
105if [ -e .git ] ; then
106    commit_time=$(git show --format='%ct' 2>/dev/null | head -1)
107    [ $? -ne 0 ] && errx "Can't lookup git commit timestamp"
108    commit_ts=$(date -r ${commit_time} '+%Y%m%d.%H%M%S')
109elif [ -d .svn ] ; then
110      if [ -e /usr/bin/svnlite ]; then
111        svn=/usr/bin/svnlite
112      elif [ -e /usr/local/bin/svn ]; then
113        svn=/usr/local/bin/svn
114      else
115        errx "Unable to find subversion"
116      fi
117      commit_ts="$( "$svn" info --show-item last-changed-date | sed -e 's/\..*//' -e 's/T/./' -e 's/-//g' -e s'/://g' )"
118    [ $? -ne 0 ] && errx "Can't lookup Subversion commit timestamp"
119else
120    errx "Unable to determine source control type"
121fi
122
123commit_ver=$(${objdir}/bin/freebsd-version/freebsd-version -u 2>/dev/null)
124[ -z "${commit_ver}" ] && errx "Unable to determine FreeBSD version"
125
126BENAME="${commit_ver}-${commit_ts}"
127
128BE_TMP=$(mktemp -d /tmp/beinstall.XXXXXX)
129[ $? -ne 0 -o ! -d ${BE_TMP} ] && errx "Unable to create mountpoint"
130[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="rmdir_be ${cleanup_commands}"
131BE_MNTPT=${BE_TMP}/mnt
132BE_MM_ROOT=${BE_TMP}/mergemaster # mergemaster will create
133mkdir -p ${BE_MNTPT}
134
135beadm create ${BENAME} >/dev/null || errx "Unable to create BE ${BENAME}"
136[ -z "$NO_CLEANUP_BE" ] && cleanup_commands="cleanup_be ${cleanup_commands}"
137
138beadm mount ${BENAME} ${BE_TMP}/mnt || errx "Unable to mount BE ${BENAME}."
139
140echo "Mounted ${BENAME} to ${BE_MNTPT}, performing install/update ..."
141make "$@" DESTDIR=${BE_MNTPT} installkernel || errx "Installkernel failed!"
142make "$@" DESTDIR=${BE_MNTPT} installworld || errx "Installworld failed!"
143
144if [ -n "${CONFIG_UPDATER}" ]; then
145	"update_${CONFIG_UPDATER}"
146	[ $? -ne 0 ] && errx "${CONFIG_UPDATER} failed!"
147fi
148
149BE_PKG="chroot ${BE_MNTPT} env ASSUME_ALWAYS_YES=true pkg"
150if [ -z "${NO_PKG_UPGRADE}" ]; then
151	${BE_PKG} update || errx "Unable to update pkg"
152	${BE_PKG} upgrade || errx "Unable to upgrade pkgs"
153fi
154
155beadm unmount ${BENAME} || errx "Unable to unmount BE"
156rmdir_be
157beadm activate ${BENAME} || errx "Unable to activate BE"
158echo
159beadm list
160echo
161echo "Boot environment ${BENAME} setup complete; reboot to use it."
162