Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not abort in case of invalid user input but retry #2257

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions usr/share/rear/conf/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2805,9 +2805,17 @@ POST_BACKUP_SCRIPT=
# Call this before Relax-and-Recover starts to do anything in the mkbackup/mkbackuponly workflow.
PRE_BACKUP_SCRIPT=

# some external backup software give you the opportunity to enter paths to exclude ...
# we tend to use a timer in seconds we wait before continuing (we do not want to break the automated restores)
WAIT_SECS=30
# Some external backup software request user input
# (e.g. to enter paths to exclude or date and time values for point in time restore).
# We use here the same default timeout as USER_INPUT_TIMEOUT was set above
# because also this timeout here interrupts a possibly ongoing user input
# (in particular when the bash builtin 'read -t timeout' is used)
# see the above explanation where USER_INPUT_TIMEOUT is set.
# WAIT_SECS is set to a default value here only
# if not already set so that the user can set it also like
# export WAIT_SECS=30
# directly before he calls "rear ...":
test "$WAIT_SECS" || WAIT_SECS="$USER_INPUT_TIMEOUT"

# to force adding multipath related executables so a recovered system would be able to boot via SAN disks only
# instead of the internal ones (no success guaranteed although). E.g. in case the destination has no internal disks.
Expand Down
25 changes: 7 additions & 18 deletions usr/share/rear/restore/DP/default/460_press_y_to_continue.sh
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@

# FIXME: The 'Left' function only works when STDOUT is an ANSI terminal
# because according to http://ascii-table.com/ansi-escape-sequences.php
# Esc[<number>D moves the cursor back by the specified <number> of columns
# so that strange output happens when STDOUT is not an ANSI terminal:
c_esc="\033"
Left () {
echo -ne ${c_esc}[${1}D
}
# restore/DP/default/460_press_y_to_continue.sh

unset REPLY
# Use the original STDOUT when 'rear' was launched by the user for the 'echo' output
# and for the 'Left' output in the 'while' loop
# but keep STDERR going to the log file so that 'rear -D' output goes to the log file:
echo -ne "Press \"y\" to continue or wait for timeout [30 secs]: " 1>&7
while true
do
while true ; do
# Use the original STDIN STDOUT and STDERR when 'rear' was launched by the user
# because 'read' outputs non-error stuff also to STDERR (e.g. its prompt):
read -t $WAIT_SECS -r -n 1 0<&6 1>&7 2>&8
read -t $WAIT_SECS -r -n 1 -p "Press 'y' to continue or wait for $WAIT_SECS seconds timeout: " 0<&6 1>&7 2>&8
rc=$?
# In case of timeout 'read -t' results exit code 142 = 128 + 14 (14 is SIGALRM timer signal from alarm(2)):
(( $rc == 142 )) && break
(( $rc == 1 )) && break
case $REPLY in
y|Y) break ;;
*) Left 1 ; continue ;;
(y|Y) break ;;
(*) continue ;;
esac
done 1>&7
done
UserOutput ""

Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
# Ask for point in time to recover with TSM.

# Ask for point in time to recover with Galaxy 10 (BACKUP=GALAXY10).
# One point in time is used for all filespaces.

LogPrint ""
LogPrint "Galaxy10 restores by default the latest backup data. Alternatively you can specify"
LogPrint "a different date and time to enable Point-In-Time Restore. Press ENTER to"
LogPrint "use the most recent available backup"
# Use the original STDIN STDOUT and STDERR when rear was launched by the user
# to get input from the user and to show output to the user (cf. _input-output-functions.sh):
read -t $WAIT_SECS -r -p "Enter date/time (MM/DD/YYYY HH:mm:ss) or press ENTER [$WAIT_SECS secs]: " 0<&6 1>&7 2>&8
# validate input
if test -z "${REPLY}"; then
LogPrint "Skipping Point-In-Time Restore, will restore most recent data."
GALAXY10_PIT=""
GALAXY10_ZEIT=""
else
# validate date
GALAXY10_ZEIT=$REPLY
GALAXY10_PIT="QR_RECOVER_POINT_IN_TIME"
fi
UserOutput ""
UserOutput "Galaxy 10 restores by default the latest backup data."
UserOutput "Press only ENTER to restore the most recent available backup."
UserOutput "Alternatively specify date and time for Point-In-Time restore."

