2018-11-07 10:36:54 -07:00
#!/bin/sh
2020-04-14 11:52:29 +02:00
#
2025-01-11 14:07:41 -05:00
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright (c) 2018-2025, Christer Edwards <christer.edwards@gmail.com>
2018-11-07 10:36:54 -07:00
# All rights reserved.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# * Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
2020-04-14 11:52:29 +02:00
#
2018-11-07 10:36:54 -07:00
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2020-08-30 10:57:14 -04:00
. /usr/local/share/bastille/common.sh
2018-11-07 10:36:54 -07:00
usage( ) {
2025-05-18 17:16:17 -06:00
error_notify "Usage: bastille upgrade [option(s)] TARGET NEW_RELEASE|install"
2025-01-14 13:03:36 -07:00
cat << EOF
2025-04-30 13:39:05 -06:00
2025-01-14 13:03:36 -07:00
Options:
2018-11-07 10:36:54 -07:00
2025-01-14 13:03:36 -07:00
-a | --auto Auto mode. Start/stop jail( s) if required.
-f | --force Force upgrade a release.
-x | --debug Enable debug mode.
2018-11-07 10:36:54 -07:00
2025-01-14 13:03:36 -07:00
EOF
exit 1
}
# Handle options.
2025-02-28 22:46:27 -07:00
AUTO = 0
2025-01-14 13:03:36 -07:00
OPTION = ""
while [ " $# " -gt 0 ] ; do
case " ${ 1 } " in
-h| --help| help )
usage
; ;
-a| --auto)
AUTO = 1
shift
; ;
-f| --force)
OPTION = "-F"
shift
; ;
-x| --debug)
enable_debug
shift
; ;
-*)
for _opt in $( echo ${ 1 } | sed 's/-//g' | fold -w1) ; do
case ${ _opt } in
a) AUTO = 1 ; ;
f) OPTION = "-F" ; ;
x) enable_debug ; ;
2025-05-01 17:39:50 -06:00
*) error_exit " [ERROR]: Unknown Option: \" ${ 1 } \" " ; ;
2025-01-14 13:03:36 -07:00
esac
done
shift
; ;
*)
break
; ;
esac
done
if [ $# -lt 2 ] || [ $# -gt 3 ] ; then
2018-11-07 10:36:54 -07:00
usage
fi
2025-01-14 13:03:36 -07:00
TARGET = " ${ 1 } "
NEWRELEASE = " ${ 2 } "
2020-11-21 00:33:06 -04:00
2025-01-14 13:03:36 -07:00
bastille_root_check
2025-04-04 16:15:05 -06:00
set_target_single " ${ TARGET } "
2018-11-07 10:36:54 -07:00
2025-01-14 13:03:36 -07:00
# Check for unsupported actions
2021-07-14 13:57:09 -04:00
if [ -f "/bin/midnightbsd-version" ] ; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Not yet supported on MidnightBSD."
2021-02-26 16:55:56 -05:00
fi
2020-02-20 18:06:31 -04:00
if freebsd-version | grep -qi HBSD; then
2025-05-01 17:39:50 -06:00
error_exit "[ERROR]: Not yet supported on HardenedBSD."
2019-05-22 21:50:29 -06:00
fi
2025-02-28 22:46:27 -07:00
thick_jail_check( ) {
2025-04-30 18:49:14 -06:00
2025-04-04 16:15:05 -06:00
local _jail = " ${ 1 } "
2025-04-30 18:49:14 -06:00
2025-05-01 17:39:50 -06:00
# Validate jail state
2025-04-04 16:15:05 -06:00
check_target_is_running " ${ _jail } " || if [ " ${ AUTO } " -eq 1 ] ; then
bastille start " ${ _jail } "
2025-04-30 08:19:50 -06:00
else
2025-04-30 18:49:14 -06:00
info " \n[ ${ _jail } ]: "
2025-01-14 13:03:36 -07:00
error_notify "Jail is not running."
2025-04-04 16:15:05 -06:00
error_exit "Use [-a|--auto] to auto-start the jail."
2020-11-21 00:33:06 -04:00
fi
}
2025-02-28 22:46:27 -07:00
thin_jail_check( ) {
2025-04-30 18:49:14 -06:00
2025-04-04 16:15:05 -06:00
local _jail = " ${ 1 } "
2025-04-30 18:49:14 -06:00
2025-05-01 17:39:50 -06:00
# Validate jail state
2025-04-04 16:15:05 -06:00
check_target_is_stopped " ${ _jail } " || if [ " ${ AUTO } " -eq 1 ] ; then
bastille stop " ${ _jail } "
2025-04-30 08:19:50 -06:00
else
2025-04-30 18:49:14 -06:00
info " \n[ ${ _jail } ]: "
2025-02-28 22:46:27 -07:00
error_notify "Jail is running."
2025-04-04 16:15:05 -06:00
error_exit "Use [-a|--auto] to auto-stop the jail."
2025-02-28 22:46:27 -07:00
fi
}
2020-11-22 20:01:14 -04:00
release_check( ) {
2025-04-30 18:49:14 -06:00
2025-04-04 17:37:15 -06:00
local _release = " ${ 1 } "
2025-04-30 18:49:14 -06:00
2020-11-22 20:01:14 -04:00
# Validate the release
2025-04-04 17:37:15 -06:00
if ! echo " ${ _release } " | grep -q "[0-9]\{2\}.[0-9]-[RELEASE,BETA,RC]" ; then
2025-05-01 17:39:50 -06:00
error_exit " [ERROR]: ${ _release } is not a valid release. "
2020-11-22 20:01:14 -04:00
fi
2025-04-30 18:49:14 -06:00
2025-02-28 22:55:05 -07:00
# Exit if NEWRELEASE doesn't exist
if [ " ${ THIN_JAIL } " -eq 1 ] ; then
2025-04-04 17:37:15 -06:00
if [ ! -d " ${ bastille_releasesdir } / ${ _release } " ] ; then
2025-05-01 17:39:50 -06:00
error_notify " [ERROR]: Release not found: ${ _release } "
2025-04-04 17:37:15 -06:00
error_exit " See 'bastille bootstrap ${ _release } to bootstrap the release. "
2025-02-28 22:55:05 -07:00
fi
fi
2020-11-22 20:01:14 -04:00
}
2025-01-14 13:03:36 -07:00
jail_upgrade( ) {
2025-04-30 18:49:14 -06:00
2025-01-14 13:03:36 -07:00
local _jailname = " ${ 1 } "
2025-05-01 17:39:50 -06:00
2025-02-28 22:55:05 -07:00
if [ " ${ THIN_JAIL } " -eq 1 ] ; then
local _oldrelease = " $( bastille config ${ _jailname } get osrelease) "
else
2025-04-04 16:15:05 -06:00
local _oldrelease = " $( jexec -l ${ _jailname } freebsd-version) "
2025-02-28 22:55:05 -07:00
fi
2025-01-14 13:03:36 -07:00
local _newrelease = " ${ 2 } "
2025-04-04 16:15:05 -06:00
local _jailpath = " ${ bastille_jailsdir } / ${ _jailname } /root "
2025-01-16 07:25:49 -07:00
local _workdir = " ${ _jailpath } /var/db/freebsd-update "
local _freebsd_update_conf = " ${ _jailpath } /etc/freebsd-update.conf "
2025-01-14 13:03:36 -07:00
# Upgrade a thin jail
2025-04-04 16:15:05 -06:00
if grep -qw " ${ bastille_jailsdir } / ${ _jailname } /root/.bastille " " ${ bastille_jailsdir } / ${ _jailname } /fstab " ; then
2025-05-15 08:20:00 -06:00
if [ " ${ _oldrelease } " = "not set" ] ; then
2025-05-15 08:06:48 -06:00
_oldrelease = " $( grep " ${ bastille_releasesdir } .*\.bastille.*nullfs.* " " ${ bastille_jailsdir } / ${ _jailname } /fstab " | awk -F"/releases/" '{print $2}' | awk '{print $1}' ) "
fi
2025-01-14 13:03:36 -07:00
local _newrelease = " ${ NEWRELEASE } "
2025-04-04 16:15:05 -06:00
# Update "osrelease" entry inside fstab
sed -i '' " /.bastille/ s| ${ _oldrelease } | ${ _newrelease } |g " " ${ bastille_jailsdir } / ${ _jailname } /fstab "
2025-05-15 08:24:18 -06:00
# Update "osrelease" inside jail.conf using 'bastille config'
bastille config ${ _jailname } set osrelease ${ _newrelease }
2025-04-04 16:15:05 -06:00
# Start jail if AUTO=1
if [ " ${ AUTO } " -eq 1 ] ; then
bastille start " ${ _jailname } "
fi
2025-05-01 17:39:50 -06:00
info " \nUpgraded ${ _jailname } : ${ _oldrelease } -> ${ _newrelease } "
2025-04-30 18:49:14 -06:00
echo "See 'bastille etcupdate TARGET' to update /etc/rc.conf"
2020-11-21 00:33:06 -04:00
else
2025-01-14 13:03:36 -07:00
# Upgrade a thick jail
env PAGER = "/bin/cat" freebsd-update ${ OPTION } --not-running-from-cron \
--currently-running " ${ _oldrelease } " \
2025-01-16 07:27:48 -07:00
-j " ${ _jailname } " \
2025-01-14 13:03:36 -07:00
-d " ${ _workdir } " \
-f " ${ _freebsd_update_conf } " \
2025-01-14 13:22:30 -07:00
-r " ${ _newrelease } " upgrade
2025-05-15 08:24:18 -06:00
# Update "osrelease" inside jail.conf using 'bastille config'
bastille config ${ _jailname } set osrelease ${ _newrelease }
2025-05-01 17:39:50 -06:00
warn " Please run 'bastille upgrade ${ _jailname } install', restart the jail, then run 'bastille upgrade ${ _jailname } install' again to finish installing updates. "
2020-11-21 00:33:06 -04:00
fi
}
jail_updates_install( ) {
2025-04-30 18:49:14 -06:00
2025-01-17 12:27:11 -07:00
local _jailname = " ${ 1 } "
2025-04-04 16:15:05 -06:00
local _jailpath = " ${ bastille_jailsdir } / ${ _jailname } /root "
2025-01-16 07:25:49 -07:00
local _workdir = " ${ _jailpath } /var/db/freebsd-update "
local _freebsd_update_conf = " ${ _jailpath } /etc/freebsd-update.conf "
2025-04-30 18:49:14 -06:00
2020-11-21 00:33:06 -04:00
# Finish installing upgrade on a thick container
2025-04-04 16:15:05 -06:00
if [ -d " ${ bastille_jailsdir } / ${ _jailname } " ] ; then
2025-01-14 13:03:36 -07:00
env PAGER = "/bin/cat" freebsd-update ${ OPTION } --not-running-from-cron \
2025-01-16 07:27:48 -07:00
-j " ${ _jailname } " \
2025-01-14 13:03:36 -07:00
-d " ${ _workdir } " \
-f " ${ _freebsd_update_conf } " \
install
2020-11-21 00:33:06 -04:00
else
2025-05-01 17:39:50 -06:00
error_exit " [ERROR]: ${ _jailname } not found. See 'bastille bootstrap RELEASE'. "
2021-01-09 21:24:05 -04:00
fi
}
2025-02-28 22:46:27 -07:00
# Check if jail is thick or thin
THIN_JAIL = 0
if grep -qw " ${ bastille_jailsdir } / ${ TARGET } /root/.bastille " " ${ bastille_jailsdir } / ${ TARGET } /fstab " ; then
THIN_JAIL = 1
fi
2020-11-21 00:33:06 -04:00
# Check what we should upgrade
2025-01-14 13:03:36 -07:00
if [ " ${ NEWRELEASE } " = "install" ] ; then
2025-02-28 22:46:27 -07:00
if [ " ${ THIN_JAIL } " -eq 1 ] ; then
2025-04-04 16:15:05 -06:00
thin_jail_check " ${ TARGET } "
2025-02-28 22:46:27 -07:00
else
2025-04-04 16:15:05 -06:00
thick_jail_check " ${ TARGET } "
2025-02-28 22:46:27 -07:00
fi
2025-04-30 18:49:14 -06:00
info " \n[ ${ TARGET } ]: "
2025-01-17 12:27:11 -07:00
jail_updates_install " ${ TARGET } "
2018-11-07 10:36:54 -07:00
else
2025-04-04 17:37:15 -06:00
release_check " ${ NEWRELEASE } "
2025-02-28 22:46:27 -07:00
if [ " ${ THIN_JAIL } " -eq 1 ] ; then
2025-04-04 16:15:05 -06:00
thin_jail_check " ${ TARGET } "
2025-02-28 22:46:27 -07:00
else
2025-04-04 16:15:05 -06:00
thick_jail_check " ${ TARGET } "
2025-02-28 22:46:27 -07:00
fi
2025-04-30 18:49:14 -06:00
info " \n[ ${ TARGET } ]: "
2025-01-14 13:03:36 -07:00
jail_upgrade " ${ TARGET } " " ${ NEWRELEASE } "
2025-05-15 08:06:48 -06:00
fi