Revised ERROR messages. Improve BEADM DESTROY. Use AWK instead BC. A lot of simplified code.

This commit is contained in:
Slawomir Wojciech Wojtczak (vermaden) 2012-08-14 01:42:02 +02:00
parent 76c1a80d8c
commit ad830232ca
1 changed files with 100 additions and 92 deletions

152
beadm
View File

@ -35,10 +35,6 @@ fi
__usage() { __usage() {
local NAME=${0##*/} local NAME=${0##*/}
echo "usage:" echo "usage:"
echo " ${NAME} subcommand cmd_options"
echo
echo " subcommands:"
echo
echo " ${NAME} activate beName" echo " ${NAME} activate beName"
echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] beName" echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] beName"
echo " ${NAME} create beName@snapshot" echo " ${NAME} create beName@snapshot"
@ -62,7 +58,12 @@ __be_exist() { # 1=DATASET
# check if argument is a snapshot # check if argument is a snapshot
__be_snapshot() { # 1=DATASET/SNAPSHOT __be_snapshot() { # 1=DATASET/SNAPSHOT
echo "${1}" | grep -q "@" 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
} }
# create new boot environment # create new boot environment
@ -76,7 +77,7 @@ __be_new() { # 1=SOURCE 2=TARGET
do do
if ! zfs list -H -o name ${FS}@${SNAPSHOT} 1> /dev/null 2> /dev/null if ! zfs list -H -o name ${FS}@${SNAPSHOT} 1> /dev/null 2> /dev/null
then then
echo "ERROR: Child snapshot '${FS}@${SNAPSHOT}' does not exists" echo "ERROR: Child snapshot '${FS}@${SNAPSHOT}' does not exist"
exit 1 exit 1
fi fi
done done
@ -86,12 +87,10 @@ __be_new() { # 1=SOURCE 2=TARGET
echo "ERROR: Snapshot '${1}@${2##*/}' already exists" echo "ERROR: Snapshot '${1}@${2##*/}' already exists"
exit 1 exit 1
fi fi
FMT=$( date "+%Y-%m-%d-%H:%M:%S" ) # NEW # FMT=$( date "+%Y-%m-%d-%H:%M:%S" )
if ! zfs snapshot -r ${1}@${FMT} 1> /dev/null 2> /dev/null # NEW # if ! zfs snapshot -r ${1}@${FMT} 1> /dev/null 2> /dev/null # 2##*/ > FMT
# if ! zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null # old #
then then
echo "ERROR: Cannot create snapshot '${1}@${FMT}'" # NEW # echo "ERROR: Cannot create snapshot '${1}@${FMT}'" # 2##*/ > FMT
# echo "ERROR: Cannot create snapshot '${1}@${2##*/}'" # old #
exit 1 exit 1
fi fi
fi fi
@ -114,11 +113,9 @@ EOF
then then
zfs clone -o canmount=off ${OPTS} ${FS}@${1##*@} ${DATASET} zfs clone -o canmount=off ${OPTS} ${FS}@${1##*@} ${DATASET}
else else
# zfs clone -o canmount=off ${OPTS} ${FS}@${2##*/} ${DATASET} # old # zfs clone -o canmount=off ${OPTS} ${FS}@${FMT} ${DATASET} # 2##*/ > FMT
zfs clone -o canmount=off ${OPTS} ${FS}@${FMT} ${DATASET} # NEW #
fi fi
done done
echo "Created successfully"
} }
ROOTFS=$( mount | awk '/ \/ / {print $1}' ) ROOTFS=$( mount | awk '/ \/ / {print $1}' )
@ -177,6 +174,7 @@ case ${1} in
esac esac
if [ "${2}" = "-S" ] if [ "${2}" = "-S" ]
then then
# do the detailed space calculation [-S]
USED_ALL=$( zfs list -H -t all -o name,used ) USED_ALL=$( zfs list -H -t all -o name,used )
while read I while read I
do do
@ -191,18 +189,18 @@ case ${1} in
(*E) USED=$( echo ${USED} | awk '{TMP=gsub(/E/,""); TMP=$0*10; gsub(/\..*/,"",TMP); print TMP"00000000000000000"}' ) ;; (*E) USED=$( echo ${USED} | awk '{TMP=gsub(/E/,""); TMP=$0*10; gsub(/\..*/,"",TMP); print TMP"00000000000000000"}' ) ;;
(*Z) USED=$( echo ${USED} | awk '{TMP=gsub(/Z/,""); TMP=$0*10; gsub(/\..*/,"",TMP); print TMP"00000000000000000000"}' ) ;; (*Z) USED=$( echo ${USED} | awk '{TMP=gsub(/Z/,""); TMP=$0*10; gsub(/\..*/,"",TMP); print TMP"00000000000000000000"}' ) ;;
esac esac
TOTAL=$( echo ${USED} + ${TOTAL} | bc ) TOTAL=$( echo | awk -v used=${USED} -v total=${TOTAL} '{print used + total}' )
done << EOF done << EOF
$( zfs list -H -t all -o name,origin -r "${BENAME_STARTS_WITH}/${NAME}" | tr '\t' '\n' | grep -v "^-$" ) $( zfs list -H -t all -o name,origin -r "${BENAME_STARTS_WITH}/${NAME}" | tr '\t' '\n' | grep -v "^-$" )
EOF EOF
case $( echo "${TOTAL}" | wc -c | tr -c -d '[0-9]\n' ) in case $( echo "${TOTAL}" | awk '{print length($0)}' ) in
(5|6|7) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-2)/10)"K"}' ); ;; (4|5|6) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-2)/10)"K"}' ); ;;
(8|9|10) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-5)/10)"M"}' ); ;; (7|8|9) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-5)/10)"M"}' ); ;;
(11|12|13) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-8)/10)"G"}' ); ;; (10|11|12) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-8)/10)"G"}' ); ;;
(14|15|16) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-11)/10)"T"}' ); ;; (13|14|15) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-11)/10)"T"}' ); ;;
(17|18|19) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-14)/10)"P"}' ); ;; (16|17|18) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-14)/10)"P"}' ); ;;
(20|21|22) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-17)/10)"E"}' ); ;; (19|20|21) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-17)/10)"E"}' ); ;;
(23|24|25) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-20)/10)"Z"}' ); ;; (22|23|24) TOTAL=$( echo ${TOTAL} | awk '{printf (substr($0,0,length($0)-20)/10)"Z"}' ); ;;
esac esac
else else
TOTAL=${USED} TOTAL=${USED}
@ -235,7 +233,6 @@ EOF
echo "ERROR: Cannot create '${2}' recursive snapshot" echo "ERROR: Cannot create '${2}' recursive snapshot"
exit 1 exit 1
fi fi
echo "Created successfully"
else else
__be_new ${ROOTFS} ${POOL}/ROOT/${2} __be_new ${ROOTFS} ${POOL}/ROOT/${2}
fi fi
@ -244,6 +241,7 @@ EOF
__usage __usage
;; ;;
esac esac
echo "Created successfully"
;; ;;
(activate) # ---------------------------------------------------------------- (activate) # ----------------------------------------------------------------
@ -262,7 +260,7 @@ EOF
MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' ) MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' )
if [ "${MNT}" != "/" ] if [ "${MNT}" != "/" ]
then then
echo "ERROR: The '${2}' is mounted at '${MNT}'" echo "ERROR: Boot environment '${2}' is mounted at '${MNT}'"
echo "ERROR: Cannot activate mounted boot environment" echo "ERROR: Cannot activate mounted boot environment"
exit 1 exit 1
fi fi
@ -308,7 +306,7 @@ EOF
fi fi
if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL} 2> /dev/null 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 '${2}'"
exit 1 exit 1
fi fi
fi fi
@ -319,7 +317,7 @@ EOF
do do
zfs set canmount=noauto ${I} zfs set canmount=noauto ${I}
done done
# enable automatic mount for active BE and promote it # enable automatic mount for active boot environment 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
@ -355,7 +353,7 @@ EOF
__be_exist ${POOL}/ROOT/${DESTROY} __be_exist ${POOL}/ROOT/${DESTROY}
if [ "${BOOTFS}" = "${POOL}/ROOT/${DESTROY}" ] if [ "${BOOTFS}" = "${POOL}/ROOT/${DESTROY}" ]
then then
echo "ERROR: '${POOL}/ROOT/${2}' is current active boot environment" echo "ERROR: Cannot destroy active boot environment"
exit 1 exit 1
fi fi
case ${CHOICE} in case ${CHOICE} in
@ -366,7 +364,7 @@ EOF
# destroy desired snapshot # destroy desired snapshot
if ! zfs destroy -r ${POOL}/ROOT/${DESTROY} 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"
exit 1 exit 1
fi fi
else else
@ -380,20 +378,39 @@ EOF
fi fi
done done
# get origins used by destroyed boot environment # get origins used by destroyed boot environment
ORIGINS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} | grep -v '^-$' ) ORIGIN_SNAPSHOTS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} | grep -v '^-$' | awk -F "@" '{print $2}' | sort -u )
# destroy boot environment # destroy boot environment
zfs destroy -r ${POOL}/ROOT/${DESTROY} zfs destroy -r ${POOL}/ROOT/${DESTROY}
# 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_ORIRINS}" \
| grep "${S}" \
| awk '{print $1}' \
| while read I
do
zfs promote ${I}
done
done
# destroy origins used by destroyed boot environment # destroy origins used by destroyed boot environment
echo "${ORIGINS}" \ ALL_ORIGINS=$( zfs list -H -t all -o origin )
echo "${ORIGIN_SNAPSHOTS}" \
| while read S
do
echo "${ALL_ORIRINS}" \
| grep "@${S}$" \
| while read I | while read I
do do
zfs destroy ${I} zfs destroy ${I}
done done
done
fi fi
echo "Destroyed successfully" echo "Destroyed successfully"
;; ;;
(*) (*)
echo "'${DESTROY}' has not been destroyed" echo "Boot environment '${DESTROY}' has not been destroyed"
;; ;;
esac esac
;; ;;
@ -406,7 +423,7 @@ EOF
__be_exist ${POOL}/ROOT/${2} __be_exist ${POOL}/ROOT/${2}
if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ] if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
then then
echo "ERROR: Renaming the active BE is not supported" echo "ERROR: Renaming active boot environment is not supported"
exit 1 exit 1
fi fi
if zfs list -H -o name ${POOL}/ROOT/${3} 2> /dev/null if zfs list -H -o name ${POOL}/ROOT/${3} 2> /dev/null
@ -419,19 +436,14 @@ EOF
;; ;;
(mount) # ------------------------------------------------------------------- (mount) # -------------------------------------------------------------------
COMPLETE=1 if [ ${#} -eq 1 ]
if [ ${#} -eq 1 -o ${#} -eq 2 ]
then then
if [ ${2} ]
then
BE=${2}
else
zfs list -H -o name -d 1 -r ${POOL}/ROOT \ zfs list -H -o name -d 1 -r ${POOL}/ROOT \
| grep "${POOL}/ROOT/" \ | grep "${POOL}/ROOT/" \
| while read NAME | while read NAME
do do
NAME=${NAME##*/} NAME=${NAME##*/}
if mount | grep -E "^${POOL}/ROOT/${NAME}" 1> /dev/null 2> /dev/null if mount | grep -q -E "^${POOL}/ROOT/${NAME}" 2> /dev/null
then then
echo ${NAME} echo ${NAME}
mount \ mount \
@ -443,39 +455,40 @@ EOF
fi fi
done done
exit 0 exit 0
fi elif [ ${#} -eq 2 ]
then
TARGET=$( mktemp -d /tmp/tmp.XXXXXX )
elif [ ${#} -eq 3 ] elif [ ${#} -eq 3 ]
then then
BE=${2}
TARGET=${3} TARGET=${3}
else else
__usage __usage
fi fi
__be_exist "${POOL}/ROOT/${BE}" __be_exist "${POOL}/ROOT/${2}"
if mount | grep -E "^${POOL}/ROOT/${BE} " 1> /dev/null 2> /dev/null if __be_mounted "${POOL}/ROOT/${2}"
then then
MNT=$( mount | grep -E "^${POOL}/ROOT/${BE} " | awk '{print $3}' ) MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' )
echo "The '${BE}' is already mounted at '${MNT}'" echo "Boot environment '${2}' is already mounted at '${MNT}'"
exit 1 exit 1
fi fi
if ! [ ${3} ] if ! mkdir -p ${TARGET} 2> /dev/null
then then
TARGET=$( mktemp -d /tmp/tmp.XXXXXX ) echo "ERROR: Cannot create '${TARGET}' mountpoint"
mkdir -p ${TARGET}
fi
if ! mount -t zfs ${POOL}/ROOT/${BE} ${TARGET}
then
echo "ERROR: Cannot mount '${POOL}/ROOT/${BE}' at '${TARGET}' mountpoint"
exit 1 exit 1
fi fi
PREFIX=$( echo ${POOL}/ROOT/${BE}/ | sed 's/\//\\\//g' ) if ! mount -t zfs ${POOL}/ROOT/${2} ${TARGET}
zfs list -H -o name,mountpoint -r ${POOL}/ROOT/${BE} \ 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 "legacy$" \ | grep -v "legacy$" \
| sort -n \ | sort -n \
| grep -E "^${POOL}/ROOT/${BE}/" \ | grep -E "^${POOL}/ROOT/${2}/" \
| while read FS MOUNTPOINT | while read FS MOUNTPOINT
do do
if [ "{FS}" != "${POOL}/ROOT/${BE}" ] if [ "{FS}" != "${POOL}/ROOT/${2}" ]
then then
INHERIT=$( zfs get -H -o source mountpoint ${FS} ) INHERIT=$( zfs get -H -o source mountpoint ${FS} )
if [ "${INHERIT}" = "local" ] if [ "${INHERIT}" = "local" ]
@ -503,38 +516,33 @@ EOF
echo "Mounted successfully on '${TARGET}'" echo "Mounted successfully on '${TARGET}'"
;; ;;
(umount|unmount) # ------------------------------------------------------------------ (umount|unmount) # ----------------------------------------------------------
COMPLETE=1
if [ ${#} -eq 2 ] if [ ${#} -eq 2 ]
then then
BE=${2} # we need this section for argument checking
elif [ ${#} -eq 3 ] :
then elif [ ${#} -eq 3 -a "${2}" = "-f" ]
BE=${3}
if [ "${2}" = "-f" ]
then then
OPTS="-f" OPTS="-f"
shift
else else
__usage __usage
fi fi
else __be_exist "${POOL}/ROOT/${2}"
__usage if ! __be_mounted "${POOL}/ROOT/${2}"
fi
__be_exist "$POOL/ROOT/$BE"
if ! mount | grep -E "^${POOL}/ROOT/${BE} " 1> /dev/null 2> /dev/null
then then
echo "The '${BE}' is not mounted" echo "Boot environment '${2}' is not mounted"
exit 1 exit 1
fi fi
mount \ mount \
| grep "^${POOL}/ROOT/${BE}" \ | grep "^${POOL}/ROOT/${2}" \
| awk '{print $1}' \ | awk '{print $1}' \
| sort -n -r \ | sort -n -r \
| while read FS | while read FS
do do
if ! umount ${OPTS} ${FS} 1> /dev/null 2> /dev/null if ! umount ${OPTS} ${FS} 1> /dev/null 2> /dev/null
then then
echo "ERROR: Cannot umount '${FS}'" echo "ERROR: Cannot umount '${FS}' dataset"
exit 1 exit 1
fi fi
done done