local answer=""
local valid_date_and_time_input=""

# Let the user enter date and time again and again until the input is valid
# or the user pressed only ENTER to restore the most recent available backup:
while true ; do
answer=$( UserInput -I GALAXY10_RESTORE_PIT -r -p "Enter date/time (MM/DD/YYYY HH:mm:ss) or press ENTER" )
# When the user pressed only ENTER leave this script to restore the most recent available backup:
if test -z "$answer"; then
UserOutput "Skipping Galaxy 10 Point-In-Time restore, will restore most recent backup."
GALAXY10_PIT=""
GALAXY10_ZEIT=""
return
fi
# Try to do Galaxy 10 Point-In-Time restore provided the user input is valid date and time:
valid_date_and_time_input="yes"
# Validate date:
tsm_restore_pit_date=$( date -d "$answer" +%Y.%m.%d ) || valid_date_and_time_input="no"
# Validate time:
tsm_restore_pit_time=$( date -d "$answer" +%T ) || valid_date_and_time_input="no"
# Exit the while loop when the user input is valid date and time:
is_true $valid_date_and_time_input && break
# Show the user that his input is invalid and do the the while loop again:
LogPrintError "Invalid date and/or time '$answer' specified."
done

# Do Galaxy 10 Point-In-Time restore:
GALAXY10_ZEIT="$answer"
GALAXY10_PIT="QR_RECOVER_POINT_IN_TIME"

UserOutput "Doing Galaxy 10 Point-In-Time restore with date and time $GALAXY10_ZEIT"

Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ NBU_CLIENT_SOURCE="${NBU_CLIENT_NAME}"

LogPrint ""
LogPrint "Netbackup Client Source For This Restore is: $NBU_CLIENT_SOURCE"
LogPrint "> If this is a normal restore to the same client press ENTER."
LogPrint "> If this is a restore to a CLONE enter the new client name."
LogPrint "If this is a normal restore to the same client press ENTER."
LogPrint "If this is a restore to a CLONE enter the new client name."
# Use the original STDIN STDOUT and STDERR when rear was launched by the user
# to get input from the user and to show output to the user (cf. _input-output-functions.sh):
read -t $WAIT_SECS -r -p "Enter Cloned Client name or press ENTER [$WAIT_SECS secs]: " 0<&6 1>&7 2>&8

# validate input
# FIXME: The input is not actually validated here.
# There is only LogPrint that show the input
# but no code that actually validates the input
# so the user cannot retry in case of invalid input
# cf. https://github.com/rear/rear/pull/2257
if test -z "${REPLY}"; then
LogPrint ""
LogPrint "Client is the same as Client Source. Normal restore...."
Expand All @@ -31,5 +36,10 @@ else
LogPrint ""
# Use the original STDIN STDOUT and STDERR when rear was launched by the user
# to get input from the user and to show output to the user (cf. _input-output-functions.sh):
# FIXME: Is it right to let 'read' timeout here which makes 'rear recover' automatically proceed after WAIT_SECS?
# I <jsmeix@suse.de> think at this point during 'rear recover' the user may not yet have been able to
# "Ensure all servers defined in bp.conf can connect to this RESCUE system using the hostname: ${NBU_CLIENT_NAME}"
# so a 'rear_shell' call could help here so that he could adapt his /usr/openv/netbackup/bp.conf as needed.
read -t $WAIT_SECS -r -p "Press any key to continue ... [$WAIT_SECS secs] " 0<&6 1>&7 2>&8
fi

Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,41 @@

