Implemented automatic toplevel mounting
snapsh now checks if the toplevel subvolume is mounted at the path defined in TOPLEVEL, and if not, does it automatically.
This commit is contained in:
parent
d003820acb
commit
a13cba3790
155
snapsh
155
snapsh
|
@ -42,16 +42,61 @@ snapsh [OPTIONS]
|
|||
Options:
|
||||
-h, --help Display this help message
|
||||
-s SUBVOL, --snapshot SUBVOL Take a snapshot of subvolume named SUBVOL.
|
||||
-d STR, --description STR Add a description for the snapshot displayed in the
|
||||
snapshots listing.
|
||||
-t TYPE, --type TYPE Set the type of snapshot, where TYPE=manual|auto|boot|backup
|
||||
Can be used with -l, --list to filter results
|
||||
-d STR, --description STR Add a description for the snapshot displayed
|
||||
in the snapshots listing.
|
||||
-t TYPE, --type TYPE Set the type of snapshot, where
|
||||
TYPE=manual|auto|boot|backup
|
||||
Can be used with --list to filter results
|
||||
-l, --list List snapshots
|
||||
-r NUMBER, --remove NUMBER Remove snapshot NUMBER. See snapshot numbers with
|
||||
snapsh -l
|
||||
--rollback NUMBER Roll back to snapshot NUMBER. See snapshot numbers
|
||||
with snapsh -l. Target subvolume is detected from
|
||||
snapshot automatically.\n"
|
||||
-r NUMBER, --remove NUMBER Remove snapshot NUMBER. See snapshot numbers
|
||||
with snapsh -l
|
||||
--rollback NUMBER Roll back to snapshot NUMBER. See snapshot
|
||||
numbers with snapsh -l. Target subvolume is
|
||||
detected from snapshot automatically.\n"
|
||||
}
|
||||
|
||||
mount_check() {
|
||||
|
||||
# Check that the toplevel subvolume (id=5) is mounted, and if not,
|
||||
# mount it to path defined in $TOPLEVEL
|
||||
|
||||
mount | grep subvolid=5 | grep "${TOPLEVEL}" > /dev/null
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
# Get the UUID of the current btrfs volume
|
||||
MOUNT_UUID=$(btrfs filesystem show | grep uuid | cut -d ':' -f 3)
|
||||
# Create the mountpoint for the toplevel if needed
|
||||
[[ -d ${TOPLEVEL} ]] || mkdir -p ${TOPLEVEL}
|
||||
# Mount the toplevel
|
||||
mount -U ${MOUNT_UUID} -o subvolid=5 ${TOPLEVEL}
|
||||
fi
|
||||
|
||||
if [[ -n ${SNAPSHOT} ]]; then
|
||||
# If taking a snapshot,
|
||||
# check that the subvolume storing snapshots exists and if not, ask
|
||||
# to create it.
|
||||
${BTRFS_EXECUTABLE} subvolume show ${SNAPSHOTS_LOCATION} > /dev/null
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
printf "Subvolume ${SNAPSHOTS_LOCATION} does not exist. Create it now?\n"
|
||||
read -n 1 -p "y/n: "
|
||||
|
||||
if [[ "${REPLY}" == "y" ]]; then
|
||||
# Create subvolume defined with SNAPSHOTS_LOCATION
|
||||
${BTRFS_EXECUTABLE} subvolume create ${SNAPSHOTS_LOCATION}
|
||||
unset ${REPLY}
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Otherwise, just check that the subvolume in SNAPSHOTS_LOCATION
|
||||
# exists, and notify if not.
|
||||
${BTRFS_EXECUTABLE} subvolume show ${SNAPSHOTS_LOCATION} > /dev/null
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
printf "Subvolume ${SNAPSHOTS_LOCATION} does not exist.\n"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,49 +105,42 @@ snapshot() {
|
|||
|
||||
EXIT_CODE=0
|
||||
root_check #Check that script is run with root privileges.
|
||||
mount_check #Check that the toplevel subvolume is mounted
|
||||
|
||||
# Check that the subvolume storing snapshots exists
|
||||
if [[ ! -d ${SNAPSHOTS_LOCATION} ]]; then
|
||||
printf "Subvolume ${SNAPSHOTS_LOCATION} does not exist. Create it now?\n"
|
||||
read -n 1 -p "y/n: "
|
||||
|
||||
if [[ "${REPLY}" == "y" ]]; then
|
||||
# Create subvolume defined with SNAPSHOTS_LOCATION
|
||||
${BTRFS_EXECUTABLE} subvolume create ${SNAPSHOTS_LOCATION}
|
||||
unset ${REPLY}
|
||||
else
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
else
|
||||
# TYPE defaults to manual
|
||||
if [[ -z "${SET_TYPE}" ]]; then
|
||||
SET_TYPE="manual"
|
||||
fi
|
||||
|
||||
printf "Creating snapshot of subvolume ${SUBVOLUME} as ${SUBVOLUME}_snapshot_${TIMESTAMP}\n"
|
||||
|
||||
# Create info file for listing snapshots
|
||||
# Created first on the source subvolume, then deleted from the source
|
||||
printf "DATE=\"$(date)\"
|
||||
SOURCE_SUBVOLUME=\"${SUBVOLUME}\"
|
||||
DESCRIPTION=\"${DESCRIPTION}\"
|
||||
TYPE=\"${SET_TYPE}\"\n" > ${TOPLEVEL}/${SUBVOLUME}/.snapsh
|
||||
|
||||
# Create readonly subvolume
|
||||
${BTRFS_EXECUTABLE} subvolume snapshot -r ${TOPLEVEL}/${SUBVOLUME} ${SNAPSHOTS_LOCATION}/${SUBVOLUME}_snapshot_${TIMESTAMP}
|
||||
|
||||
# Delete info file from source
|
||||
rm -f ${TOPLEVEL}/${SUBVOLUME}/.snapsh
|
||||
|
||||
printf "Snapshot created!
|
||||
${SUBVOLUME}_snapshot_${TIMESTAMP}
|
||||
DATE=$(date)
|
||||
SOURCE_SUBVOLUME=${SUBVOLUME}
|
||||
DESCRIPTION=${DESCRIPTION}
|
||||
TYPE=\"${SET_TYPE}\"\n"
|
||||
|
||||
# TYPE defaults to manual
|
||||
if [[ -z "${SET_TYPE}" ]]; then
|
||||
SET_TYPE="manual"
|
||||
fi
|
||||
|
||||
printf "Creating snapshot of subvolume ${SUBVOLUME} as \
|
||||
${SUBVOLUME}_snapshot_${TIMESTAMP}\n"
|
||||
|
||||
# Create info file for listing snapshots
|
||||
# Created first on the source subvolume, then deleted from the source
|
||||
printf "DATE=\"$(date)\"
|
||||
SOURCE_SUBVOLUME=\"${SUBVOLUME}\"
|
||||
DESCRIPTION=\"${DESCRIPTION}\"
|
||||
TYPE=\"${SET_TYPE}\"\n" > ${TOPLEVEL}/${SUBVOLUME}/.snapsh
|
||||
|
||||
# Create readonly subvolume
|
||||
${BTRFS_EXECUTABLE} subvolume snapshot -r ${TOPLEVEL}/${SUBVOLUME} \
|
||||
${SNAPSHOTS_LOCATION}/${SUBVOLUME}_snapshot_${TIMESTAMP}
|
||||
|
||||
let EXIT_CODE=${EXIT_CODE}+$?
|
||||
|
||||
# Delete info file from source
|
||||
rm -f ${TOPLEVEL}/${SUBVOLUME}/.snapsh
|
||||
|
||||
printf "Snapshot created!
|
||||
${SUBVOLUME}_snapshot_${TIMESTAMP}
|
||||
DATE=$(date)
|
||||
SOURCE_SUBVOLUME=${SUBVOLUME}
|
||||
DESCRIPTION=${DESCRIPTION}
|
||||
TYPE=\"${SET_TYPE}\"\n"
|
||||
|
||||
|
||||
exit ${EXIT_CODE}
|
||||
}
|
||||
|
||||
|
@ -110,6 +148,8 @@ snapshot() {
|
|||
|
||||
list() {
|
||||
root_check
|
||||
mount_check
|
||||
|
||||
shopt -s nullglob
|
||||
NUM=1
|
||||
SNAPSHOTS=(${SNAPSHOTS_LOCATION}/*/)
|
||||
|
@ -117,14 +157,18 @@ list() {
|
|||
printf "No snapshots found in ${SNAPSHOTS_LOCATION}.\n"
|
||||
exit 0
|
||||
fi
|
||||
printf "%6s %s %s %26s %s %s %6s %s %s\n" "Number" "|" "Time:" "|" "Source" "|" "Type" "|" "Description"
|
||||
printf "%6s %s %s %26s %10s %s %6s %s %s\n" "Number" "|" "Time:" "|" \
|
||||
"Source" "|" "Type" "|" "Description"
|
||||
for snapshot in ${SNAPSHOTS[@]}; do
|
||||
if [[ -z "${SET_TYPE}" ]]; then
|
||||
. ${snapshot}/.snapsh
|
||||
printf "%8s %32s %8s %8s %s\n" "${NUM} |" "${DATE} |" "${SOURCE_SUBVOLUME} |" "${TYPE} |" "${DESCRIPTION}"
|
||||
printf "%8s %32s %12s %8s %s\n" "${NUM} |" "${DATE} |" \
|
||||
"${SOURCE_SUBVOLUME} |" "${TYPE} |" "${DESCRIPTION}"
|
||||
elif [[ -n "${SET_TYPE}" ]]; then
|
||||
. ${snapshot}/.snapsh
|
||||
[[ "${SET_TYPE}" == "${TYPE}" ]] && printf "%8s %32s %8s %8s %s\n" "${NUM} |" "${DATE} |" "${SOURCE_SUBVOLUME} |" "${TYPE} |" "${DESCRIPTION}"
|
||||
[[ "${SET_TYPE}" == "${TYPE}" ]] && printf "%8s %32s %12s %8s %s\n" \
|
||||
"${NUM} |" "${DATE} |" "${SOURCE_SUBVOLUME} |" "${TYPE} |" \
|
||||
"${DESCRIPTION}"
|
||||
fi
|
||||
|
||||
let NUM=NUM+1
|
||||
|
@ -136,6 +180,7 @@ list() {
|
|||
|
||||
remove() {
|
||||
root_check
|
||||
mount_check
|
||||
|
||||
# List snapshots in to array SNAPSHOTS
|
||||
SNAPSHOTS=(${SNAPSHOTS_LOCATION}/*/)
|
||||
|
@ -170,6 +215,8 @@ remove() {
|
|||
|
||||
rollback() {
|
||||
root_check # Check root privileges
|
||||
mount_check # Check that the toplevel subvolume is mounted
|
||||
|
||||
SNAPSHOTS=(${SNAPSHOTS_LOCATION}/*/) # List snapshots to array
|
||||
|
||||
# Check that NUBER to roll back to is a valid snapshot
|
||||
|
@ -302,7 +349,7 @@ fi
|
|||
|
||||
|
||||
# Options parsing:
|
||||
OPTIONS=$(getopt -a -n snapsh -o hs:d:lr:t: --long help,snapshot:,description:,list,remove:,rollback:,type:,post-rollback -- "$@")
|
||||
OPTIONS=$(getopt -a -n snapsh -o hs:d:lr:t: --long help,snapshot:,description:,list,remove:,rollback:,type:,post-rollback,mount -- "$@")
|
||||
|
||||
# Invalid options (getopt returns nonzero)
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
|
@ -373,6 +420,12 @@ while true; do
|
|||
shift 2
|
||||
;;
|
||||
|
||||
--mount)
|
||||
mount_check
|
||||
shift
|
||||
break
|
||||
;;
|
||||
|
||||
--)
|
||||
shift
|
||||
break
|
||||
|
|
Loading…
Reference in New Issue