Files
dsnap-sync/bin/tape-admin
2025-08-04 10:26:13 +02:00

2546 lines
73 KiB
Bash
Executable File

#! /bin/sh
# tape-admin
# https://github.com/rzerres/dsnap-sync
# Copyright (C) 2017 - 2019 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
ltfs_umount
if [ $? -eq 0 ]; then
${MKLTFS} --device=$ltfs_devname --volume-name=${volume_name} --tape-serial=${volume_serial} --force 2>${ERRFILE}
RET=$?
rm -f ${ERRFILE}
return $RET
fi
}
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}Unmount ${GREEN}'%s'${NO_COLOR} to reformat LTFS tape.\n" \
"$ltfs_mountpoint"
fi
ltfs_umount
fi
# Take care that we have the correct media in drive slot
slot_source="0"
mtx_getlabel $slot_source
if [ ${#volume_name_active} -gt 0 ]; then
if [ $volume_name_active != $volume_name ]; then
if [ $verbose -ge 1 ]; then
printf "${MAGENTA}Loader needs to exchange loaded tape ${GREEN}'%s'${MAGENTA} with tape ${GREEN}'%s'${NO_COLOR}\n" \
"$volume_name_active" "$volume_name"
fi
if [ $? -eq 0 ]; then
mtx_unload
if [ $? -eq 0 ]; then
if [ $verbose -ge 2 ]; then
printf "${MAGENTA}MTX finished unload tape ${GREEN}'%s'${NO_COLOR}\n" \
"$volume_name_active"
fi
volume_name_active=""
fi
fi
fi
fi
if [ ${#volume_name_active} -eq 0 ]; then
# no tape in drive slot, load selected volume_name
get_mediapool_name "${volume_name}"
if [ ${#mediapool_name} -gt 0 ]; then
get_slot "${mediapool_name}" "${volume_name}"
if [ $? -eq 0 ]; then
mtx_load ${volume_slot}
if [ $? -eq 0 ]; then
if [ $verbose -ge 2 ]; then
printf "${MAGENTA}MTX finished loading tape ${GREEN}'%s'${NO_COLOR}\n" \
"$volume_name"
fi
fi
fi
fi
fi
# check LTFS
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 [ $? -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
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
if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Wipe tape ${GREEN}'%s'${MAGENTA} (Volume-Name: ${GREEN}'%s'${NO_COLOR})\n" \
"$volume_name_active" "$volume_serial"
fi
# wiping: put tape in an unformatted state
ltfs_wipe
if [ $? -eq 0 ]; then
# format: create the ltfs partitions
ltfs_format $volume_name_active $volume_serial
if [ $? -eq 0 ]; then
ltfs_mount
fi
fi
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
ltfs_umount
if [ $? -eq 0 ]; then
#rm -rf $ltfs_mountpoint/*
make_err_file
if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Wiping LTFS medium, that creates an ${GREEN}'unpartitioned media'${MAGENTA} ...${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 */
sleep 2
CMD="${MKLTFS} --device=$ltfs_devname --wipe --force"
if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Calling: ${GREEN}%s${NO_COLOR}\n" \
${CMD}
fi
${CMD} 2>${ERRFILE}
RET=$?
rm -f ${ERRFILE}
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; Return-Code: ${GREEN}%s${NO_COLOR}\n" \
${MKLTFS} $RET
return $RET
;;
*)
return $RET
;;
esac
fi
}
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 1 ]; 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
# if no explicit tape should be mounted, 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
# check the mediapolicy for given volume_name
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
#ltfs_format ${volume_name_active}
ltfs_reformat ${volume_name_active}
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_reformat ${volume_name_active}
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${NO_COLOR}\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_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
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 ] && [ ${#volume_name_active} -gt 0 ]; 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 <<EOF
$progname $version
Usage: $progname [options]
Options:
--add-retensiondays add RetensionDays to LastWrite attribute for given TapeName in Pool (JSON-File)
(input attribute: <mediapool> <volume_name> <days>)
--color Enable colored output messages
--get-lastwrite extract LastWrite attribute from given Pool member (JSON-File)
(input attribute: <mediapool> [<volume_name>])
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: <volume_name>)
--get-mediapools extract MediaPool names from configuration (JSON-File)
--get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>])
--get-poolmember extract VolumeName attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>])
--get-poolmember-next extract VolumeName for next usable Pool member (JSON-File)
(input attribute: <mediapool> [volume_name])
--get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>])
--get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File)
(input attribute: <mediapool>)
--get-slot extract Slot attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>])
--ltfs-getattribute report ltfs extended attribute for mounted tape
(input attribute: <ltfs_attribute>)
--ltfs-format format tape
(input attribute: <volume_name> <tape_id>)
--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: [<volume_name>])
--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: <mediapool> [<volume_name>])
--mtx-exchange exchange tapes in slots
(input attribute: <slot_source> <slot_target>)
--mtx-getlabel report tape label/barcode for tape in drive
(input attribute: <slot_source>)
--mtx-inventory run inquriy task for tape-changer
--mtx-load load a tape to target slot
(input attribute: <slot_source>)
--mtx-status list changer slot status
--mtx-transfer transfer a tape to target slot
(input attribute: <slot_source> <slot_target>)
--mtx-unload unload a tape
(input attribute: slot_source drive)
--mount make tape accessible for OS
(input attribute: <mediapool_name> [<volume_name>])
-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: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
--update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File)
if no datestring is specified, use "now"
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
--update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File)
(input attribute: <mediapool>)
--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 <host> 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 <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)
if ! $quiet; then
printf "${MAGENTA}LTFS tape mount checke\n"
fi
ltfs_is_mounted
if test $? -gt 0; then
exit 1
fi
;;
ltfs-mount)
if ! $quiet; then
printf "${MAGENTA}LTFS mount Tape\n"
fi
ltfs_mount
if test $? -gt 0; then
exit 1
fi
;;
ltfs-reformat)
if ! $quiet; then
printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}"
fi
ltfs_reformat "${volume_name}"
if test $? -gt 0; then
return 1
fi
;;
ltfs-umount)
if ! $quiet; then
printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n"
fi
ltfs_umount
if test $? -gt 0; then
exit 1
fi
;;
media-change)
if ! $quiet; then
if [ ${#volume_name} -ge 1 ]; then
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \
"${mediapool_name}" "${volume_name}"
else
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR}\n" \
"${mediapool_name}"
fi
fi
media_change $mediapool_name $volume_name
if test $? -gt 0; then
return 1
fi
;;
mount)
if ! $quiet; then
if test ${#volume_name} -ge 1; then
printf "${MAGENTA}Mount tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${NO_COLOR}\n" \
"${volume_name}" "${mediapool_name}"
else
printf "${MAGENTA}Mount next tape for mediapool ${GREEN}'%s'${NO_COLOR}\n" \
"${mediapool_name}"
fi
fi
mount_tape "${mediapool_name}" "${volume_name}"
if test $? -gt 0; then
exit 1
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