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

192
beadm
View File

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