Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

...
  • 3 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
753 overlays/install-overlay/root/beadm.install
View
@@ -0,0 +1,753 @@
+#!/bin/sh -e
+
+# Copyright (c) 2012 Slawomir Wojciech Wojtczak (vermaden). All rights reserved.
+# Copyright (c) 2012 Bryan Drewery (bdrewery). All rights reserved.
+# Copyright (c) 2012 Mike Clarke (rawthey). All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+
+unset LC_ALL
+unset LANG
+PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin
+
+if [ $( uname -r | cut -d '.' -f1 ) -lt 8 ]
+then
+ echo "ERROR: beadm works on FreeBSD 8.0 or later"
+ exit 1
+fi
+
+__usage() {
+ local NAME=${0##*/}
+ echo "usage:"
+ echo " ${NAME} activate <beName>"
+ echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] <beName>"
+ echo " ${NAME} create <beName@snapshot>"
+ echo " ${NAME} destroy [-F] <beName | beName@snapshot>"
+ echo " ${NAME} list [-a] [-s] [-D] [-H]"
+ echo " ${NAME} rename <origBeName> <newBeName>"
+ echo " ${NAME} mount <beName> [mountpoint]"
+ echo " ${NAME} { umount | unmount } [-f] <beName>"
+ exit 1
+}
+
+# check if boot environment exists
+__be_exist() { # 1=DATASET
+ if ! zfs list -H -o name ${1} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Boot environment '${1##*/}' does not exist"
+ exit 1
+ fi
+}
+
+# check if argument is a snapshot
+__be_snapshot() { # 1=DATASET/SNAPSHOT
+ echo "${1}" | grep -q "@" 2> /dev/null
+}
+
+# check if boot environment is mounted
+__be_mounted() { # 1=BE
+ mount 2> /dev/null | grep -q -E "^${1} " 2> /dev/null
+}
+
+# check if boot environment is a clone
+__be_clone() { # 1=DATASET
+ if zfs list ${1} 1> /dev/null 2> /dev/null
+ then
+ local ORIGIN="$( zfs list -H -o origin ${1} )"
+ if [ "${ORIGIN}" = "-" ]
+ then
+ # boot environment is not a clone
+ return 1
+ else
+ # boot environment is a clone
+ return 0
+ fi
+ else
+ # boot environment does not exist
+ return 2
+ fi
+}
+
+# create new boot environment
+__be_new() { # 1=SOURCE 2=TARGET
+ local SOURCE=$( echo ${1} | cut -d '@' -f 1 )
+ if __be_snapshot ${1}
+ then
+ # create boot environment from snapshot
+ local SNAPSHOT=$( echo ${1} | cut -d '@' -f 2 )
+ zfs list -r -H -t filesystem -o name ${SOURCE} \
+ | while read FS
+ do
+ if ! zfs list -H -o name ${FS}@${SNAPSHOT} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Child snapshot '${FS}@${SNAPSHOT}' does not exist"
+ exit 1
+ fi
+ done
+ else
+ # create boot environment from other boot environment
+ if zfs list -H -o name ${1}@${2##*/} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Snapshot '${1}@${2##*/}' already exists"
+ exit 1
+ fi
+ # snapshot format
+ FMT=$( date "+%Y-%m-%d-%H:%M:%S" )
+ if ! zfs snapshot -r ${1}@${FMT} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Cannot create snapshot '${1}@${FMT}'"
+ exit 1
+ fi
+ fi
+ # clone properties of source boot environment
+ zfs list -H -o name -r ${SOURCE} \
+ | while read FS
+ do
+ local OPTS=""
+ while read NAME PROPERTY VALUE
+ do
+ local OPTS="-o ${PROPERTY}=${VALUE} ${OPTS}"
+ done << EOF
+$( zfs get -o name,property,value -s local,received -H all ${FS} | awk '!/[\t ]canmount[\t ]/' )
+EOF
+ DATASET=$( echo ${FS} | awk '{print $1}' | sed -E s/"^${POOL}\/ROOT\/${SOURCE##*/}"/"${POOL}\/ROOT\/${2##*/}"/g )
+ if [ "${OPTS}" = "-o = " ]
+ then
+ local OPTS=""
+ fi
+ if __be_snapshot ${1}
+ then
+ zfs clone -o canmount=off ${OPTS} ${FS}@${1##*@} ${DATASET}
+ else
+ zfs clone -o canmount=off ${OPTS} ${FS}@${FMT} ${DATASET}
+ fi
+ done
+}
+
+ROOTFS=$( mount | awk '/ \/mnt / {print $1}' )
+
+if echo ${ROOTFS} | grep -q -m 1 -E "^/dev/"
+then
+ echo "ERROR: This system does not boot from ZFS pool"
+ exit 1
+fi
+
+POOL=$( echo ${ROOTFS} | awk -F '/' '{print $1}' )
+
+if ! zfs list ${POOL}/ROOT 1> /dev/null 2> /dev/null
+then
+ echo "ERROR: This system is not configured for boot environments"
+ exit 1
+fi
+
+BOOTFS=$( zpool list -H -o bootfs ${POOL} )
+
+if [ -z "${BOOTFS}" -o "${BOOTFS}" = "-" ]
+then
+ echo "ERROR: ZFS boot pool '${POOL}' has unset 'bootfs' property"
+ exit 1
+fi
+
+case ${1} in
+
+ (list) # --------------------------------------------------------------------
+ OPTION_a=0
+ OPTION_D=0
+ OPTION_s=0
+ shift
+ while getopts "aDHs" OPT
+ do
+ case ${OPT} in
+ (a) OPTION_a=1 ;;
+ (D) OPTION_D=1 ;;
+ (H) OPTION_H=1 ;;
+ (s) OPTION_s=1
+ OPTION_a=1 ;;
+ (*) __usage ;;
+ esac
+ done
+ awk -v POOL="${POOL}" \
+ -v ROOTFS="${ROOTFS}" \
+ -v BOOTFS="${BOOTFS}" \
+ -v OPTION_a="${OPTION_a}" \
+ -v OPTION_D="${OPTION_D}" \
+ -v OPTION_H="${OPTION_H}" \
+ -v OPTION_s="${OPTION_s}" \
+ 'function __normalize(VALUE) {
+ if(VALUE == "-" || VALUE == 0)
+ return 0
+ else
+ return substr(VALUE, 1, length(VALUE) - 1) * MULTIPLIER[substr(VALUE, length(VALUE))]
+ }
+ function __show_units(VALUE) {
+ if(VALUE < 1024) { UNIT = "K"; }
+ else if(VALUE < 1048576) { VALUE /= 1024; UNIT = "M"; }
+ else if(VALUE < 1073741824) { VALUE /= 1048576; UNIT = "G"; }
+ else if(VALUE < 1099511627776) { VALUE /= 1073741824; UNIT = "T"; }
+ else if(VALUE < 1125899906842624) { VALUE /= 1099511627776; UNIT = "P"; }
+ else if(VALUE < 1152921504606846976) { VALUE /= 1125899906842624; UNIT = "E"; }
+ else { VALUE /= 1152921504606846976; UNIT = "Z"; }
+ return sprintf("%.1f%s", VALUE, UNIT)
+ }
+ function __get_bename(BENAME) {
+ sub(BENAME_BEGINS_WITH "\/", "", BENAME)
+ sub("/.*", "", BENAME)
+ return BENAME
+ }
+ function __convert_date(DATE) {
+ CMD_DATE = "date -j -f \"%a %b %d %H:%M %Y\" \"" DATE "\" +\"%Y-%m-%d %H:%M\""
+ CMD_DATE | getline NEW
+ close(CMD_DATE)
+ return NEW
+ }
+ BEGIN {
+ BENAME_BEGINS_WITH = POOL "/ROOT"
+ MULTIPLIER["K"] = 1
+ MULTIPLIER["M"] = 1024
+ MULTIPLIER["G"] = 1048576
+ MULTIPLIER["T"] = 1073741824
+ MULTIPLIER["P"] = 1099511627776
+ MULTIPLIER["E"] = 1125899906842624
+ MULTIPLIER["Z"] = 1152921504606846976
+ MOUNTPOINT_LENGTH = 10
+ FSNAME_LENGTH = 2
+ if(OPTION_a == 1)
+ FSNAME_LENGTH = 19
+ CMD_MOUNT="mount"
+ while(CMD_MOUNT | getline)
+ if($1 ~ "^" BENAME_BEGINS_WITH)
+ MOUNTS[$1] = $3
+ close(CMD_MOUNT)
+ FS = "\\t"
+ CMD_ZFS_LIST = "zfs list -H -t all -s creation -o name,used,usedds,usedbysnapshots,usedrefreserv,refer,creation,origin -r "
+ while(CMD_ZFS_LIST BENAME_BEGINS_WITH | getline) {
+ if($1 != BENAME_BEGINS_WITH) {
+ FSNAME = $1
+ FSNAMES[length(FSNAMES) + 1] = FSNAME
+ USED = __normalize($2)
+ USEDBYDATASET = __normalize($3)
+ USEDBYSNAPSHOTS = __normalize($4)
+ USEDREFRESERV = __normalize($5)
+ REFER[FSNAME] = __normalize($6)
+ CREATIONS[FSNAME] = $7
+ ORIGINS[FSNAME] = $8
+ if(FSNAME ~ /@/)
+ SPACES[FSNAME] = USED
+ else {
+ SPACES[FSNAME] = USEDBYDATASET + USEDREFRESERV
+ if(OPTION_D != 1)
+ SPACES[FSNAME] += USEDBYSNAPSHOTS
+ BE = " " __get_bename(FSNAME) " "
+ if(index(BELIST, BE) == 0)
+ BELIST = BELIST " " BE
+ MOUNTPOINT = MOUNTS[FSNAME]
+ if(MOUNTPOINT) {
+ if((OPTION_a == 0 && FSNAME == (BENAME_BEGINS_WITH "/" __get_bename(FSNAME))) || (OPTION_a == 1)) {
+ LM = length(MOUNTPOINT)
+ if(LM > MOUNTPOINT_LENGTH)
+ MOUNTPOINT_LENGTH = LM
+ }
+ }
+ else
+ MOUNTPOINT = "-"
+ }
+ if(OPTION_a == 1)
+ LF = length(FSNAME)
+ else if(FSNAME !~ /@/)
+ LF = length(__get_bename(FSNAME))
+ if(LF > FSNAME_LENGTH)
+ FSNAME_LENGTH = LF
+ }
+ }
+ close(CMD_ZFS_LIST)
+ split(BELIST, BENAMES, " ")
+ if(OPTION_a == 1) {
+ BE_HEAD = "BE/Dataset/Snapshot"
+ printf "%-" FSNAME_LENGTH + 2 "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", BE_HEAD, "Active", "Mountpoint", "Space", "Created"
+ }
+ else if(OPTION_H == 1)
+ BE_HEAD = ""
+ else {
+ BE_HEAD = "BE"
+ printf "%-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", BE_HEAD, "Active", "Mountpoint", "Space", "Created"
+ }
+ if(OPTION_s != 1)
+ SNAPSHOT_FILTER = "(/[^@]*)?$"
+ for(I = 1; I <= length(BENAMES); I++) {
+ BENAME = BENAMES[I]
+ if(OPTION_a == 1) {
+ printf "\n"
+ print BENAME
+ for(J = 1; J <= length(FSNAMES); J++) {
+ FSNAME = FSNAMES[J]
+ if(FSNAME ~ "^" BENAME_BEGINS_WITH "/" BENAME SNAPSHOT_FILTER) {
+ ACTIVE = ""
+ if(FSNAME == ROOTFS)
+ ACTIVE = ACTIVE "N"
+ if(FSNAME == BOOTFS)
+ ACTIVE = ACTIVE "R"
+ if(! ACTIVE)
+ ACTIVE = "-"
+ MOUNTPOINT = MOUNTS[FSNAME]
+ if(! MOUNTPOINT)
+ MOUNTPOINT = "-"
+ printf " %-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", FSNAME, ACTIVE, MOUNTPOINT, __show_units(SPACES[FSNAME]), __convert_date(CREATIONS[FSNAME])
+ ORIGIN = ORIGINS[FSNAME]
+ ORIGIN_DISPLAY = ORIGIN
+ sub(BENAME_BEGINS_WITH "/", "", ORIGIN_DISPLAY)
+ if(ORIGIN != "-") {
+ if(OPTION_D == 1)
+ SPACE = REFER[ORIGIN]
+ else
+ SPACE = SPACES[ORIGIN]
+ printf " %-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", " " ORIGIN_DISPLAY, "-", "-", __show_units(SPACE), __convert_date(CREATIONS[ORIGIN])
+ }
+ }
+ }
+ }
+ else {
+ SPACE = 0
+ ACTIVE = ""
+ NAME = BENAME_BEGINS_WITH "/" BENAME
+ if(NAME == ROOTFS)
+ ACTIVE = ACTIVE "N"
+ if(NAME == BOOTFS)
+ ACTIVE = ACTIVE "R"
+ if(! ACTIVE)
+ ACTIVE = "-"
+ for(J = 1; J <= length(FSNAMES); J++) {
+ FSNAME = FSNAMES[J]
+ if(FSNAME ~ "^" BENAME_BEGINS_WITH "/" BENAME "(/[^@]*)?$") {
+ if((BENAME_BEGINS_WITH "/" BENAME) == FSNAME) {
+ MOUNTPOINT = MOUNTS[FSNAME]
+ if(! MOUNTPOINT)
+ MOUNTPOINT = "-"
+ CREATION = __convert_date(CREATIONS[FSNAME])
+ }
+ ORIGIN = ORIGINS[FSNAME]
+ if(ORIGIN == "-")
+ SPACE += SPACES[FSNAME]
+ else {
+ if(OPTION_D == 1)
+ SPACE += REFER[FSNAME]
+ else
+ SPACE += SPACES[FSNAME] + SPACES[ORIGIN]
+ }
+ }
+ }
+ if(OPTION_H == 1)
+ printf "%s\t%s\t%s\t%s\t%s\n", BENAME, ACTIVE, MOUNTPOINT, __show_units(SPACE), CREATION
+ else
+ printf "%-" FSNAME_LENGTH "s %-6s %-" MOUNTPOINT_LENGTH "s %6s %s\n", BENAME, ACTIVE, MOUNTPOINT, __show_units(SPACE), CREATION
+ }
+ }
+ }'
+ ;;
+
+ (create) # ------------------------------------------------------------------
+ case ${#} in
+ (4)
+ if ! [ ${2} = "-e" ]
+ then
+ __usage
+ fi
+ # check if argument for -e option is full path dataset
+ # argument for -e option must be 'beName' or 'beName@snapshot'
+ if echo ${3} | grep -q "/" 2> /dev/null
+ then
+ __usage
+ fi
+ __be_exist ${POOL}/ROOT/${3}
+ if zfs list -H -o name ${POOL}/ROOT/${4} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Boot environment '${4}' already exists"
+ exit 1
+ fi
+ __be_new ${POOL}/ROOT/${3} ${POOL}/ROOT/${4}
+ ;;
+ (2)
+ if __be_snapshot ${2}
+ then
+ if ! zfs snapshot -r ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Cannot create '${2}' recursive snapshot"
+ exit 1
+ fi
+ else
+ __be_new ${ROOTFS} ${POOL}/ROOT/${2}
+ fi
+ ;;
+ (*)
+ __usage
+ ;;
+ esac
+ echo "Created successfully"
+ ;;
+
+ (activate) # ----------------------------------------------------------------
+ if [ ${#} -ne 2 ]
+ then
+ __usage
+ fi
+ __be_exist ${POOL}/ROOT/${2}
+ if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
+ then
+ echo "Already activated"
+ exit 0
+ else
+ if __be_mounted ${POOL}/ROOT/${2}
+ then
+ MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' )
+ if [ "${MNT}" != "/" ]
+ then
+ # boot environment is not current root and its mounted
+ echo "ERROR: Boot environment '${2}' is mounted at '${MNT}'"
+ echo "ERROR: Cannot activate manually mounted boot environment"
+ exit 1
+ fi
+ fi
+ # do not change root (/) mounted boot environment mountpoint
+ if [ "${ROOTFS}" != "${POOL}/ROOT/${2}" ]
+ then
+ TMPMNT=$( mktemp -d -t BE-${2} )
+ if ! mkdir -p ${TMPMNT} 2> /dev/null
+ then
+ echo "ERROR: Cannot create '${TMPMNT}' directory"
+ exit 1
+ fi
+ MOUNT=0
+ while read FS MNT TYPE OPTS DUMP FSCK;
+ do
+ if [ "${FS}" = "${POOL}/ROOT/${2}" ]
+ then
+ MOUNT=${MNT}
+ break
+ fi
+ done << EOF
+$( mount -p )
+EOF
+ if [ ${MOUNT} -eq 0 ]
+ then
+ zfs set canmount=noauto ${POOL}/ROOT/${2}
+ zfs set mountpoint=${TMPMNT} ${POOL}/ROOT/${2}
+ zfs mount ${POOL}/ROOT/${2}
+ else
+ TMPMNT=${MOUNT}
+ fi
+ cp /boot/zfs/zpool.cache ${TMPMNT}/boot/zfs/zpool.cache
+ LOADER_CONFIGS=${TMPMNT}/boot/loader.conf
+ if [ -f ${TMPMNT}/boot/loader.conf.local ]
+ then
+ LOADER_CONFIGS="${LOADER_CONFIGS} ${TMPMNT}/boot/loader.conf.local"
+ fi
+ sed -i '' -E s/"^vfs.root.mountfrom=.*$"/"vfs.root.mountfrom=\"zfs:${POOL}\/ROOT\/${2##*/}\""/g ${LOADER_CONFIGS}
+ if [ ${MOUNT} -eq 0 ]
+ then
+ zfs umount ${POOL}/ROOT/${2}
+ zfs set mountpoint=legacy ${POOL}/ROOT/${2}
+ fi
+ fi
+ if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Failed to activate '${2}' boot environment"
+ exit 1
+ fi
+ fi
+ # execute ZFS LIST only once
+ ZFS_LIST=$( zfs list -H -o name -r ${POOL}/ROOT )
+ # disable automatic mount on all inactive boot environments
+ echo "${ZFS_LIST}" \
+ | grep -v "^${POOL}/ROOT/${2}$" \
+ | grep -v "^${POOL}/ROOT/${2}/" \
+ | while read NAME
+ do
+ zfs set canmount=noauto ${NAME}
+ done
+ # enable automatic mount for active boot environment and promote it
+ echo "${ZFS_LIST}" \
+ | grep -E "^${POOL}/ROOT/${2}(/|$)" \
+ | while read NAME
+ do
+ zfs set canmount=on ${NAME}
+ while __be_clone ${NAME}
+ do
+ zfs promote ${NAME}
+ done
+ done
+ echo "Activated successfully"
+ ;;
+
+ (destroy) # -----------------------------------------------------------------
+ if [ "${2}" != "-F" ]
+ then
+ DESTROY=${2}
+ else
+ DESTROY=${3}
+ fi
+ __be_exist ${POOL}/ROOT/${DESTROY}
+ case ${#} in
+ (2)
+ echo "Are you sure you want to destroy '${2}'?"
+ echo -n "This action cannot be undone (y/[n]): "
+ read CHOICE
+ ;;
+ (3)
+ if [ "${2}" != "-F" ]
+ then
+ __usage
+ fi
+ CHOICE=Y
+ ;;
+ (*)
+ __usage
+ ;;
+ esac
+ if [ "${BOOTFS}" = "${POOL}/ROOT/${DESTROY}" ]
+ then
+ echo "ERROR: Cannot destroy active boot environment"
+ exit 1
+ fi
+ case ${CHOICE} in
+ (Y|y|[Yy][Ee][Ss])
+ # destroy snapshot or boot environment
+ if __be_snapshot ${POOL}/ROOT/${DESTROY}
+ then
+ # destroy desired snapshot
+ if ! zfs destroy -r ${POOL}/ROOT/${DESTROY} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Snapshot '${2}' is origin for other boot environment"
+ exit 1
+ fi
+ else
+ if __be_clone ${POOL}/ROOT/${DESTROY}
+ then
+ # promote clones dependent on snapshots used by destroyed boot environment
+ zfs list -H -t all -o name,origin \
+ | while read NAME ORIGIN
+ do
+ if echo "${ORIGIN}" | grep -q -E "${POOL}/ROOT/${DESTROY}(/.*@|@)" 2> /dev/null
+ then
+ zfs promote ${NAME}
+ fi
+ done
+ # get origins used by destroyed boot environment
+ ORIGIN_SNAPSHOTS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} | grep -v '^-$' | awk -F "@" '{print $2}' | sort -u )
+ fi
+ # check if boot environment was created from existing snapshot
+ ORIGIN=$( zfs list -H -o origin ${POOL}/ROOT/${DESTROY} )
+ CREATION=$( zfs list -H -o creation ${POOL}/ROOT/${DESTROY} )
+ CREATION=$( date -j -f "%a %b %d %H:%M %Y" "${CREATION}" +"%Y-%m-%d-%H:%M" )
+ SNAPSHOT_NAME=$( echo "${ORIGIN}" | cut -d '@' -f 2 | sed -E 's/:[0-9]{2}$//g' )
+ if [ "${2}" = "-F" ]
+ then
+ CHOICE=1
+ elif [ "${SNAPSHOT_NAME}" != "${CREATION}" ]
+ then
+ ORIGIN=$( basename ${ORIGIN} )
+ echo "Boot environment '${DESTROY}' was created from existing snapshot"
+ echo -n "Destroy '${ORIGIN}' snapshot? (y/[n]): "
+ read CHOICE
+ case ${CHOICE} in
+ (Y|y|[Yy][Ee][Ss])
+ CHOICE=1
+ ;;
+ (*)
+ CHOICE=0
+ echo "Origin snapshot '${ORIGIN}' will be preserved"
+ ;;
+ esac
+ else
+ CHOICE=1
+ fi
+ # destroy boot environment
+ zfs destroy -r ${POOL}/ROOT/${DESTROY}
+ # check if boot environment is a clone
+ if __be_clone ${POOL}/ROOT/${DESTROY}
+ then
+ # promote datasets dependent on origins used by destroyed boot environment
+ ALL_ORIGINS=$( zfs list -H -t all -o name,origin )
+ echo "${ORIGIN_SNAPSHOTS}" \
+ | while read S
+ do
+ echo "${ALL_ORIGINS}" \
+ | grep "${S}" \
+ | awk '{print $1}' \
+ | while read I
+ do
+ zfs promote ${I}
+ done
+ done
+ fi
+ # destroy origins used by destroyed boot environment
+ SNAPSHOTS=$( zfs list -H -t snapshot -o name )
+ echo "${ORIGIN_SNAPSHOTS}" \
+ | while read S
+ do
+ echo "${SNAPSHOTS}" \
+ | grep "@${S}$" \
+ | while read I
+ do
+ if [ ${CHOICE} -eq 1 ]
+ then
+ zfs destroy ${I}
+ fi
+ done
+ done
+ fi
+ echo "Destroyed successfully"
+ ;;
+ (*)
+ echo "Boot environment '${DESTROY}' has not been destroyed"
+ ;;
+ esac
+ ;;
+
+ (rename) # ------------------------------------------------------------------
+ if [ ${#} -ne 3 ]
+ then
+ __usage
+ fi
+ __be_exist ${POOL}/ROOT/${2}
+ if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
+ then
+ echo "ERROR: Renaming active boot environment is not supported"
+ exit 1
+ fi
+ if zfs list -H -o name ${POOL}/ROOT/${3} 2> /dev/null
+ then
+ echo "ERROR: Boot environment '${3}' already exists"
+ exit 1
+ fi
+ zfs rename ${POOL}/ROOT/${2} ${POOL}/ROOT/${3}
+ echo "Renamed successfully"
+ ;;
+
+ (mount) # ------------------------------------------------------------
+ if [ ${#} -eq 2 ]
+ then
+ TARGET=$( mktemp -d -t BE-${2} )
+ elif [ ${#} -eq 3 ]
+ then
+ TARGET=${3}
+ else
+ __usage
+ fi
+ __be_exist "${POOL}/ROOT/${2}"
+ if __be_mounted "${POOL}/ROOT/${2}"
+ then
+ MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' )
+ echo "Boot environment '${2}' is already mounted at '${MNT}'"
+ exit 1
+ fi
+ if ! mkdir -p ${TARGET} 2> /dev/null
+ then
+ echo "ERROR: Cannot create '${TARGET}' mountpoint"
+ exit 1
+ fi
+ if ! mount -t zfs ${POOL}/ROOT/${2} ${TARGET}
+ then
+ echo "ERROR: Cannot mount '${2}' at '${TARGET}' mountpoint"
+ exit 1
+ fi
+ PREFIX=$( echo ${POOL}/ROOT/${2}/ | sed 's/\//\\\//g' )
+ zfs list -H -o name,mountpoint -r ${POOL}/ROOT/${2} \
+ | grep -v -E "[[:space:]](legacy|none)$" \
+ | sort -n \
+ | grep -E "^${POOL}/ROOT/${2}/" \
+ | while read FS MOUNTPOINT
+ do
+ if [ "{FS}" != "${POOL}/ROOT/${2}" ]
+ then
+ INHERIT=$( zfs get -H -o source mountpoint ${FS} )
+ if [ "${INHERIT}" = "local" ]
+ then
+ case ${MOUNTPOINT} in
+ (legacy|none)
+ continue
+ ;;
+ (*)
+ MOUNTPOINT="/$( echo "${FS}" | sed s/"${PREFIX}"//g )"
+ ;;
+ esac
+ fi
+ fi
+ if ! mkdir -p ${TARGET}${MOUNTPOINT} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Cannot create '${TARGET}${MOUNTPOINT}' mountpoint"
+ exit 1
+ fi
+ if ! mount -t zfs ${FS} ${TARGET}${MOUNTPOINT} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Cannot mount '${FS}' at '${TARGET}${MOUNTPOINT}' mountpoint"
+ exit 1
+ fi
+ done
+ echo "Mounted successfully on '${TARGET}'"
+ ;;
+
+ (umount|unmount) # ----------------------------------------------------------
+ if [ ${#} -eq 2 ]
+ then
+ # we need this empty section for argument checking
+ :
+ elif [ ${#} -eq 3 -a "${2}" = "-f" ]
+ then
+ OPTS="-f"
+ shift
+ else
+ __usage
+ fi
+ __be_exist "${POOL}/ROOT/${2}"
+ if ! __be_mounted "${POOL}/ROOT/${2}"
+ then
+ echo "Boot environment '${2}' is not mounted"
+ exit 1
+ fi
+ MOUNT=$( mount )
+ MOUNTPOINT=$( echo "${MOUNT}" | grep -m 1 "^${POOL}/ROOT/${2} on " | awk '{print $3}' )
+ echo "${MOUNT}" \
+ | awk '{print $1}' \
+ | grep -E "^${POOL}/ROOT/${2}(/|$)" \
+ | sort -n -r \
+ | while read FS
+ do
+ if ! umount ${OPTS} ${FS} 1> /dev/null 2> /dev/null
+ then
+ echo "ERROR: Cannot umount '${FS}' dataset"
+ exit 1
+ fi
+ done
+ echo "Unmounted successfully"
+ # only delete the temporary mountpoint directory
+ if echo "${MOUNTPOINT}" | grep -q -E "/BE-${2}\.[a-zA-Z0-9]{8}" 1> /dev/null 2> /dev/null
+ then
+ # delete only when it is an empty directory
+ if [ $( find ${MOUNTPOINT} | head | wc -l | bc ) -eq 1 ]
+ then
+ rm -r ${MOUNTPOINT}
+ fi
+ fi
+ ;;
+
+ (*) # -----------------------------------------------------------------------
+ __usage
+ ;;
+
+esac
18 src-sh/pc-extractoverlay/ports-overlay/usr/local/etc/grub.d/10_ktrueos
View
@@ -129,6 +129,18 @@ detect_beadm()
{
which -s beadm
if [ $? -ne 0 ] ; then return 0; fi
+
+ # Check if we are running from the installer and use its beadm
+ if [ -e "/root/beadm.install" ] ; then
+ BEADM="/root/beadm.install"
+ else
+ BEADM="`which beadm`"
+ fi
+
+ ${BEADM} list >/dev/null 2>/dev/null
+ if [ $? -ne 0 ] ; then return 0; fi
+
+
if [ -e "/etc/defaults/pcbsd" ] ; then
NICK="PC-BSD"
else
@@ -136,10 +148,10 @@ detect_beadm()
fi
# Get list of beadm datasets
- for b in `beadm list 2>/dev/null| grep -v "Created" | cut -d ' ' -f 1`
+ for b in `${BEADM} list 2>/dev/null| grep -v "Created" | cut -d ' ' -f 1`
do
# Got a beadm snapshot, lets get the complete dataset name
- cdataset=`beadm list -a | grep "/ROOT/${b}" | awk '{print $1}'`
+ cdataset=`${BEADM} list -a | grep "/ROOT/${b}" | awk '{print $1}'`
ztank=`echo $cdataset | cut -d '/' -f 1`
shortdataset="/`echo $cdataset | cut -d '/' -f 2-5`"
@@ -157,7 +169,7 @@ EOF
# Now lets look for options in loader.conf to load
loadPrefix="${shortdataset}"
# If this is the current mounted dataset, we can skip mounting it
- mount | grep -q "$cdataset on / ("
+ mount | grep -q -e "$cdataset on / (" -e "$cdataset on /mnt ("
if [ $? -eq 0 ] ; then
display_loaderopts
else
9 src-sh/pc-sysinstall/backend/functions-unmount.sh
View
@@ -228,6 +228,12 @@ setup_grub()
# Mount devfs
rc_halt "mount -t devfs devfs ${FSMNT}/dev"
+ # Check for a custom beadm.install to copy before we run grub
+ if [ -e "/root/beadm.install" ] ; then
+ rc_halt "cp /root/beadm.install ${FSMNT}/root/beadm.install"
+ rc_halt "chmod 755 ${FSMNT}/root/beadm.install"
+ fi
+
# Make sure to copy zpool.cache first
rc_nohalt "cp /boot/zfs/zpool.cache ${FSMNT}/boot/zfs/"
@@ -253,6 +259,9 @@ setup_grub()
rc_halt "chroot ${FSMNT} grub-mkconfig -o /boot/grub/grub.cfg"
# Sleep and cleanup
+ if [ -e "${FSMNT}/root/beadm.install" ] ; then
+ rc_halt "rm ${FSMNT}/root/beadm.install"
+ fi
sleep 5
rc_halt "umount ${FSMNT}/dev"
};

No commit comments for this range

Something went wrong with that request. Please try again.