Rewrite && and || into if/then/else syntax which fixes some bugs.

This commit is contained in:
Slawomir Wojciech Wojtczak (vermaden) 2012-05-05 08:11:43 +02:00
parent 87501e9de4
commit 8c2047d87f
1 changed files with 125 additions and 56 deletions

181
beadm
View File

@ -26,8 +26,10 @@ unset LC_ALL
unset LANG unset LANG
PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin
[ $( uname -r | cut -d '.' -f1 ) -lt 8 ] \ if [ $( uname -r | cut -d '.' -f1 ) -lt 8 ]
&& echo "ERROR: beadm only works on FreeBSD 8.0 or later." then
echo "ERROR: beadm only works on FreeBSD 8.0 or later."
fi
__usage() { __usage() {
NAME=${0##*/} NAME=${0##*/}
@ -46,10 +48,11 @@ __usage() {
} }
__be_exist() { # 1=DATASET __be_exist() { # 1=DATASET
zfs list -H -o name ${1} 1> /dev/null 2> /dev/null || { if ! zfs list -H -o name ${1} 1> /dev/null 2> /dev/null
then
echo "ERROR: Boot environment '${1##*/}' does not exist" echo "ERROR: Boot environment '${1##*/}' does not exist"
exit 1 exit 1
} fi
} }
__be_snapshot() { # 1=DATASET/SNAPSHOT __be_snapshot() { # 1=DATASET/SNAPSHOT
@ -57,18 +60,21 @@ __be_snapshot() { # 1=DATASET/SNAPSHOT
} }
__be_new() { # 1=SOURCE 2=TARGET __be_new() { # 1=SOURCE 2=TARGET
__be_snapshot ${1} && { if __be_snapshot ${1}
then
zfs clone ${1} ${2} zfs clone ${1} ${2}
} || { else
zfs list -H -o name ${1}@${2##*/} 1> /dev/null 2> /dev/null && { if zfs list -H -o name ${1}@${2##*/} 1> /dev/null 2> /dev/null
then
echo "ERROR: Snapshot '${1}@${2##*/}' exists" echo "ERROR: Snapshot '${1}@${2##*/}' exists"
exit 1 exit 1
} fi
zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null || { if ! zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null
then
echo "ERROR: Cannot create snapshot '${1}@${2##*/}'" echo "ERROR: Cannot create snapshot '${1}@${2##*/}'"
exit 1 exit 1
} fi
} fi
zfs list -H -o name -t filesystem -r ${1} \ zfs list -H -o name -t filesystem -r ${1} \
| while read FS | while read FS
do do
@ -82,7 +88,10 @@ EOF
SOURCE=${1##*/} SOURCE=${1##*/}
TARGET=${2##*/} TARGET=${2##*/}
DATASET=$( echo ${FS} | awk '{print $1}' | sed -E s/"^${POOL}\/ROOT\/${SOURCE}"/"${POOL}\/ROOT\/${TARGET}"/g ) DATASET=$( echo ${FS} | awk '{print $1}' | sed -E s/"^${POOL}\/ROOT\/${SOURCE}"/"${POOL}\/ROOT\/${TARGET}"/g )
[ "${OPTS}" = "-o =" ] && OPTS="" if [ "${OPTS}" = "-o = " ]
then
OPTS=""
fi
zfs clone -o canmount=noauto ${OPTS} ${FS}@${2##*/} ${DATASET} zfs clone -o canmount=noauto ${OPTS} ${FS}@${2##*/} ${DATASET}
MOUNT=$( zfs get -H -o value mountpoint ${FS} ) MOUNT=$( zfs get -H -o value mountpoint ${FS} )
zfs set mountpoint=${MOUNT} ${DATASET} zfs set mountpoint=${MOUNT} ${DATASET}
@ -91,14 +100,25 @@ EOF
} }
ROOTFS=$( mount | awk '/ \/ / {print $1}' ) ROOTFS=$( mount | awk '/ \/ / {print $1}' )
echo ${ROOTFS} | grep -q -E "^/dev/" && {
if echo ${ROOTFS} | grep -q -E "^/dev/"
then
echo "ERROR: This system does not boot from ZFS pool" echo "ERROR: This system does not boot from ZFS pool"
exit 1 exit 1
} fi
POOL=$( echo ${ROOTFS} | awk -F '/' '{print $1}' ) 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} ) BOOTFS=$( zpool list -H -o bootfs ${POOL} )
case ${1} in case ${1} in
(list) # -------------------------------------------------------------------- (list) # --------------------------------------------------------------------
POOL_PREFIX="${POOL}/ROOT" POOL_PREFIX="${POOL}/ROOT"
LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" ) LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" )
@ -112,9 +132,18 @@ case ${1} in
do do
NAME=${NAME##*/} NAME=${NAME##*/}
unset ACTIVE unset ACTIVE
[ "${POOL_PREFIX}/${NAME}" = "${ROOTFS}" ] && ACTIVE="${ACTIVE}N" if [ "${POOL_PREFIX}/${NAME}" = "${ROOTFS}" ]
[ "${POOL_PREFIX}/${NAME}" = "${BOOTFS}" ] && ACTIVE="${ACTIVE}R" then
[ -z "${ACTIVE}" ] && ACTIVE="-" ACTIVE="${ACTIVE}N"
fi
if [ "${POOL_PREFIX}/${NAME}" = "${BOOTFS}" ]
then
ACTIVE="${ACTIVE}R"
fi
if [ -z "${ACTIVE}" ]
then
ACTIVE="-"
fi
printf "%-${WIDTH_NAME}s %-6s " ${NAME} ${ACTIVE} printf "%-${WIDTH_NAME}s %-6s " ${NAME} ${ACTIVE}
case ${ACTIVE} in case ${ACTIVE} in
(N|NR) MOUNT="/" ;; (N|NR) MOUNT="/" ;;
@ -124,60 +153,92 @@ case ${1} in
date -j -f "%a %b %d %H:%M %Y" "${C} ${R} ${E} ${A} ${T}" +"%Y-%m-%d %H:%M" date -j -f "%a %b %d %H:%M %Y" "${C} ${R} ${E} ${A} ${T}" +"%Y-%m-%d %H:%M"
done done
;; ;;
(create) # ------------------------------------------------------------------ (create) # ------------------------------------------------------------------
case ${#} in case ${#} in
(4) (4)
[ ${2} = "-e" ] || __usage if [ ${2} = "-e" ]
then
__usage
fi
__be_exist ${POOL}/ROOT/${3} __be_exist ${POOL}/ROOT/${3}
zfs list -H -o name ${POOL}/ROOT/${4} 2> /dev/null && { if zfs list -H -o name ${POOL}/ROOT/${4} 2> /dev/null
then
echo "ERROR: Boot environment '${4}' already exists" echo "ERROR: Boot environment '${4}' already exists"
exit 1 exit 1
} fi
__be_new ${POOL}/ROOT/${3} ${POOL}/ROOT/${4} __be_new ${POOL}/ROOT/${3} ${POOL}/ROOT/${4}
;; ;;
(2) (2)
__be_snapshot ${2} && { if __be_snapshot ${2}
zfs snapshot ${POOL}/ROOT/${2} 2> /dev/null || { then
if zfs snapshot ${POOL}/ROOT/${2} 2> /dev/null
then
echo "ERROR: Cannot create '${2}' snapshot" echo "ERROR: Cannot create '${2}' snapshot"
exit 1 exit 1
} fi
echo "Created successfully" echo "Created successfully"
} || { else
__be_new ${ROOTFS} ${POOL}/ROOT/${2} __be_new ${ROOTFS} ${POOL}/ROOT/${2}
} fi
;; ;;
(*) (*)
__usage __usage
;; ;;
esac esac
;; ;;
(activate) # ---------------------------------------------------------------- (activate) # ----------------------------------------------------------------
__be_exist ${POOL}/ROOT/${2} __be_exist ${POOL}/ROOT/${2}
[ "${BOOTFS}" = "${POOL}/ROOT/${2}" ] && { if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
then
echo "Already activated" echo "Already activated"
exit 0 exit 0
} || { else
[ "${ROOTFS}" = "${POOL}/ROOT/${2}" ] || { if [ "${ROOTFS}" != "${POOL}/ROOT/${2}" ]
MNT="/tmp/BE" then
mkdir -p ${MNT} || { TMPMNT="/tmp/BE"
echo "ERROR: Cannot create '${MNT}' directory" if ! mkdir -p ${TMPMNT}
then
echo "ERROR: Cannot create '${TMPMNT}' directory"
exit 1 exit 1
} fi
zfs set mountpoint=${MNT} ${POOL}/ROOT/${2} MOUNT=0
zfs mount ${POOL}/ROOT/${2} while read FS MNT
cp /boot/zfs/zpool.cache ${MNT}/boot/zfs/zpool.cache # 2> /dev/null do
LOADER_CONFIGS=${MNT}/boot/loader.conf if [ "${FS}" = "${POOL}/ROOT/${2}" ]
[ -f ${MNT}/boot/loader.conf.local ] && LOADER_CONFIGS="${LOADER_CONFIGS} ${MNT}/boot/loader.conf.local" then
MOUNT=${MNT}
fi
done << EOF
$( mount -p | awk '{print $1 " " $2}' )
EOF
if [ ${MOUNT} -eq 0 ]
then
zfs set mountpoint=${TMPMNT} ${POOL}/ROOT/${2}
zfs mount ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
else
TMPMNT=${MOUNT}
fi
cp /boot/zfs/zpool.cache ${TMPMNT}/boot/zfs/zpool.cache # 2> /dev/null
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} 2> /dev/null sed -i '' -E s/"^vfs.root.mountfrom=.*$"/"vfs.root.mountfrom=\"zfs:${POOL}\/ROOT\/${2##*/}\""/g ${LOADER_CONFIGS} 2> /dev/null
zfs umount ${POOL}/ROOT/${2} if [ ${MOUNT} -eq 0 ]
zfs set mountpoint=legacy ${POOL}/ROOT/${2} then
} zfs umount ${POOL}/ROOT/${2}
zpool set bootfs=${POOL}/ROOT/${2} ${POOL} && { zfs set mountpoint=legacy ${POOL}/ROOT/${2}
} || { fi
fi
if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL}
then
echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'" echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'"
exit 1 exit 1
} fi
} fi
zfs list -H -o name -r ${POOL}/ROOT \ zfs list -H -o name -r ${POOL}/ROOT \
| grep -v "${POOL}/ROOT/${2}" \ | grep -v "${POOL}/ROOT/${2}" \
| while read I | while read I
@ -189,31 +250,39 @@ case ${1} in
do do
MOUNT=$( zfs get -H -o value mountpoint ${I} ) MOUNT=$( zfs get -H -o value mountpoint ${I} )
zfs set canmount=noauto ${I} zfs set canmount=noauto ${I}
[ "${MOUNT}" = legacy ] || zfs set mountpoint=${MOUNT} ${I} if [ "${MOUNT}" != legacy ]
then
zfs set mountpoint=${MOUNT} ${I}
fi
zfs set canmount=on ${I} 2> /dev/null zfs set canmount=on ${I} 2> /dev/null
zfs promote ${I} zfs promote ${I} 2> /dev/null
done done
echo "Activated successfully" echo "Activated successfully"
;; ;;
(destroy) # ---------------------------------------------------------------- (destroy) # ----------------------------------------------------------------
__be_exist ${POOL}/ROOT/${2} __be_exist ${POOL}/ROOT/${2}
[ "${BOOTFS}" = "${POOL}/ROOT/${2}" ] && { if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
then
echo "ERROR: '${POOL}/ROOT/${2}' is current active boot environment" echo "ERROR: '${POOL}/ROOT/${2}' is current active boot environment"
exit 1 exit 1
} fi
echo "Are you sure you want to destroy '${2}'?" echo "Are you sure you want to destroy '${2}'?"
echo -n "This action cannot be undone (y/[n]): " echo -n "This action cannot be undone (y/[n]): "
read CHOICE read CHOICE
case ${CHOICE} in case ${CHOICE} in
(Y|y|[Yy][Ee][Ss]) (Y|y|[Yy][Ee][Ss])
__be_snapshot ${POOL}/ROOT/${2} && { if __be_snapshot ${POOL}/ROOT/${2}
zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null || { then
if ! zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
then
echo "ERROR: Snapshot '${2}' is origin for other boot environment(s)" echo "ERROR: Snapshot '${2}' is origin for other boot environment(s)"
exit 1 exit 1
} fi
} || { else
ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${2} ) ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${2} )
zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null || { if zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
then
zfs destroy -r ${POOL}/ROOT/${2} 2>&1 \ zfs destroy -r ${POOL}/ROOT/${2} 2>&1 \
| grep "${POOL}/ROOT/" \ | grep "${POOL}/ROOT/" \
| grep -v "@" \ | grep -v "@" \
@ -221,13 +290,13 @@ case ${1} in
do do
zfs promote ${I} 2> /dev/null zfs promote ${I} 2> /dev/null
done done
} fi
echo "${ORIGINS}" \ echo "${ORIGINS}" \
| while read I | while read I
do do
zfs destroy -r ${I} 2> /dev/null zfs destroy -r ${I} 2> /dev/null
done done
} fi
echo "Destroyed successfully" echo "Destroyed successfully"
;; ;;
(*) (*)
@ -235,8 +304,8 @@ case ${1} in
;; ;;
esac esac
;; ;;
(*) # ----------------------------------------------------------------------- (*) # -----------------------------------------------------------------------
__usage __usage
;; ;;
esac esac