Added destroy -F option, umount all depended datasets of BE upon destroy command.
This commit is contained in:
parent
f8caebcc6c
commit
fde3b39006
87
beadm
87
beadm
|
|
@ -28,7 +28,8 @@ PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin
|
||||||
|
|
||||||
if [ $( uname -r | cut -d '.' -f1 ) -lt 8 ]
|
if [ $( uname -r | cut -d '.' -f1 ) -lt 8 ]
|
||||||
then
|
then
|
||||||
echo "ERROR: beadm only works on FreeBSD 8.0 or later"
|
echo "ERROR: beadm works on FreeBSD 8.0 or later"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__usage() {
|
__usage() {
|
||||||
|
|
@ -39,15 +40,15 @@ __usage() {
|
||||||
echo " subcommands:"
|
echo " subcommands:"
|
||||||
echo
|
echo
|
||||||
echo " ${NAME} activate beName"
|
echo " ${NAME} activate beName"
|
||||||
echo " ${NAME} create [-e nonActiveBe | beName@snapshot] beName"
|
echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] beName"
|
||||||
echo " ${NAME} create beName@snapshot"
|
echo " ${NAME} create beName@snapshot"
|
||||||
echo " ${NAME} destroy beName"
|
echo " ${NAME} destroy [-F] beName | beName@snapshot"
|
||||||
echo " ${NAME} destroy beName@snapshot"
|
|
||||||
echo " ${NAME} list"
|
echo " ${NAME} list"
|
||||||
echo " ${NAME} rename origBeName newBeName"
|
echo " ${NAME} rename origBeName newBeName"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check if BE exists
|
||||||
__be_exist() { # 1=DATASET
|
__be_exist() { # 1=DATASET
|
||||||
if ! 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
|
then
|
||||||
|
|
@ -56,10 +57,12 @@ __be_exist() { # 1=DATASET
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check if argument is a snapshot
|
||||||
__be_snapshot() { # 1=DATASET/SNAPSHOT
|
__be_snapshot() { # 1=DATASET/SNAPSHOT
|
||||||
echo "${1}" | grep -q "@"
|
echo "${1}" | grep -q "@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# create new BE
|
||||||
__be_new() { # 1=SOURCE 2=TARGET
|
__be_new() { # 1=SOURCE 2=TARGET
|
||||||
local SOURCE=$( echo ${1} | cut -d '@' -f 1 )
|
local SOURCE=$( echo ${1} | cut -d '@' -f 1 )
|
||||||
if __be_snapshot ${1}
|
if __be_snapshot ${1}
|
||||||
|
|
@ -132,23 +135,23 @@ BOOTFS=$( zpool list -H -o bootfs ${POOL} )
|
||||||
case ${1} in
|
case ${1} in
|
||||||
|
|
||||||
(list) # --------------------------------------------------------------------
|
(list) # --------------------------------------------------------------------
|
||||||
POOL_PREFIX="${POOL}/ROOT"
|
BENAME_STARTS_WITH="${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/" )
|
||||||
WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L )
|
WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L )
|
||||||
WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L )
|
WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L )
|
||||||
WIDTH_NAME=$(( ${WIDTH_NAME} - ${#POOL_PREFIX} - 1 ))
|
WIDTH_NAME=$(( ${WIDTH_NAME} - ${#BENAME_STARTS_WITH} - 1 ))
|
||||||
printf "%-${WIDTH_NAME}s %-6s %-10s %5s %6s %s\n" \
|
printf "%-${WIDTH_NAME}s %-6s %-10s %5s %6s %s\n" \
|
||||||
BE Active Mountpoint Space Policy Created
|
BE Active Mountpoint Space Policy Created
|
||||||
echo "${LIST}" \
|
echo "${LIST}" \
|
||||||
| while read NAME USED MOUNTPOINT C R E A T
|
| while read NAME USED MOUNTPOINT Y m d H M
|
||||||
do
|
do
|
||||||
NAME=${NAME##*/}
|
NAME=${NAME##*/}
|
||||||
unset ACTIVE
|
unset ACTIVE
|
||||||
if [ "${POOL_PREFIX}/${NAME}" = "${ROOTFS}" ]
|
if [ "${BENAME_STARTS_WITH}/${NAME}" = "${ROOTFS}" ]
|
||||||
then
|
then
|
||||||
ACTIVE="${ACTIVE}N"
|
ACTIVE="${ACTIVE}N"
|
||||||
fi
|
fi
|
||||||
if [ "${POOL_PREFIX}/${NAME}" = "${BOOTFS}" ]
|
if [ "${BENAME_STARTS_WITH}/${NAME}" = "${BOOTFS}" ]
|
||||||
then
|
then
|
||||||
ACTIVE="${ACTIVE}R"
|
ACTIVE="${ACTIVE}R"
|
||||||
fi
|
fi
|
||||||
|
|
@ -162,7 +165,7 @@ case ${1} in
|
||||||
(*) MOUNT="-" ;;
|
(*) MOUNT="-" ;;
|
||||||
esac
|
esac
|
||||||
printf "%-10s %5s %-6s " ${MOUNT} ${USED} "static"
|
printf "%-10s %5s %-6s " ${MOUNT} ${USED} "static"
|
||||||
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" "${Y} ${m} ${d} ${H} ${M}" +"%Y-%m-%d %H:%M"
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
@ -174,7 +177,7 @@ case ${1} in
|
||||||
__usage
|
__usage
|
||||||
fi
|
fi
|
||||||
__be_exist ${POOL}/ROOT/${3}
|
__be_exist ${POOL}/ROOT/${3}
|
||||||
if zfs list -H -o name ${POOL}/ROOT/${4} 2> /dev/null
|
if zfs list -H -o name ${POOL}/ROOT/${4} 1> /dev/null 2> /dev/null
|
||||||
then
|
then
|
||||||
echo "ERROR: Boot environment '${4}' already exists"
|
echo "ERROR: Boot environment '${4}' already exists"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -184,9 +187,9 @@ case ${1} in
|
||||||
(2)
|
(2)
|
||||||
if __be_snapshot ${2}
|
if __be_snapshot ${2}
|
||||||
then
|
then
|
||||||
if ! zfs snapshot -r ${POOL}/ROOT/${2} 2> /dev/null
|
if ! zfs snapshot -r ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
|
||||||
then
|
then
|
||||||
echo "ERROR: Cannot create '${2}' snapshot"
|
echo "ERROR: Cannot create '${2}' recursive snapshot"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Created successfully"
|
echo "Created successfully"
|
||||||
|
|
@ -237,7 +240,7 @@ EOF
|
||||||
else
|
else
|
||||||
TMPMNT=${MOUNT}
|
TMPMNT=${MOUNT}
|
||||||
fi
|
fi
|
||||||
cp /boot/zfs/zpool.cache ${TMPMNT}/boot/zfs/zpool.cache # 2> /dev/null
|
cp /boot/zfs/zpool.cache ${TMPMNT}/boot/zfs/zpool.cache
|
||||||
LOADER_CONFIGS=${TMPMNT}/boot/loader.conf
|
LOADER_CONFIGS=${TMPMNT}/boot/loader.conf
|
||||||
if [ -f ${TMPMNT}/boot/loader.conf.local ]
|
if [ -f ${TMPMNT}/boot/loader.conf.local ]
|
||||||
then
|
then
|
||||||
|
|
@ -250,24 +253,24 @@ EOF
|
||||||
zfs set mountpoint=legacy ${POOL}/ROOT/${2}
|
zfs set mountpoint=legacy ${POOL}/ROOT/${2}
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL}
|
if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL} 2> /dev/null
|
||||||
then
|
then
|
||||||
echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'"
|
echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# Disable mounting on all inactive datasets
|
# disable automatic mount on all inactive datasets
|
||||||
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
|
||||||
do
|
do
|
||||||
zfs set canmount=noauto ${I}
|
zfs set canmount=noauto ${I}
|
||||||
done
|
done
|
||||||
# Enable mounting for the active BE and promote it
|
# enable automatic mount for active BE and promote it
|
||||||
zfs list -H -o name,origin -t filesystem -r ${POOL}/ROOT/${2} \
|
zfs list -H -o name,origin -t filesystem -r ${POOL}/ROOT/${2} \
|
||||||
| while read I ORIGIN
|
| while read I ORIGIN
|
||||||
do
|
do
|
||||||
zfs set canmount=on ${I} 2> /dev/null
|
zfs set canmount=on ${I}
|
||||||
if [ ${ORIGIN} != "-" ]
|
if [ ${ORIGIN} != "-" ]
|
||||||
then
|
then
|
||||||
zfs promote ${I}
|
zfs promote ${I}
|
||||||
|
|
@ -277,33 +280,51 @@ EOF
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(destroy) # -----------------------------------------------------------------
|
(destroy) # -----------------------------------------------------------------
|
||||||
if [ ${#} -ne 2 ]
|
case ${#} in
|
||||||
then
|
(2)
|
||||||
__usage
|
echo "Are you sure you want to destroy '${2}'?"
|
||||||
fi
|
echo -n "This action cannot be undone (y/[n]): "
|
||||||
__be_exist ${POOL}/ROOT/${2}
|
read CHOICE
|
||||||
if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
|
DESTROY=${2}
|
||||||
|
;;
|
||||||
|
(3)
|
||||||
|
if [ "${2}" != "-F" ]
|
||||||
|
then
|
||||||
|
__usage
|
||||||
|
fi
|
||||||
|
CHOICE=Y
|
||||||
|
DESTROY=${3}
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
__usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
__be_exist ${POOL}/ROOT/${DESTROY}
|
||||||
|
if [ "${BOOTFS}" = "${POOL}/ROOT/${DESTROY}" ]
|
||||||
then
|
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
|
fi
|
||||||
echo "Are you sure you want to destroy '${2}'?"
|
|
||||||
echo -n "This action cannot be undone (y/[n]): "
|
|
||||||
read CHOICE
|
|
||||||
case ${CHOICE} in
|
case ${CHOICE} in
|
||||||
(Y|y|[Yy][Ee][Ss])
|
(Y|y|[Yy][Ee][Ss])
|
||||||
if __be_snapshot ${POOL}/ROOT/${2}
|
if __be_snapshot ${POOL}/ROOT/${DESTROY}
|
||||||
then
|
then
|
||||||
if ! zfs destroy -r ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
|
if ! zfs destroy -r ${POOL}/ROOT/${DESTROY} 1> /dev/null 2> /dev/null
|
||||||
then
|
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
|
fi
|
||||||
else
|
else
|
||||||
ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${2} )
|
zfs list -r -H -o name ${POOL}/ROOT/${DESTROY} \
|
||||||
if ! zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
|
| sort -n -r \
|
||||||
|
| while read DATASET
|
||||||
|
do
|
||||||
|
zfs umount ${DATASET} 1> /dev/null 2> /dev/null || true
|
||||||
|
done
|
||||||
|
ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${DESTROY} )
|
||||||
|
if ! zfs destroy ${POOL}/ROOT/${DESTROY} 1> /dev/null 2> /dev/null
|
||||||
then
|
then
|
||||||
zfs destroy -r ${POOL}/ROOT/${2} 2>&1 \
|
zfs destroy -r ${POOL}/ROOT/${DESTROY} 2>&1 \
|
||||||
| grep "${POOL}/ROOT/" \
|
| grep "${POOL}/ROOT/" \
|
||||||
| grep -v "@" \
|
| grep -v "@" \
|
||||||
| while read I
|
| while read I
|
||||||
|
|
@ -323,7 +344,7 @@ EOF
|
||||||
echo "Destroyed successfully"
|
echo "Destroyed successfully"
|
||||||
;;
|
;;
|
||||||
(*)
|
(*)
|
||||||
echo "'${2}' has not been destroyed"
|
echo "'${DESTROY}' has not been destroyed"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue