#! /bin/dash # tape_admin # https://github.com/rzerres/dsnap-sync # Copyright (C) 2017, 2018 Ralf Zerres # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # ------------------------------------------------------------------------- # Helper routines for tape handling progname="${0##*/}" version="0.0.1" # global variables color=0 date_cmd="date -u +%Y%M%d%H%M%S" default_changer_device="/dev/changer" dryrun=0 ltfs_mountpoint="/media/tape" ltfs_devname="/dev/sg9" mediapools_json="/etc/dsnap-sync/MediaPools.json" mediapool_name="" use_mtx=0 verbose=0 volume_name="" # MTX=mtx JQ=jq LTFS=ltfs LTFSCK=ltfsck MKLTFS=mkltfs # ascii color BLUE= GREEN= MAGENTA= RED= YELLOW= NO_COLOR= ### # functions ### check_prerequisites () { # requested binaries: which ${MTX} >/dev/null 2>&1 || { printf "'%s' is not installed.\n" ${MTX} && exit 1; } which ${LTFS} >/dev/null 2>&1 || { printf "'%s' is not installed.\n" ${LTFS} && exit 1; } which ${MKLTFS} >/dev/null 2>&1 || { printf "'%s' is not installed.\n" ${MKLTFS} && exit 1; } which ${JQ} >/dev/null 2>&1 || { printf "'%s' is not installed.\n" ${JQ} && exit 1; } } compare_date () { local date1=${1} local date2=${2} if [ $date1 -eq $date2 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}date1 ${GREEN}'%s'${MAGENTA} is equal to date2 ${GREEN}'%s'${NO_COLOR}\n" \ "$date1" "$date2" fi return 0 elif [ $date1 -lt $date2 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}date1 ${GREEN}'%s'${MAGENTA} is lower then date2 ${GREEN}'%s'${NO_COLOR}\n" \ "$date1" "$date2" fi return 1 elif [ $date1 -gt $date2 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}date1 ${GREEN}'%s'${MAGENTA} is greater then date2 ${GREEN}'%s'${NO_COLOR}\n" \ "$date1" "$date2" fi return 2 fi } die () { error "$@" exit 1 } error () { printf "\n==> ERROR: %s\n" "$@" notify_error 'Error' 'Check journal for more information.' } >&2 get_mediapolicy () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}get_mediapolicy...${NO_COLOR}\n" fi if test ! -r ${mediapools_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} media-pool file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}}\n" \ "$mediapools_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | select(.VolumeName == \"${volume_name}\") \ | .MediaPolicy ' \ ${mediapools_json}" volume_mediapolicy=$(eval $cmd) if [ $verbose -ge 3 ]; then printf "${MAGENTA}MediaPolicy for volume_name ${GREEN}'%s'${MAGENTA} in media-pool ${GREEN}'%s'${MAGENTA}: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" "$volume_mediapolicy" fi } get_poolmember () { # return: 0-> volume_name match; 1 -> volume_name does not match local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2:-any} if [ $verbose -ge 1 ]; then printf "${BLUE}get_poolmember...${NO_COLOR}\n" fi if test ! -r ${mediapools_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} media-pool file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}}\n" \ "$mediapools_json" fi exit 1 fi #cmd="jq --monochrome-output --join-output --ascii-output '.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '.MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[].VolumeName' \ ${mediapools_json}" poolmember=$(eval $cmd) if [ $verbose -ge 2 ]; then printf "${MAGENTA}poolmembers for media-pool ${GREEN}'%s'${MAGENTA} are:\n${NO_COLOR}%s${NO_COLOR}\n" \ "$mediapool_name" "$poolmember" fi for i in $poolmember ; do if test "$i" = "\"${volume_name}\""; then if [ $verbose -ge 3 ]; then printf "${MAGENTA}volume_name ${GREEN}'%s'${MAGENTA} is member of media-pool ${GREEN}'%s'${NO_COLOR}}\n" \ "$i" "$mediapool_name" fi return 0 break fi done return 1 } get_poolmember_next () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}get_poolmember_next...${NO_COLOR}\n" fi if test ! -r ${mediapools_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} media-pool file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}}\n" \ "$mediapools_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | .VolumeName ' \ ${mediapools_json}" volume_poolmember=$(eval $cmd) i=0 volume_index=-1 for member in $volume_poolmember; do if [ $i -eq 0 ]; then volume_name_next=$(echo $member | sed -e 's/"//g') fi if [ $i -eq $volume_index ]; then if [ ${#member} -ge 1 ]; then volume_name_next=$(echo $member | sed -e 's/"//g') break; fi fi if [ $member = \"$volume_name\" ]; then volume_index=$(($i+1)) fi i=$(($i + 1)) done if [ $verbose -ge 3 ]; then printf "${MAGENTA}poolmember_next for media-pool ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$mediapool_name" "$volume_name_next" fi } get_slot () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}get_slot...${NO_COLOR}\n" fi if test ! -r ${mediapools_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} media-pool file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}}\n" \ "$mediapools_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | select(.VolumeName == \"${volume_name}\") \ | .Slot ' \ ${mediapools_json}" volume_slot=$(eval $cmd) volume_slot=$(echo $volume_slot | sed -e 's/"//g') if [ $verbose -ge 3 ]; then printf "${MAGENTA}Slot for volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${MAGENTA}: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" "$volume_slot" fi } get_retensiondate () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}get_retensiondate...${NO_COLOR}\n" fi if test ! -r ${mediapools_json}; then if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} media-pool file ${GREEN}'%s'${MAGENTA} can't be opend!${NO_COLOR}}\n" \ "$mediapools_json" fi exit 1 fi cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | select(.VolumeName == \"${volume_name}\") \ | .RetensionDate ' \ ${mediapools_json}" volume_retensiondate=$(eval $cmd) if [ $verbose -ge 3 ]; then printf "${MAGENTA}RetensionDate for volume_name ${GREEN}'%s'${MAGENTA} in media-pool ${GREEN}'%s'${MAGENTA}: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" "$volume_retensiondate" fi } ltfs_format () { local ltfs_devname=${ltfs_devname} local volume_name=${1} local tape_id=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_format...${NO_COLOR}\n" fi make_err_file ${MKLTFS} --device=$ltfs_devname --volume-name=${volume_name} --tape-serial=${tape_id} 2>${ERRFILE} RET=$? } ltfs_is_mounted () { local ltfs_devname if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_is_mounted...${NO_COLOR}\n" fi ltfs_devname=$(findmnt -n -T $ltfs_mountpoint -o source | awk -F ':' '{print $2}') if [ ${#ltfs_devname} -gt 1 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape mounted via ${GREEN}'%s'${MAGENTA} at ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_devname" "$ltfs_mountpoint" fi return 0 else return 1 fi } ltfs_mount () { if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_mount...${NO_COLOR}\n" fi ltfs_is_mounted if [ $? -eq 1 ]; then if [ ! -d $ltfs_mountpoint ]; then mkdir -p $ltfs_mountpoint fi if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS mounting tape ${GREEN}'%s'${MAGENTA} to ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_devname" "$ltfs_mountpoint" ${LTFS} -o devname=$ltfs_devname -o verbose=$verbose $ltfs_mountpoint else ${LTFS} -o devname=$ltfs_devname -o verbose=0 $ltfs_mountpoint fi if [ $? -eq 0 ]; then return 0 else return $? fi fi } ltfs_umount () { if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_unmount...${NO_COLOR}\n" fi ltfs_is_mounted if [ $? -eq 0 ]; then ret=$(umount $ltfs_mountpoint 2>/dev/null) if [ $? -eq 0 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape ${GREEN}'%s'${MAGENTA} unmounted.${NO_COLOR}\n" \ "$ltfs_devname" fi return 0 else return 1 fi fi } ltfs_wipe () { local ltfs_devname=${ltfs_devname} local volume_name=${1} local tape_id=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_wipe...${NO_COLOR}\n" fi rm -rf $ltfs_mountpoint/* } make_err_file() { ERRFILE=`mktemp $XDG_RUNTIME_DIR/mtx.err.XXXXXXXXXX` if test x${ERRFILE} = x; then ERRFILE="$XDG_RUNTIME_DIR/mtx.err.$$" if test -f ${ERRFILE}; then echo "ERROR: Temp file security problem on: ${ERRFILE}" exit 1 fi fi } make_temp_file() { TMPFILE=`mktemp $XDG_RUNTIME_DIR/mtx.XXXXXXXXXX` if test x${TMPFILE} = x; then TMPFILE="$XDG_RUNTIME_DIR/mtx.$$" if test -f ${TMPFILE}; then echo "ERROR: Temp file security problem on: ${TMPFILE}" exit 1 fi fi } mtx_exchange () { local changer_device=${changer_device:-$default_changer_device} #export changer_device local slot_source=${1} local slot_target=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}mtx_exchange...${NO_COLOR}\n" fi make_err_file ${MTX} -f $changer_device exchange $slot_source $slot_target 2>${ERRFILE} RET=$? } mtx_getlabel () { local changer_device=${changer_device:-$default_changer_device} local slot_source=${slot_source:-99} export slot_source if [ $verbose -ge 1 ]; then printf "${BLUE}Tape get-label...${NO_COLOR}\n" fi make_temp_file ${MTX} -f $changer_device status >${TMPFILE} RET=$? case ${slot_source} in 0) if [ $verbose -ge 2 ]; then printf "Calling: ${GREEN}%s${MAGENTA} -f ${GREEN}%s${MAGENTA} %s${NO_COLOR}\n" \ "${MTX}" "${changer_device}" "${slot_source}" fi volume_name=$(perl -ne ' /Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE}) #/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "Drive:$1:Slot:$2:$4\n";' ${TMPFILE} ;; [0-9][0-8] | [0-9]) if [ $verbose -ge 2 ]; then printf "Calling: ${GREEN}%s${MAGENTA} -f ${GREEN}%s${MAGENTA} %s${NO_COLOR}\n" \ "${MTX}" "${changer_device}" "${slot_source}" fi perl -ne ' /Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE} ;; *) if [ $verbose -ge 2 ]; then printf "Calling: ${GREEN}%s${MAGENTA} -f ${GREEN}%s${MAGENTA} -- to list all slots${NO_COLOR}\n" \ "${MTX}" "${changer_device}" fi # can be converted to awk+sed+cut, see below perl -ne ' /Data Transfer Element (\d+):Empty/ && print "Drive:$1:empty\n"; /Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "Drive:$1:Slot:$2:$4\n"; /Storage Element (\d+):Empty/ && print "Slot:$1:empty\n"; /Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "Slot:$1:$3\n"; /Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "Import:$1:empty\n"; /Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "Import:$1:$3\n";' ${TMPFILE} ;; esac # If perl isn't installed, you can use by those commands #cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/" #cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep -v "IMPORT/EXPORT" | awk "{print \"S:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" #cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep "IMPORT/EXPORT" | awk "{print \"I:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" rm -f ${TMPFILE} >/dev/null 2>&1 return $RET } mtx_inventory () { local changer_device=${changer_device:-$default_changer_device} if [ $verbose -ge 1 ]; then printf "${BLUE}mtx_inventory...${NO_COLOR}\n" fi ${MTX} -f $changer_device inventory RET=$? } mtx_load () { local changer_device=${changer_device:-$default_changer_device} local slot_source=${1} local drive=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}mtx_load...${NO_COLOR}\n" fi make_err_file ${MTX} -f $changer_device load $slot_source $drive 2>${ERRFILE} RET=$? } mtx_status () { local changer_device=${changer_device:-$default_changer_device} if [ $verbose -ge 1 ]; then printf "${BLUE}Tape status...${NO_COLOR}\n" fi ${MTX} -f $changer_device status } mtx_transfer () { local changer_device=${changer_device:-$default_changer_device} #export changer_device local slot_source=${1##slot_source=} local slot_target=${2##slot_target=} if [ $verbose -ge 1 ]; then printf "${BLUE}Tape transfer...${NO_COLOR}\n" fi make_err_file ${MTX} -f $changer_device transfer $slot_source $slot_target 2>${ERRFILE} RET=$? } mtx_unload () { local changer_device=${changer_device:-$default_changer_device} local slot_source=${1} local drive=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}Tape unload...${NO_COLOR}\n" fi make_err_file for i in 1 2 3 4 5 ; do ${MTX} -f $changer_device unload $slot_source $drive 2>${ERRFILE} RET=$? if test $RET -eq 0; then break fi grep "Error Code=" ${ERRFILE} 2>/dev/null 1>/dev/null if test $? -ne 0 ; then break fi sleep $i done cat ${ERRFILE} rm -f ${ERRFILE} >/dev/null 2>&1 if test $RET -ne 0 ; then if [ $verbose -ge 2 ]; then printf "${RED}Fail: %s -f %s unload slot=%s drive=%s${NOCOLOR}\n" \ "${MTX}" "${changer_device}" "${slot_source}" "${drive}" fi fi exit $RET } parse_params () { #printf "\n${BLUE}Parse arguments...${NO_COLOR}\n" # Evaluate given call parameters while [ $# -gt 0 ]; do key="$1" case $key in -h | --help | \-\? | --usage) # Call usage() function. usage ;; --dry-run|--dryrun) dryrun=1 shift 1 ;; --get-retensiondate) shift 1 pool_params=${*} pool_params="${pool_params%% -*}" params=$* set -- $pool_params count=$# test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-retensiondate ;; --get-poolmember) shift 1 pool_params=${*} pool_params="${pool_params%% -*}" params=$* set -- $pool_params count=$# test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-poolmember ;; --get-poolmember-next) shift 1 pool_params=${*} pool_params="${pool_params%% -*}" params=$* set -- $pool_params count=$# test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-poolmember-next ;; --get-slot) shift 1 pool_params=${*} pool_params="${pool_params%% -*}" params=$* set -- $pool_params count=$# test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-slot ;; --mount-tape) shift 1 tape_params=${*} tape_params="${tape_params%% -*}" params=$* set -- $tape_params count=$# test $count -lt 2 && usage test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=mount-tape ;; -p|--port) port=$2 shift 2 ;; --remote) remote=$2 shift 2 ;; --use-mtx) use_mtx=1 shift 1 ;; --ltfs-devname) ltfs_devname="$2" shift 2 ;; --ltfs-format) shift 1 ltfs_params=${*} ltfs_params="${ltfs_params%% -*}" params=$* set -- $ltfs_params count=$# test $count -ge 1 && volume_name="$1" test $count -ge 2 && tape_id="$2" set -- $params shift $count cmd=ltfs-format ;; --ltfs-is-mounted) shift 1 cmd=ltfs-is-mounted ;; --ltfs-mount) shift 1 cmd=ltfs-mount ;; --ltfs-mountpoint) ltfs_mountpoint="$2" shift 2 ;; --ltfs-umount) shift 1 cmd=ltfs-umount ;; --mtx-exchange) shift slots=${*} slots="${slots%% -*}" params=$* set -- $slots count=$# test $count -lt 2 && usage slot_source="$1" slot_target="$2" set -- $params shift $count cmd=mtx-exchange ;; --mtx-getlabel) shift slots=${*} slots="${slots%% -*}" params=$* set -- $slots count=$# test $count -eq 1 && slot_source="$1" set -- $params shift $count slot_getlabel=1 cmd=mtx-getlabel ;; --mtx-inventory|mtx-inquiry) shift cmd=mtx-inventory ;; --mtx-load) shift slots=${*} slots="${slots%% -*}" params=$* set -- $slots count=$# test $count -lt 1 && usage slot_source="$1" test $count -eq 2 && drive="$2" set -- $params shift $count cmd=mtx-load ;; --mtx-transfer) shift slots=${*} slots="${slots%% -*}" params=$* set -- $slots count=$# test $count -lt 2 && usage slot_source="${1}" slot_target="${2}" set -- $params shift $count cmd=mtx-transfer ;; --mtx-unload) shift slots=${*} slots="${slots%% -*}" params=$* set -- $slots count=$# test $count -lt 1 && usage slot_source="$1" test $count -eq 2 && drive="$2" set -- $params shift $count cmd=mtx-unload ;; -v|--verbose) verbose=$(($verbose + 1)) shift 1 ;; --version) printf "%s v%s\n" "$progname" "$version" exit 0 ;; --ltfs-devname=*) ltfs_devname="${1#*=}" shift ;; --ltfs-mountpoint=*) ltfs_mountpoint="${1#*=}" shift ;; --color=*) case ${1#*=} in yes | Yes | True | true) color=1; ;; *) ;; esac shift ;; --remote=*) remote=${1#*=} shift ;; --v=* | --verbose=*) verbose=${1#*=} shift ;; --) # End of all options shift break ;; -*) printf "WARN: Unknown option (ignored): $1" >&2 die "Unknown option" ;; *) printf "Unknown option: %s\nRun '%s -h' for valid options.\n" $key $progname die "Unknown option" ;; esac done if [ -z "$remote" ]; then ssh="" else ssh="ssh -T $remote" if [ ! -z "$port" ]; then ssh="$ssh -p $port" fi fi if [ "$color" ]; then # ascii color BLUE='\033[0;34m' GREEN='\033[0;32m' MAGENTA='\033[0;35m' RED='\033[0;31m' YELLOW='\033[0;33m' NO_COLOR='\033[0m' fi if [ $verbose -ge 2 ]; then printf "${BLUE}$progname (runtime arguments)...${NO_COLOR}\n" printf "LTFS Settings\n" printf " ltfs device-name: '%s'\n" "$ltfs_devname" printf " ltfs mount-point: '%s'\n" "$ltfs_mountpoint" printf "MTX Settings\n" printf " def changer-name: '%s'\n" "$default_changer_device" if [ $verbose -ge 1 ]; then tape_options="verbose_level=$verbose"; fi if [ $dryrun -eq 1 ]; then tape_options="${tape_options} dry-run=true"; fi if [ $color -eq 1 ]; then tape_options="${tape_options} color=true"; fi if [ $use_mtx -eq 1 ]; then tape_options="${tape_options} use-mtx=true"; fi printf "Options: '%s'\n\n" "${tape_options}" fi } mount_tape () { local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}mount_tape...${NO_COLOR}\n" fi ltfs_is_mounted if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}LTFS Tape is-mounted: ${GREEN}%d${NO_COLOR}\n" \ "$?" fi # get label from tape in given drive slot mtx_getlabel 0 if [ $verbose -ge 1 ]; then printf "${MAGENTA}Tape Label: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" fi # check if given tape is poolmember of selected pool get_poolmember ${mediapool_name} ${volume_name} if [ $? -eq 0 ]; then # volume_name match get_mediapolicy ${mediapool_name} ${volume_name} if [ ${#volume_mediapolicy} -gt 0 ]; then if [ ${volume_mediapolicy} = "append" ] || [ ${volume_mediapolicy} = "overwrite" ] ; then return 0 fi if [ ${volume_mediapolicy} = "overwrite" ] ; then volume_retensiondate="20180101000000" get_retensiondate ${mediapool_name} ${volume_name} date_now=$($date_cmd) compare_date $date_now $volume_retensiondate if [ $? -eq 2 ]; then # retensiondate has exposed: wipe given tape ltfs_wipe return 0 fi if [ $? -eq 1 ]; then # respect active retensiondate: unload given tape ltfs_unmount mtx_unload # use next volume_name from pool get_poolmember_next ${mediapool_name} ${volume_name} get_slot ${mediapool_name} ${volume_name_next} mtx_load ${volume_slot} ltfs_mount return 0 fi fi fi else # volume_name does not match ltfs_umount mtx_unload 0 # TODO get_poolmember get_poolmember_next ${mediapool_name} ${volume_name} #mtx load ${volume_name_next} fi else if [ $verbose -ge 1 ]; then printf "${MAGENTA}No LTFS Tape mounted...${NO_COLOR}\n" fi get_slot ${mediapool_name} ${volume_name} mtx_load ${volume_slot} ltfs_mount return 0 fi } traperror () { printf "Exited due to error on line %s.\n" $1 printf "exit status: %s\n" "$2" #printf "command: %s\n" "$3" #printf "bash line: %s\n" "$4" #printf "function name: %s\n" "$5" exit 1 } trapkill () { printf "Exited due to user intervention.\n" #run_cleanup exit 0 } usage () { cat < Send the snapshot backup to a remote machine. The snapshot will be sent via ssh. You should specify the remote machine's hostname or ip address. The 'root' user must be permitted to login on the remote machine. -p, --port The remote port. --dry-run perform a trial run where no changes are made. -v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) --version show program version EOF exit 0 } ### # Main ### cwd=`pwd` # can't be ported to dash (ERR is not supported) trap trapkill TERM INT check_prerequisites # validate commandline options, set resonable defaults parse_params $@ case $cmd in get-mediapolicy) get_mediapolicy "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}MediaPolicy for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${volume_name}" "${volume_mediapolicy}" fi fi ;; get-poolmember) valid_member=0 get_poolmember "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}Volume-Name ${GREEN}'%s'${MAGENTA} is a valid mediapool member.${NO_COLOR}\n" \ "${volume_name}" fi valid_member=1 fi ;; get-poolmember-next) valid_member=0 get_poolmember_next "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}Next Volume-Name from media-pool ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}'%s'\n" \ "${mediapool_name}" "${volume_name_next}" fi fi ;; get-retensiondate) get_retensiondate "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}RetensionDate for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${volume_name}" "${volume_retensiondate}" fi fi ;; get-slot) get_slot "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}Slot location for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${volume_name}" "${volume_slot}" fi fi ;; ltfs-format) ltfs_format "${volume_name}" "${tape_id}" ;; ltfs-is-mounted) ltfs_is_mounted if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}LTFS Tape is-mounted: ${GREEN}%d${NO_COLOR}\n" \ "$?" fi fi ;; ltfs-mount) ltfs_mount if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}LTFS Tape mount: ${GREEN}%d${NO_COLOR}\n" \ "$?" fi fi ;; ltfs-umount) ltfs_umount if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}LTFS Tape unmount: ${GREEN}%d${NO_COLOR}\n" \ "$?" fi fi ;; mtx-exchange) mtx_exchange "${slot_source}" "${slot_target}" ;; mtx-getlabel) mtx_getlabel $slot_source if [ $verbose -ge 1 ]; then printf "${MAGENTA}Tape Label: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" fi ;; mtx-inventory) mtx_inventory ;; mtx-load) mtx_load "${slot_source}" "${drive}" ;; mtx-transfer) mtx_transfer "${slot_source}" "${slot_target}" ;; mtx-unload) mtx_unload "${slot_source}" "${drive}" ;; mount-tape) mount_tape "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}mount tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${MAGENTA}:${NO_COLOR} %s.\n" \ "${volume_name}" "${mediapool_name}" "$?" fi fi ;; esac # return: 0 = equal, 1 = lower, 2 = greater #compare_date "20180824090000" "20180824090000" exit 0