NBU_ENDTIME=()

LogPrint ""
LogPrint "NetBackup restores by default the latest backup data."
LogPrint "Press ENTER to restore the most recent available backup."
LogPrint "Alternatively specify date (and time) for Point-In-Time Restore."
UserOutput ""
UserOutput "NetBackup restores by default the latest backup data."
UserOutput "Press only ENTER to restore the most recent available backup."
UserOutput "Alternatively specify date (and time) for Point-In-Time Restore."

local answer=""
answer=$( UserInput -I NBU_RESTORE_PIT -t $WAIT_SECS -r -p "Enter date (mm/dd/yyyy) or date and time (mm/dd/yyyy HH:MM:SS) or press ENTER" )

if test -z "$answer"; then
LogPrint "Skipping NetBackup Point-In-Time Restore, will restore most recent backup."
return
fi

# Validate user date and time input:
local valid_date_and_time_input="yes"
local valid_date_and_time_input=""
local nbu_endtime_date=""
local nbu_endtime_time=""
# Validate date:
nbu_endtime_date=$( date -d "$answer" +%m/%d/%Y ) || valid_date_and_time_input="no"
# Validate time:
nbu_endtime_time=$( date -d "$answer" +%T ) || valid_date_and_time_input="no"
# It is an Error (not a BugError) when user input is invalid:
is_true $valid_date_and_time_input || Error "Invalid date and/or time '$answer' specified. Ending NetBackup Restore attempt..."

# Let the user enter date and time again and again until the input is valid
# or the user pressed only ENTER to restore the most recent available backup:
while true ; do
answer=$( UserInput -I NBU_RESTORE_PIT -r -p "Enter date (mm/dd/yyyy) or date and time (mm/dd/yyyy HH:MM:SS) or press ENTER" )
# When the user pressed only ENTER leave this script to restore the most recent available backup:
if test -z "$answer" ; then
UserOutput "Skipping NetBackup Point-In-Time Restore, will restore most recent backup."
return
fi
# Try to do NetBackup Point-In-Time Restore provided the user input is valid date and time:
valid_date_and_time_input="yes"
# Validate date:
nbu_endtime_date=$( date -d "$answer" +%m/%d/%Y ) || valid_date_and_time_input="no"
# Validate time:
nbu_endtime_time=$( date -d "$answer" +%T ) || valid_date_and_time_input="no"
# Exit the while loop when the user input is valid date and time:
is_true $valid_date_and_time_input && break
# Show the user that his input is invalid and do the the while loop again:
LogPrintError "Invalid date and/or time '$answer' specified."
done

# Do NetBackup Point-In-Time Restore:
NBU_ENDTIME=( "$nbu_endtime_date" )
# When also an actual time was specified (i.e. when it is not "00:00:00") add it:
test "$nbu_endtime_time" != "00:00:00" && NBU_ENDTIME+=( "$nbu_endtime_time" )

LogPrint "Doing NetBackup Point-In-Time Restore of all filespaces at or before ${NBU_ENDTIME[@]}"
UserOutput "Doing NetBackup Point-In-Time Restore of all filespaces at or before ${NBU_ENDTIME[@]}"

Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,45 @@
# Ask for point in time to recover with TSM.
# One point in time is used for all filespaces.

LogPrint ""
LogPrint "TSM restores by default the latest backup data."
LogPrint "Press ENTER to restore the most recent available backup."
LogPrint "Alternatively specify date and time for Point-In-Time restore."
UserOutput ""
UserOutput "TSM restores by default the latest backup data."
UserOutput "Press only ENTER to restore the most recent available backup."
UserOutput "Alternatively specify date and time for Point-In-Time restore."

local answer=""

answer=$( UserInput -I TSM_RESTORE_PIT -t $WAIT_SECS -r -p "Enter date/time (YYYY-MM-DD HH:mm:ss) or press ENTER" )

