#! /bin/sh # 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.14" # global variables color=0 date_cmd="date -u +%Y%m%d%H%M%S" # use universial time date_iso="" date_seconds="" default_changer_device="/dev/changer" dryrun=0 ltfs_mountpoint="/media/tape" ltfs_devname="" mediapools_json="/etc/dsnap-sync/MediaPools.json" mediapool_name="" quiet=false timezone="Europe/Berlin" use_mtx=0 verbose=0 volume_name="" volume_name_active="" volume_name_next="" # helper programms ATTR=attr JQ=jq LTFS=ltfs LTFSCK=ltfsck MKLTFS=mkltfs MTX=mtx SSH=ssh # ascii color BLUE= GREEN= MAGENTA= RED= YELLOW= NO_COLOR= ### # functions ### add_retensiondays_to_retensiondate () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1:-0} local volume_name=${2} local retension_days=${3:-0} if [ $verbose -ge 1 ]; then printf "${BLUE}add_retensiondays_to_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 else json_path=${mediapools_json%/*} json_file=${mediapools_json##*/} cp "$mediapools_json" $XDG_RUNTIME_DIR/$json_file fi get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 if [ $retension_days -eq 0 ]; then # get default retensiondays form given mediapool get_mediapool_retensiondays $mediapool_name if [ $? -eq 0 ]; then retension_days=${mediapool_defaultretensiondays} fi fi if [ $verbose -ge 2 ]; then printf "${MAGENTA}New RetensionDays: ${NO_COLOR}'%s'.\n" \ "${retension_days}" fi # get active retensiondate for given tape get_retensiondate $mediapool_name $volume_name if [ $? -eq 0 ]; then # calculate retensiondate in seconds date_iso_to_seconds "${volume_retensiondate}" if [ $? -eq 0 ]; then volume_retensiondate_seconds=$(($date_seconds + $retension_days * 24 * 60 * 60)) if [ $verbose -ge 3 ]; then printf "${MAGENTA}New RetensionDate in seconds is: ${NO_COLOR}'%s'.\n" \ "${volume_retensiondate_seconds}" fi # format to iso date_seconds_to_string "${volume_retensiondate_seconds}" if [ $? -eq 0 ]; then volume_retensiondate=${date_iso} if [ $verbose -ge 2 ]; then date_string_tz=$(echo $volume_retensiondate | cut -c 1-8) volume_date=$(date --date="${date_string_tz}Z") printf "${MAGENTA}RetensionDate is: ${NO_COLOR}'%s'.\n" \ "${volume_date}" fi fi fi fi # update retensionsdate if [ ${#volume_name} -ge 1 ]; then cmd="jq --monochrome-output --ascii-output '.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member \ | map(.VolumeName == \"$volume_name\") | index(true)' \ ${mediapools_json}" tape_index=$(eval $cmd) if [ $? -eq 0 ]; then cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member[$tape_index] \ | .RetensionDate) \ |= \"$volume_retensiondate\" ' \ ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" $(eval $cmd) if [ $? -eq 0 ]; then cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" else if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_retensiondate" "$volume_name" fi return 1 fi else return 1 fi if [ $verbose -ge 2 ]; then printf "${MAGENTA}New RetensionDate in UTC for volume ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$volume_retensiondate" fi fi } check_prerequisites () { # requested binaries: which ${ATTR} >/dev/null 2>&1 || { printf "'%s' is not installed.\n" ${ATTR} && exit 1; } 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 findmnt >/dev/null 2>&1 || { printf "'findmnt' is not installed." && 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; } which perl >/dev/null 2>&1 || { printf "'%s' is not installed.\n" perl && exit 1; } which awk >/dev/null 2>&1 || { printf "'%s' is not installed.\n" awk && exit 1; } which sed >/dev/null 2>&1 || { printf "'%s' is not installed.\n" sed && 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 } date_iso_to_seconds () { local date_string=$1 year=$(echo $date_string | cut -c 1-4) month=$(echo $date_string | cut -c 5-6) day=$(echo $date_string | cut -c 7-8) hour=$(echo $date_string | cut -c 9-10) minute=$(echo $date_string | cut -c 11-12) second=$(echo $date_string | cut -c 13-14) test ${month#0} -gt 12 && printf "${RED}Error:${NO_COLOR} Invalid argument month: '%s'\n" $month && return 1 test ${day#0} -gt 31 && printf "${RED}Error:${NO_COLOR} Invalid argument day: '%s'\n" $day && return 1 test ${hour#0} -gt 23 && printf "${RED}Error:${NO_COLOR} Invalid argument hour: '%s'\n" $hour && return 1 test ${minute#0} -gt 59 && printf "${RED}Error:${NO_COLOR} Invalid argument minute: '%s'\n" $minute && return 1 test ${second#0} -gt 50 && printf "${RED}Error:${NO_COLOR} Invalid argument second: '%s'\n" $second && return 1 date_iso=$(printf "%s-%s-%s %s:%s:%s\n" \ ${year} ${month} ${day} ${hour} ${minute} ${second}) date_seconds=$(date --date="$date_iso" +"%s") } date_seconds_to_iso () { local date_string=$1 date_iso=$(date --date="@$date_string" +"%Y-%m-%d %H:%M:%S") } date_seconds_to_string () { local date_string=$1 date_iso=$(date --date="@$date_string" +"%Y%m%d%H%M%S") } date_string_to_iso () { local date_string=$1 year=$(echo $date_string | cut -c 1-4) month=$(echo $date_string | cut -c 5-6) day=$(echo $date_string | cut -c 7-8) hour=$(echo $date_string | cut -c 9-10) minute=$(echo $date_string | cut -c 11-12) second=$(echo $date_string | cut -c 13-14) test ${month#0} -gt 12 && printf "${RED}Error:${NO_COLOR} Invalid argument month: '%s'\n" $month && return 1 test ${day#0} -gt 31 && printf "${RED}Error:${NO_COLOR} Invalid argument day: '%s'\n" $day && return 1 test ${hour#0} -gt 23 && printf "${RED}Error:${NO_COLOR} Invalid argument hour: '%s'\n" $hour && return 1 test ${minute#0} -gt 59 && printf "${RED}Error:${NO_COLOR} Invalid argument minute: '%s'\n" $minute && return 1 test ${second#0} -gt 59 && printf "${RED}Error:${NO_COLOR} Invalid argument second: '%s'\n" $second && return 1 date_iso=$(printf "%s-%s-%s %s:%s:%s\n" \ ${year} ${month} ${day} ${hour} ${minute} ${second}) } die () { error "$@" exit 1 } error () { printf "\n==> ERROR: %s\n" "$@" notify_error 'Error' 'Check journal for more information.' } >&2 get_lastwrite () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} #local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}get_lastwrite...${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 if [ ${#volume_name} -ge 1 ]; then get_poolmember $mediapool_name $volume_name if [ $? -ne 0 ]; then printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" return 1 fi # select last write date for given volume cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | select(.VolumeName == \"${volume_name}\") \ | .LastWrite ' \ ${mediapools_json}" else # select volume with latest write date cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | sort_by(.LastWrite) \ | .[-1] \ | .VolumeName ' \ ${mediapools_json}" volume_name=$(eval $cmd) volume_name=$(echo $volume_name | sed -e 's/"//g') cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | sort_by(.LastWrite) \ | .[-1] \ | .LastWrite ' \ ${mediapools_json}" fi volume_name_next=$volume_name volume_lastwrite=$(eval $cmd) if [ ${#volume_lastwrite} -gt 1 ]; then volume_lastwrite=$(echo $volume_lastwrite | sed -e 's/"//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}volume_lastwrite for volume ${GREEN}'%s'${MAGENTA} in media-pool ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" "$volume_lastwrite" fi else return 1 fi } 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) volume_mediapolicy=$(echo $volume_mediapolicy | sed -e 's/"//g') if [ $verbose -ge 2 ]; 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_mediapool_name () { local mediapools_json=${mediapools:-$mediapools_json} local volume_name=${1} if [ $verbose -ge 1 ]; then printf "${BLUE}get_mediapool_name...${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[] \ | .Name as \$MediaPoolName \ | .Member[].VolumeName \ | select(. == \"${volume_name}\") \ | \$MediaPoolName' ${mediapools_json}" mediapool_name=$(eval $cmd) mediapool_name=$(echo $mediapool_name | sed -e 's/"//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Media-pool name for VolumeName %s: ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" fi } get_mediapool_names () { local mediapools_json=${mediapools:-$mediapools_json} #local mediapool_name=${1} if [ $verbose -ge 1 ]; then printf "${BLUE}get_mediapool_names...${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[] \ | .Name ' \ ${mediapools_json}" mediapool_names=$(eval $cmd) mediapool_names=$(echo $mediapool_names | sed -e 's/"//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Media-pool names: ${GREEN}'%s'${NO_COLOR}\n" \ "$mediapool_names" fi } get_mediapool_retensiondays () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} if [ $verbose -ge 1 ]; then printf "${BLUE}get_mediapool_retensiondays...${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 if [ ${#mediapool_name} -ge 1 ]; then # select default retension days for given pool cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .DefaultRetensionDays ' \ ${mediapools_json}" fi mediapool_defaultretensiondays=$(eval $cmd) mediapool_defaultretensiondays=$(echo $mediapool_defaultretensiondays | sed -e 's/"//g') if [ ${#mediapool_defaultretensiondays} -ge 1 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}default retension days for media-pool ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$mediapool_name" "$mediapool_defaultretensiondays" fi else if [ $verbose -ge 1 ]; then printf "${RED}Error: ${MAGENTA}No retension days for media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$mediapool_name" "$mediapool_defaultretensiondays" fi return 1 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 --ascii-output '.MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[].VolumeName' \ ${mediapools_json}" poolmember=$(eval $cmd) poolmember=$(echo $poolmember | sed -e 's/"//g') 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 i=0 for i in $poolmember ; do if [ "${volume_name}" = "any" ]; then volume_name = $i if [ $verbose -ge 2 ]; then printf "${MAGENTA}selecting first volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$i" "$mediapool_name" fi return 0 break fi if test "$i" = "${volume_name}"; then if [ $verbose -ge 2 ]; 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:-"any"} 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 get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | sort_by(.LastWrite) \ | .[0] \ | .VolumeName ' \ ${mediapools_json}" volume_poolmember=$(eval $cmd) volume_poolmember=$(echo $volume_poolmember | sed -e 's/"//g') 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} -ge 1 ]; then if [ $member = $volume_name ]; then volume_index=$(($i+1)) fi fi i=$(($i + 1)) done if [ $verbose -ge 2 ]; 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 get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 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 2 ]; 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 get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ | select(.Name == \"${mediapool_name}\") \ | .Member[] \ | select(.VolumeName == \"${volume_name}\")) \ | .RetensionDate ' \ ${mediapools_json}" volume_retensiondate=$(eval $cmd) if [ ${#volume_retensiondate} -gt 1 ]; then volume_retensiondate=$(echo $volume_retensiondate | sed -e 's/"//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}RetensionDate in UTC 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 else if ! quiet; then printf "${MAGENTA}No RetensionDate for given tape ${GREEN}'%s'${MAGENTA} in media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" fi return 1 fi } ltfs_get_attribute () { local ltfs_attribute_name=${1:-volumeName} if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_get_attribute...${NO_COLOR}\n" fi make_err_file # Reference: https://www.ibm.com/support/knowledgecenter/en/STQNYL_2.4.0/ltfs_hints_virtual_extended_attribute.html # eg: ltfs.indexCreator # ltfs.volumeBlocksize # ltfs.volumeName, ltfs.volumeSerial, ltfs.volumeUUID ltfs_attribute_value=$(${ATTR} -g ltfs.$ltfs_attribute_name $ltfs_mountpoint 2>${ERRFILE}) rm -f ${ERRFILE} if [ $? -eq 0 ]; then ltfs_attribute_value=$(echo ${ltfs_attribute_value##*:} | sed -e 's/\r\n//g') if [ $verbose -ge 1 ]; then printf "${MAGENTA}LTFS attribute ${GREEN}'%s'${MAGENTA} is: ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_attribute_name" "$ltfs_attribute_value" fi return 0 else if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS attribute ${GREEN}'%s'${MAGENTA} isn't valid${NO_COLOR}\n" \ "$ltfs_attribute_name" fi fi return $? } ltfs_get_devname () { if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_get_devname...${NO_COLOR}\n" fi ltfs_is_mounted if [ $? -eq 1 ]; then make_err_file ltfs -o device_list -o quiet 2>/dev/null -o device_list 2>${ERRFILE} # ltfs returns '1' RET=$? if [ $RET -eq 1 ]; then ltfs_devname=$(cat $ERRFILE | awk -F ',' ' /Vender ID/ {print $1}' | awk -F '= ' '{print $2}') if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS device name: ${GREEN}'%s'${NO_COLOR}\n" \ $ltfs_devname fi rm -f ${ERRFILE} return 0 else return $RET fi fi } ltfs_format () { local volume_name=${1} local volume_serial=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_format...${NO_COLOR}\n" fi if [ ${#volume_serial} -eq 0 ]; then tape_id=$(echo $volume_name | sed -e 's/\([[:alpha:]]*-\)//g') # tape_id needs to be exactly 6 character long volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id})))) volume_serial="${volume_serial}${tape_id}" fi if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS format tape ${GREEN}'%s'${MAGENTA} with serial ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$volume_serial" fi make_err_file ${MKLTFS} --device=$ltfs_devname --volume-name=${volume_name} --tape-serial=${volume_serial} --force 2>${ERRFILE} RET=$? rm -f ${ERRFILE} return $RET } ltfs_is_mounted () { local ltfs_devname_mounted if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_is_mounted...${NO_COLOR}\n" fi ltfs_devname_mounted=$(findmnt -n -T $ltfs_mountpoint -o source | awk -F ':' '{print $2}') if [ ${#ltfs_devname_mounted} -gt 1 ]; then ltfs_devname=$ltfs_devname_mounted if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape is mounted via ${GREEN}'%s'${MAGENTA} at ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_devname" "$ltfs_mountpoint" fi return 0 else if [ $verbose -ge 2 ]; then printf "${MAGENTA}findmnt: no target mounted at ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_mountpoint" fi 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 make_err_file 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 1>/dev/null 2>${ERRFILE} else ${LTFS} -o devname=$ltfs_devname -o verbose=0 $ltfs_mountpoint 1>/dev/null 2>${ERRFILE} fi if [ $? -eq 0 ]; then rm -f ${ERRFILE} return 0 else # format tape if needed if [ -z $volume_name_active ]; then slot_source="0" mtx_getlabel $slot_source fi need_format=$(grep "medium is not partitioned" ${ERRFILE}) rm -f ${ERRFILE} if [ ${#need_format} -ge 1 ]; then ltfs_format ${volume_name_active} ltfs_mount fi return $? fi else if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape ${GREEN}'%s'${MAGENTA} is mounted to ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_devname" "$ltfs_mountpoint" fi fi } ltfs_reformat () { local volume_name=${1} if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_reformat...${NO_COLOR}\n" fi ltfs_is_mounted if [ $? -eq 0 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape ${GREEN}'%s'${MAGENTA} is mounted to ${GREEN}'%s'${NO_COLOR}\n" \ "$ltfs_devname" "$ltfs_mountpoint" fi slot_source="0" mtx_getlabel $slot_source if [ ${#volume_name} -gt 0 ] && [ $volume_name_active != $volume_name ]; then get_mediapool_name $volume_name if [ $? -eq 0 ]; then ltfs_umount if [ $? -eq 0 ]; then mtx_unload if [ $? -eq 0 ]; then mount_tape "${mediapool_name}" "${volume_name}" fi fi fi fi else if [ ! -d $ltfs_mountpoint ]; then mkdir -p $ltfs_mountpoint fi get_mediapool_name "${volume_name}" if [ $? -eq 0 ]; then get_slot "${mediapool_name}" "${volume_name}" if [ $? -eq 0 ]; then slot_source=0 mtx_getlabel ${slot_source} if [ $? -eq 0 ]; then if [ ${volume_name_active} != ${volume_name} ]; then mtx_unload ${slot_source} mtx load ${volume_slot} fi make_err_file 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 1>/dev/null 2>${ERRFILE} else ${LTFS} -o devname=$ltfs_devname -o verbose=0 $ltfs_mountpoint 1>/dev/null 2>${ERRFILE} fi if [ $? -ge 0 ]; then if [ -z $volume_name_active ]; then slot_source="0" mtx_getlabel $slot_source fi need_format=$(grep "medium is not partitioned" ${ERRFILE}) rm -f ${ERRFILE} fi fi fi fi fi if [ ${#volume_name} -eq 0 ] || [ $volume_name_active = $volume_name ]; then tape_id=$(echo $volume_name_active | sed -e 's/\([[:alpha:]]*-\)//g') # tape_id needs to be exactly 6 character long volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id})))) volume_serial="${volume_serial}${tape_id}" if [ ${#need_format} -ge 1 ]; then ltfs_format ${volume_name_active} ${volume_serial} else ltfs_umount if [ $? -eq 0 ]; then ltfs_wipe if [ $? -eq 0 ]; then ltfs_format ${volume_name_active} ${volume_serial} fi fi fi if [ $? -eq 0 ]; then ltfs_mount fi fi return $? } ltfs_umount () { if [ $verbose -ge 1 ]; then printf "${BLUE}ltfs_umount...${NO_COLOR}\n" fi ltfs_is_mounted if [ $? -eq 0 ]; then if [ $verbose -ge 3 ]; then printf "${MAGENTA}unmounting LTFS tape ${GREEN}'%s'${NO_COLOR}.\n" \ "$ltfs_mountpoint" fi umount $ltfs_mountpoint 2>/dev/null ret=$? case $ret in 0) if [ $verbose -ge 2 ]; then printf "${MAGENTA}LTFS tape ${GREEN}'%s'${MAGENTA} unmounted.${NO_COLOR}\n" \ "$ltfs_mountpoint" fi return 0 ;; *) printf "${RED}Error: '%s' ${MAGENTA}LTFS tape ${GREEN}'%s'${MAGENTA} is in use!${NO_COLOR}\n" \ "$ret" "$ltfs_mountpoint" return 1 ;; esac fi } ltfs_wipe () { 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 if [ $verbose -ge 2 ]; then printf "${MAGENTA}Restore the LTFS medium to an unpartitioned medium ...${NO_COLOR}\n" fi # ltfs_error.h #define PROG_NO_ERRORS 0x00 /* Success */ #define PROG_TREAT_SUCCESS 0x01 /* Treat as success */ #define PROG_REBOOT_REQUIRED 0x02 /* Reboot required */ #define PROG_UNCORRECTED 0x04 /* Cannot recover, the cartridge is modified */ #define PROG_OPERATIONAL_ERROR 0x08 /* Get device error while processing, the cartridge may be modified */ #define PROG_USAGE_SYNTAX_ERROR 0x10 /* Wrong argument */ #define PROG_CANCELED_BY_USER 0x20 /* Canceled by user */ #define PROG_SHARED_LIB_ERROR 0x40 /* Library error */ ${MKLTFS} --device=$ltfs_devname --wipe --force 2>${ERRFILE} RET=$? rm -f ${ERRFILE} if [ $verbose -ge 3 ]; then printf "${MAGENTA}%s returncode: ${GREEN}%s${NO_COLOR}\n" \ ${MKLTFS} $RET fi case $RET in 1) printf "${MAGENTA}%s: Treat as success ${GREEN}%s${NO_COLOR}\n" \ ${MKLTFS} $RET return 0 ;; 2) printf "${MAGENTA}%s: Reboot required ${GREEN}%s${NO_COLOR}\n" \ ${MKLTFS} $RET return 0 ;; 8) printf "${MAGENTA}%s: Get device error while processing, the cartridge may be modified ${GREEN}%s${NO_COLOR}\n" \ ${MKLTFS} $RET return $RET ;; *) return $RET ;; esac } 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 } media_change () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}media_change...${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 if [ ${#mediapool_name } -ge 1 ]; then if [ ${#volume_name } -eq 0 ]; then get_lastwrite "${mediapool_name}" if [ $verbose -ge 2 ]; then printf "${MAGENTA}Last written Volume: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name_next}" fi fi add_retensiondays_to_retensiondate "${mediapool_name}" "${volume_name}" "${retension_days}" if test $? -eq 0; then if [ $verbose -ge 1 ]; then date_string_to_iso "${volume_retensiondate}" if [ $? -eq 0 ]; then volume_date=$(date --date="${date_iso}Z") printf "${MAGENTA}Updated RetensionDate date for ${GREEN}'%s'${MAGENTA} to: ${NO_COLOR}'%s'.\n" \ "${volume_name}" "${volume_date}" fi fi fi get_poolmember_next "${mediapool_name}" if test $? -eq 0; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}MediaPool: ${GREEN}%s${NO_COLOR} (next tape: ${GREEN}%s${NO_COLOR})\n" \ "${mediapool_name}" "${volume_name_next}" fi update_lastwrite "${mediapool_name}" "${volume_name_next}" "${date_string}" fi fi } mount_tape () { local mediapool_name=${1} local volume_name=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}mount_tape...${NO_COLOR}\n" fi if [ $verbose -ge 2 ]; then if [ ${#volume_name } -ge 1 ]; then printf "${MAGENTA}MediaPool: ${GREEN}%s${NO_COLOR} (mounting tape: ${GREEN}%s${NO_COLOR})\n" \ "${mediapool_name}" "${volume_name}" else printf "${MAGENTA}MediaPool: ${GREEN}%s${NO_COLOR} (mounting next tape)\n" \ "${mediapool_name}" fi fi ltfs_is_mounted if test $? -eq 0; then # get date from last written tape in given mediapool if [ "${#volume_name}" -eq 0 ]; then get_lastwrite ${mediapool_name} if [ $? != 0 ]; then exit 1 fi fi # get label from tape in given drive slot slot_source="0" mtx_getlabel $slot_source if [ $? -eq 0 ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Active tape in drive: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name_active}" fi if [ "${#volume_name_active}" -ge 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Re-Mounting requested Tape: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" fi ltfs_umount if [ $? -eq 0 ]; then mtx_unload if [ $? -eq 0 ]; then mount_tape "${mediapool_name}" "${volume_name}" return 0 else return $? fi else return $? fi fi fi # check if given tape is poolmember of selected pool get_poolmember ${mediapool_name} ${volume_name} if [ $? -eq 0 ]; then # volume_name is member of given mediapool get_mediapolicy ${mediapool_name} ${volume_name_active} if [ ${#volume_mediapolicy} -gt 0 ]; then if [ ${volume_mediapolicy} = "append" ] ; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ "${volume_mediapolicy}" fi volume_retensiondate="20180101000000" get_retensiondate ${mediapool_name} ${volume_name} if [ $? -eq 0 ]; then date_now=$($date_cmd) compare_date $date_now $volume_retensiondate if [ $? -eq 2 ]; then # retensiondate has exposed: use it if [ $verbose -ge 3 ]; then printf "${MAGENTA}Valid tape, retensiondate has exposed: ${GREEN}%s${NO_COLOR}\n" \ "${volume_retensiondate}" fi return 0 fi if [ $? -eq 1 ]; then # respect active retensiondate: unload given tape if [ $verbose -ge 3 ]; then printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" "${volume_retensiondate}" fi ltfs_umount mtx_unload # use next volume_name from pool if [ $verbose -ge 3 ]; then printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \ "${mediapool_name}" fi get_poolmember_next ${mediapool_name} ${volume_name} get_slot ${mediapool_name} ${volume_name_next} mtx_load ${volume_slot} ltfs_mount if [ $? -eq 0 ]; then return 0 fi fi return 0 fi if [ ${volume_mediapolicy} = "overwrite" ] ; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ "${volume_mediapolicy}" fi 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 if [ $verbose -ge 3 ]; then printf "${MAGENTA}Valid tape, wipe and reformat: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" fi ltfs_wipe ltfs_format ${volume_name} ${volume_serial} if [ $? -eq 0 ]; then return 0 fi fi if [ $? -eq 1 ]; then # respect active retensiondate: unload given tape if [ $verbose -ge 3 ]; then printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" "${volume_retensiondate}" fi ltfs_umount mtx_unload # use next volume_name from pool if [ $verbose -ge 3 ]; then printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \ "${mediapool_name}" fi get_poolmember_next ${mediapool_name} ${volume_name} get_slot ${mediapool_name} ${volume_name_next} mtx_load ${volume_slot} ltfs_mount if [ $? -eq 0 ]; then return 0 fi fi fi fi fi else # volume_name is not member of given pool ltfs_umount if [ $? -eq 0 ]; then mtx_unload if [ $? -eq 0 ]; then if [ "${#volume_name}" -eq 0 ]; then get_lastwrite ${mediapool_name} fi get_poolmember_next ${mediapool_name} ${volume_name} if [ $? -eq 0 ]; then mtx load ${volume_name_next} ltfs_mount fi else return $? fi else return $? fi fi else if [ $verbose -ge 1 ]; then printf "${MAGENTA}No LTFS Tape mounted...${NO_COLOR}\n" fi if [ "${#volume_name}" -eq 0 ]; then # set volume_name and last write date #get_lastwrite ${mediapool_name} get_poolmember_next ${mediapool_name} if [ "${#volume_name_next}" -ge 1 ]; then volume_name=${volume_name_next} fi fi # check label of tape in given drive slot (slot=0) slot_source="0" mtx_getlabel $slot_source if [ $? -eq 0 ] && [ "${#volume_name_active}" -gt 1 ]; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}Tape in drive: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name_active}" fi if [ "${#volume_name_active}" -gt 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Active tape ${GREEN}%s${MAGENTA} needs to be exchanged with ${GREEN}%s${NO_COLOR}\n" \ "${volume_name_active}" "${volume_name}" fi mtx_unload if [ $? -eq 0 ]; then mount_tape "${mediapool_name}" "${volume_name}" if [ $? -eq 0 ]; then return 0 else return $? fi else return $? fi fi else # mount new tape get_slot ${mediapool_name} ${volume_name} if [ $? -eq 0 ]; then mtx_load ${volume_slot} fi fi # volume_name is member of given mediapool get_mediapolicy ${mediapool_name} ${volume_name} if [ ${#volume_mediapolicy} -gt 0 ]; then if [ ${volume_mediapolicy} = "append" ] ; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ "${volume_mediapolicy}" fi #volume_retensiondate="20180101000000" get_retensiondate ${mediapool_name} ${volume_name} date_now=$($date_cmd) compare_date $date_now $volume_retensiondate RET=$? if [ $RET -eq 2 ]; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}RetensionDate has exposed, mount the tape\n" fi ltfs_mount return 0 elif [ $RET -eq 1 ]; then if [ $verbose -ge 1 ]; then printf "${MAGENTA}Tape is bocked via RetensionDate.\n" fi get_poolmember_next "${mediapool_name}" if test $? -eq 0; then if [ $verbose -ge 2 ]; then printf "${MAGENTA}MediaPool: ${GREEN}%s${NO_COLOR} (using next tape: ${GREEN}%s${NO_COLOR})\n" \ "${mediapool_name}" "${volume_name_next}" fi # recurse all over again mount_tape "${mediapool_name}" "${volume_name_next}" return 0 fi fi 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_mount if [ $? -eq 0 ]; then ltfs_wipe ltfs_format ${volume_name} ${volume_serial} if [ $? -eq 0 ]; then return 0 fi fi fi if [ $? -eq 1 ]; then # respect active retensiondate: unload given tape mtx_unload if [ $? -eq 0 ]; then # use next volume_name from pool get_poolmember_next ${mediapool_name} ${volume_name} mount_tape "${mediapool_name}" "${volume_name}" return 0 else return $? fi fi fi 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=$? rm -f ${ERRFILE} } 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}mtx_getlabel...${NO_COLOR}\n" fi make_temp_file ${MTX} -f $changer_device status >${TMPFILE} 2>/dev/null RET=$? case ${slot_source} in 0) if [ $verbose -ge 3 ]; then printf "Calling: ${GREEN}%s${MAGENTA} -f ${GREEN}%s${MAGENTA} %s${NO_COLOR}\n" \ "${MTX}" "${changer_device}" "${slot_source}" fi volume_name_active=$(perl -ne ' /Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE}) volume_name_active=$(echo $volume_name_active | sed -e 's/ *$//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \ "${slot_source}" "${volume_name_active}" fi ;; [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 volume_name=$(perl -ne ' /Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE}) volume_name=$(echo $volume_name | sed -e 's/ *$//g') if [ $verbose -ge 2 ]; then printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \ "${slot_source}" "${volume_name}" fi ;; *) 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 1>/dev/null 2>${ERRFILE} RET=$? rm -f ${ERRFILE} if [ $verbose -ge 2 ]; then if [ $RET -eq 0 ]; then printf "${MAGENTA}Successfully loaded tape to drive ${GREEN}%s${NO_COLOR}\n" \ "$drive" else printf "${RED}Error: Can't loaded tape to drive ${GREEN}%s${NO_COLOR}\n" \ "$drive" return $RET fi fi } mtx_status () { local changer_device=${changer_device:-$default_changer_device} if [ $verbose -ge 1 ]; then printf "${BLUE}mtx_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}mtx_transfer...${NO_COLOR}\n" fi make_err_file ${MTX} -f $changer_device transfer $slot_source $slot_target 2>${ERRFILE} RET=$? rm -f ${ERRFILE} } mtx_unload () { local changer_device=${changer_device:-$default_changer_device} local slot_source=${1} local drive=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}mtx_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 1>/dev/null 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${NO_COLOR}\n" \ "${MTX}" "${changer_device}" "${slot_source}" "${drive}" fi fi return $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 ;; --add-retensiondays) shift 1 pool_params=${*} pool_params="${pool_params%% -[-a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 mediapool_name="$1" volume_name="$2" test $count -ge 3 && retension_days="$3" set -- $params shift $count cmd=add-retensiondays ;; #--dry-run|--dryrun) # dryrun=1 # shift 1 # ;; --get-lastwrite) shift 1 pool_params=${*} pool_params="${pool_params%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-lastwrite ;; --get-mediapolicy) shift 1 pool_params=${*} pool_params="${pool_params%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-mediapolicy ;; --get-mediapool-name) volume_name=$2 shift 2 cmd=get-mediapool-name ;; --get-mediapools) shift 1 cmd=get-mediapools ;; --get-poolmember) shift 1 pool_params=${*} pool_params="${pool_params%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 1 && printf "missing argument: mediapool_name\n" && exit 1 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%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 1 && printf "missing argument: mediapool_name\n" && exit 1 test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-poolmember-next ;; --get-retensiondate) shift 1 pool_params=${*} pool_params="${pool_params%% -[-a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-retensiondate ;; --get-retensiondays) shift 1 pool_params=${*} pool_params="${pool_params%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 1 && printf "missing argument: mediapool_name\n" && exit 1 mediapool_name="$1" set -- $params shift $count cmd=get-mediapool-retensiondays ;; --get-slot) shift 1 pool_params=${*} pool_params="${pool_params%% -[a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 test $count -ge 1 && mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=get-slot ;; --ltfs-format) shift 1 ltfs_params=${*} ltfs_params="${ltfs_params%% -[a-z]*}" params=$* set -- $ltfs_params count=$# test $count -lt 1 && printf "missing argument: volume_name\n" && exit 1 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-reformat) shift 1 count=$# test $count -lt 1 && printf "missing argument: volume_name\n" && exit 1 test $count -ge 1 && volume_name="$1" shift $count cmd=ltfs-reformat ;; --ltfs-umount) shift 1 cmd=ltfs-umount ;; --media-change) shift 1 tape_params=${*} tape_params="${tape_params%% -[a-z]*}" params=$* set -- $tape_params count=$# test $count -lt 1 && printf "missing argument: mediapool_name\n" && exit 1 mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=media-change ;; --mount) shift 1 tape_params=${*} tape_params="${tape_params%% -[a-z]*}" params=$* set -- $tape_params count=$# test $count -lt 1 && printf "missing argument: mediapool_name\n" && exit 1 mediapool_name="$1" test $count -ge 2 && volume_name="$2" set -- $params shift $count cmd=mount ;; --mtx-exchange) shift slots=${*} slots="${slots%% -[-a-z]*}" params=$* set -- $slots count=$# test $count -lt 2 && printf "missing arguments: slot_source, slot_target\n" && exit 1 slot_source="$1" slot_target="$2" set -- $params shift $count cmd=mtx-exchange ;; --mtx-getlabel) shift slots=${*} slots="${slots%% -[-a-z]*}" 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%% -[-a-z]*}" params=$* set -- $slots count=$# test $count -lt 1 && printf "missing argument: slot_source\n" && exit 1 slot_source="$1" test $count -eq 2 && drive="$2" set -- $params shift $count cmd=mtx-load ;; --mtx-status) shift cmd=mtx-status ;; --mtx-transfer) shift slots=${*} slots="${slots%% -[-a-z]*}" params=$* set -- $slots count=$# test $count -lt 2 && printf "missing argument: slot_source, slot_target\n" && exit 1 slot_source="${1}" slot_target="${2}" set -- $params shift $count cmd=mtx-transfer ;; --mtx-unload) shift slots=${*} slots="${slots%% -[-a-z]*}" params=$* set -- $slots count=$# test $count -lt 1 && printf "missing argument: slot_source\n" && exit 1 slot_source="$1" test $count -eq 2 && drive="$2" set -- $params shift $count cmd=mtx-unload ;; #-p|--port) # port=$2 # shift 2 # ;; #--remote) # remote=$2 # shift 2 # ;; -q|--quiet) quiet=true shift 1 ;; --use-mtx) use_mtx=1 shift 1 ;; --ltfs-devname) ltfs_devname="$2" shift 2 ;; --ltfs-getattribute) shift 1 ltfs_params=${*} ltfs_params="${ltfs_params%% -[-a-z]*}" params=$* set -- $ltfs_params count=$# test $count -eq 0 && ltfs_attribute_name="volumeName" test $count -eq 1 && ltfs_attribute_name="$1" set -- $params shift $count cmd=ltfs-getattribute ;; --update-lastwrite) shift 1 pool_params=${*} pool_params="${pool_params%% -[-a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 mediapool_name="$1" volume_name="$2" test $count -ge 3 && date_string="$3" set -- $params shift $count cmd=update-lastwrite ;; --update-retensiondate) shift 1 pool_params=${*} pool_params="${pool_params%% -[-a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, volume_name\n" && exit 1 mediapool_name="$1" volume_name="$2" test $count -ge 3 && date_string="$3" set -- $params shift $count cmd=update-retensiondate ;; --update-retensiondays) shift 1 pool_params=${*} pool_params="${pool_params%% -[-a-z]*}" params=$* set -- $pool_params count=$# test $count -lt 2 && printf "missing arguments: mediapool_name, retensiondays\n" && exit 1 mediapool_name="$1" test $(expr $2 : '^[[:digit:]]\+') -eq 0 && printf "missing arguments: retensiondays must be an integer\n" && exit 1 mediapool_defaultretensiondays="$2" set -- $params shift $count cmd=update-mediapool-retensiondays ;; -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 $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 [ ${#remote} -ge 1 ]; then # printf "Remote Settings\n" # printf " remote host: '%s'\n" "$remote" # printf " ssh options: '%s'\n" "$ssh" #fi if [ $verbose -ge 1 ]; then tape_options="verbose_level=$verbose"; fi if $quiet ; then tape_options="verbose_level=0 quiet=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 } 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 } update_lastwrite () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1:-0} local volume_name=${2} local date_string=${3:-now} if [ $verbose -ge 1 ]; then printf "${BLUE}update_lastwrite...${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 else json_path=${mediapools_json%/*} json_file=${mediapools_json##*/} cp "$mediapools_json" $XDG_RUNTIME_DIR/$json_file fi if [ ${#volume_name} -ge 1 ]; then get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 # update last write date for given volume (date field in utc) if [ "${date_string}" = "now" ]; then volume_lastwrite=$($date_cmd) else volume_lastwrite=$date_string fi cmd="jq --monochrome-output --ascii-output '.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member \ | map(.VolumeName == \"$volume_name\") | index(true)' \ ${mediapools_json}" tape_index=$(eval $cmd) if [ $? -eq 0 ]; then cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member[$tape_index] \ | .LastWrite) \ |= \"$volume_lastwrite\" ' \ ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" $(eval $cmd) if [ $? -eq 0 ]; then cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" else return 1 fi else return 1 fi if [ $verbose -ge 2 ]; then printf "${MAGENTA}LastWrite in UTC for for volume ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$volume_lastwrite" fi fi } update_mediapool_retensiondays () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1:-0} local mediapool_defaultretensiondays=${2} if [ $verbose -ge 1 ]; then printf "${BLUE}update_mediapool_retensiondays..${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 else json_path=${mediapools_json%/*} json_file=${mediapools_json##*/} cp "$mediapools_json" $XDG_RUNTIME_DIR/$json_file fi if [ ${mediapool_defaultretensiondays} -ge 0 ]; then cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .DefaultRetensionDays) \ |= \"${mediapool_defaultretensiondays}\" ' \ ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" $(eval $cmd) if [ $? -eq 0 ]; then cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" else if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} Can't update DefaultRetensinDays ${GREEN}'%s'${MAGENTA} in media-pool file ${GREEN}'%s'${NO_COLOR}\n" \ "$mediapool_defaultretensiondays" "$mediapools_json" fi return 1 fi else return 1 fi } update_retensiondate () { local mediapools_json=${mediapools:-$mediapools_json} local mediapool_name=${1:-0} local volume_name=${2} local date_string=${3:-now} if [ $verbose -ge 1 ]; then printf "${BLUE}update_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 else json_path=${mediapools_json%/*} json_file=${mediapools_json##*/} cp "$mediapools_json" $XDG_RUNTIME_DIR/$json_file fi if [ ${#volume_name} -ge 1 ]; then get_poolmember $mediapool_name $volume_name test $? -ne 0 && printf "${RED}Error:${MAGENTA} tape ${GREEN}'%s'${MAGENTA} in not a member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_name" "$mediapool_name" && return 1 # update retension date for given volume (date field in utc) if [ "${date_string}" = "now" ]; then volume_retensiondate=$($date_cmd) else volume_retensiondate=$date_string fi cmd="jq --monochrome-output --ascii-output '.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member \ | map(.VolumeName == \"$volume_name\") | index(true)' \ ${mediapools_json}" tape_index=$(eval $cmd) if [ $? -eq 0 ]; then cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ | select(.Name == \"$mediapool_name\") \ | .Member[$tape_index] \ | .RetensionDate) \ |= \"$volume_retensiondate\" ' \ ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" $(eval $cmd) if [ $? -eq 0 ]; then cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" else if [ $verbose -ge 1 ]; then printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \ "$volume_retensiondate" "$volume_name" fi return 1 fi else return 1 fi if [ $verbose -ge 3 ]; then printf "${MAGENTA}RetensionDate for for volume ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}%s${NO_COLOR}\n" \ "$volume_name" "$volume_retensiondate" fi fi } usage () { cat < ) --color Enable colored output messages --get-lastwrite extract LastWrite attribute from given Pool member (JSON-File) (input attribute: []) without given volume_name, extract Pool member that was last witten to --get-mediapool-name extract MediaPool name for given VolumeName from configuration (JSON-File) (input attribute: ) --get-mediapools extract MediaPool names from configuration (JSON-File) --get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File) (input attribute: []) --get-poolmember extract VolumeName attribute from Pool configuration (JSON-File) (input attribute: []) --get-poolmember-next extract VolumeName for next usable Pool member (JSON-File) (input attribute: [volume_name]) --get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File) (input attribute: []) --get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File) (input attribute: ) --get-slot extract Slot attribute from Pool configuration (JSON-File) (input attribute: []) --ltfs-getattribute report ltfs extended attribute for mounted tape (input attribute: ) --ltfs-format format tape (input attribute: ) --ltfs-is-mounted returns true, if ltfs tape is already mounted --ltfs-mount mount a ltfs tape (returns true on success) --ltfs-reformat reformat mounted tape (input attribute: []) --ltfs-umount unmount a ltfs tape (returns true on success) --media-change Update RetensionDate for last written Pool-Tape and und exchange tapes in slots (input attribute: []) --mtx-exchange exchange tapes in slots (input attribute: ) --mtx-getlabel report tape label/barcode for tape in drive (input attribute: ) --mtx-inventory run inquriy task for tape-changer --mtx-load load a tape to target slot (input attribute: ) --mtx-status list changer slot status --mtx-transfer transfer a tape to target slot (input attribute: ) --mtx-unload unload a tape (input attribute: slot_source drive) --mount make tape accessible for OS (input attribute: []) -q, --quiet Be quiet --update-lastwrite update LastWrite attribute for given TapeName in Pool (JSON-File) if no datestring is specified, use "now" (input attribute: [ ) --update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File) if no datestring is specified, use "now" (input attribute: [ ) --update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File) (input attribute: ) --use-mtx use mtx loader handling. If not specified, all mtx commands will use default device ($default_changer_device) -v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) --version show program version EOF # -r, --remote 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. exit 0 } ### # Main ### cwd=`pwd` # can't be ported to dash (ERR is not supported) trap trapkill TERM INT check_prerequisites # validate the device name to access ltfs ltfs_get_devname # validate commandline options, set resonable defaults parse_params $@ case $cmd in add-retensiondays) add_retensiondays_to_retensiondate "${mediapool_name}" "${volume_name}" "${retension_days}" if test $? -gt 0; then if ! $quiet; then printf "${RED}Error: ${MAGENTA}Could not update RetensionDate for ${GREEN}'%s'${MAGENTA} in media-pool ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" "${mediapool_name}" fi exit 1 else date_string_to_iso "${volume_retensiondate}" if [ $? -eq 0 ] && ! $quiet; then volume_date=$(date --date="${date_iso}Z") printf "${MAGENTA}New RetensionDate date for ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}'%s'.\n" \ "${volume_name}" "${volume_date}" fi fi ;; get-lastwrite) valid_member=0 get_lastwrite "${mediapool_name}" "${volume_name}" if test $? -gt 0; then return 1 else if ! $quiet; then date_string_to_iso ${volume_lastwrite} if [ $? -eq 0 ]; then volume_date=$(date --date="${date_iso}Z") printf "${MAGENTA}Last write date for Volume ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${MAGENTA} is : ${NO_COLOR}'%s'.\n" \ "${volume_name}" "${mediapool_name}" "${volume_date}" fi fi fi ;; get-mediapolicy) get_mediapolicy "${mediapool_name}" "${volume_name}" if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}MediaPolicy for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR}'%s'.\n" \ "${volume_name}" "${volume_mediapolicy}" fi fi ;; get-mediapool-name) get_mediapool_name "${volume_name}" if test $? -gt 0; then return 1 else if ! $quiet; then printf "${MAGENTA}MediaPool name: ${GREEN}'%s'${NO_COLOR}\n" \ "${mediapool_name}" fi fi ;; get-mediapools) get_mediapool_names if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}MediaPool names: ${GREEN}'%s'${NO_COLOR}\n" \ "${mediapool_names}" fi fi ;; get-poolmember) valid_member=0 get_poolmember "${mediapool_name}" "${volume_name}" if test $? -gt 0; then return 1 else if ! $quiet; 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 $? -gt 0; then exit 1 else if ! $quiet; 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-mediapool-retensiondays) get_mediapool_retensiondays "${mediapool_name}" if test $? -gt 0; then return 1 else if ! $quiet; then printf "${MAGENTA}Default retension days for tapes in mediapool ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${mediapool_name}" "${mediapool_defaultretensiondays}" fi fi ;; get-retensiondate) get_retensiondate "${mediapool_name}" "${volume_name}" if test $? -gt 0; then exit 1 else date_string_to_iso "${volume_retensiondate}" volume_date=$(date --date="${date_iso}Z") if ! $quiet; then printf "${MAGENTA}RetensionDate for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${volume_name}" "${volume_date}" fi fi ;; get-slot) get_slot "${mediapool_name}" "${volume_name}" if test $? -eq 0; then if ! $quiet; then printf "${MAGENTA}Slot location for ${GREEN}'%s'${MAGENTA} is:${NO_COLOR} %s.\n" \ "${volume_name}" "${volume_slot}" fi fi exit $? ;; ltfs-format) ltfs_format "${volume_name}" "${tape_id}" if test $? -gt 0; then exit 1 fi ;; ltfs-getattribute) ltfs_is_mounted if test $? -gt 0; then exit 1 else ltfs_get_attribute "${ltfs_attribute_name}" if test $? -gt 0; then return 1 else if ! $quiet; then printf "${MAGENTA}LTFS attribute ${GREEN}'%s'${MAGENTA} is: ${GREEN}'%s'${NO_COLOR}\n" \ "${ltfs_attribute_name}" "${ltfs_attribute_value}" fi fi fi ;; ltfs-is-mounted) ltfs_is_mounted if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}LTFS Tape is-mounted: ${GREEN}true${NO_COLOR}\n" fi fi ;; ltfs-mount) ltfs_mount if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}LTFS Tape mount: ${GREEN}true${NO_COLOR}\n" fi fi ;; ltfs-reformat) ltfs_reformat "${volume_name}" if test $? -gt 0; then return 1 else if ! $quiet; then printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \ "${volume_name}" fi fi ;; ltfs-umount) ltfs_umount if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n" fi fi ;; media-change) media_change $mediapool_name $volume_name if test $? -gt 0; then return 1 else if ! $quiet; then if [ ${#volume_name} -ge 1 ]; then printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \ "${mediapool_name}" "${volume_name}" else printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR}\n" \ "${mediapool_name}" fi fi fi ;; mount) mount_tape "${mediapool_name}" "${volume_name}" if test $? -gt 0; then exit 1 else if ! $quiet; then if test ${#volume_name} -ge 1; then printf "${MAGENTA}Tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \ "${volume_name}" "${mediapool_name}" else printf "${MAGENTA}Next tape for mediapool ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \ "${mediapool_name}" fi fi fi ;; mtx-exchange) mtx_exchange "${slot_source}" "${slot_target}" exit $? ;; mtx-getlabel) mtx_getlabel $slot_source exit $? ;; mtx-inventory) mtx_inventory exit $? ;; mtx-load) mtx_load "${slot_source}" "${drive}" exit $? ;; mtx-status) mtx_status "${slot_source}" "${slot_target}" exit $? ;; mtx-transfer) mtx_transfer "${slot_source}" "${slot_target}" exit $? ;; mtx-unload) mtx_unload "${slot_source}" "${drive}" exit $? ;; update-lastwrite) update_lastwrite "${mediapool_name}" "${volume_name}" "${date_string}" if test $? -gt 0; then exit 1 else if ! $quiet; then date_string_to_iso "${volume_lastwrite}" if [ $? -eq 0 ]; then volume_date=$(date --date="${date_iso}Z") printf "${MAGENTA}LastWrite date for ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}'%s'.\n" \ "${volume_name}" "${volume_date}" fi fi fi ;; update-mediapool-retensiondays) update_mediapool_retensiondays "${mediapool_name}" "${mediapool_defaultretensiondays}" if test $? -gt 0; then exit 1 else if ! $quiet; then printf "${MAGENTA}New DefaultRetensionDays attribute for ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}'%s'.\n" \ "${mediapool_name}" "${mediapool_defaultretensiondays}" fi fi ;; update-retensiondate) update_retensiondate "${mediapool_name}" "${volume_name}" "${date_string}" if test $? -gt 0; then exit 1 else if ! $quiet; then date_string_to_iso "${volume_retensiondate}" if [ $? -eq 0 ]; then volume_date=$(date --date="${date_iso}Z") printf "${MAGENTA}RetensionDate date for ${GREEN}'%s'${MAGENTA} is: ${NO_COLOR}'%s'.\n" \ "${volume_name}" "${volume_date}" fi fi fi ;; esac