if test -z "$answer"; then
LogPrint "Skipping TSM Point-In-Time restore, will restore most recent backup."
return
fi

local valid_date_and_time_input=""
local tsm_restore_pit_date=""
local tsm_restore_pit_time=""

# Validate date:
tsm_restore_pit_date=$( date -d "$answer" +%Y.%m.%d ) || Error "Invalid date specified for TSM recovery: '$answer'"
# Let the user enter date and time again and again until the input is valid
# or the user pressed only ENTER to restore the most recent available backup:
while true ; do
answer=$( UserInput -I TSM_RESTORE_PIT -r -p "Enter date/time (YYYY-MM-DD HH:mm:ss) or press ENTER" )
# When the user pressed only ENTER leave this script to restore the most recent available backup:
if test -z "$answer"; then
UserOutput "Skipping TSM Point-In-Time restore, will restore most recent backup."
return
fi
# Try to do TSM Point-In-Time restore provided the user input is valid date and time:
valid_date_and_time_input="yes"
# Validate date:
tsm_restore_pit_date=$( date -d "$answer" +%Y.%m.%d ) || valid_date_and_time_input="no"
# Validate time:
tsm_restore_pit_time=$( date -d "$answer" +%T ) || valid_date_and_time_input="no"
# Exit the while loop when the user input is valid date and time:
is_true $valid_date_and_time_input && break
# Show the user that his input is invalid and do the the while loop again:
LogPrintError "Invalid date and/or time '$answer' specified."
done

# Do TSM Point-In-Time restore:
# Add valid date to dsmc options:
TSM_DSMC_RESTORE_OPTIONS+=( -date=5 -pitd="$tsm_restore_pit_date" )

# Validate time:
tsm_restore_pit_time=$( date -d "$answer" +%T ) || Error "Invalid time specified for TSM recovery: '$answer'"
# Add valid actual time (i.e. when it is not "00:00:00") to dsmc options:
# FIXME: Is it right to add '-date=5' here a second time to the TSM_DSMC_RESTORE_OPTIONS array
# because it was already added above in the "Add valid date to dsmc options" step?
test "$tsm_restore_pit_time" != "00:00:00" && TSM_DSMC_RESTORE_OPTIONS+=( -date=5 -pitt="$tsm_restore_pit_time" )

LogPrint "Restoring all TSM filespaces from backup before $tsm_restore_pit_date $tsm_restore_pit_time (MM/DD/YYYY HH:mm:ss)"
LogPrint "Note: The following list of file spaces always shows the latest backup and not the date/time you specified here."
UserOutput "Restoring all TSM filespaces from backup before $tsm_restore_pit_date $tsm_restore_pit_time (YYYY.MM.DD HH:mm:ss)"
UserOutput "Note: The following list of file spaces always shows the latest backup and not the date/time you specified here."

16 changes: 12 additions & 4 deletions usr/share/rear/verify/default/040_validate_variables.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# verify/default/040_validate_variables.sh

# Test if variable WAIT_SECS is a positive integer,
# if not, give it the default value from default.conf.
# Ensure USER_INPUT_TIMEOUT and WAIT_SECS are positive integers
# to ensure commands like 'read -t $WAIT_SECS' will not fail
# or not wait at all (which happens for 'read -t 0').

# is_positive_integer outputs '0' and returns 1
# if its (first) argument is not a positive integer (or empty):
is_positive_integer $WAIT_SECS 1>/dev/null || WAIT_SECS=30
# if its (first) argument is not a positive integer (or empty).

# Test if USER_INPUT_TIMEOUT is a positive integer,
# if not, set the default value as in default.conf:
is_positive_integer $USER_INPUT_TIMEOUT 1>/dev/null || USER_INPUT_TIMEOUT=300

# Test if WAIT_SECS is a positive integer,
# if not, set the default value as in default.conf:
is_positive_integer $WAIT_SECS 1>/dev/null || WAIT_SECS="$USER_INPUT_TIMEOUT"