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

Use UserInput in some more usual places #1573

Merged
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
231 changes: 136 additions & 95 deletions usr/share/rear/layout/prepare/default/200_recreate_hpraid.sh
Original file line number Diff line number Diff line change
@@ -1,119 +1,160 @@
# Ask to recreate HP raid before the actual restoration takes place.

if ! grep -q '^cciss ' /proc/modules; then
return
fi

ORIG_LAYOUT_CODE="$LAYOUT_CODE"

#
# Ask to recreate HP's Smart Array line of hardware RAID controllers
# and actually recreate that before the actual restoration takes place.
#
# This script is only about HP Smart Array hardware RAID controllers
# that are supported by the 'cciss' kernel module.
# Newer HP Smart Array hardware RAID controllers that need
# the 'hpsa' kernel module are not supported by this script.
# Cf.
# http://cciss.sourceforge.net/
# which reads (excerpt):
# The cciss driver has been removed from RHEL7 and SLES12.
# If you really want cciss on RHEL7 checkout the elrepo directory.
# A new Smart Array driver called "hpsa" has been accepted into
# the main line linux kernel as of Dec 18, 2009, in linux-2.6.33-rc1.
# This new driver will support new Smart Array products going
# forward, and the cciss driver will eventually be deprecated.
#

# Skip that unless the cciss kernel module
# (for HP Smart Array hardware RAID controllers)
# is loaded:
grep -q '^cciss ' /proc/modules || return 0

# The code below calls layout-functions like create_device()
# that append code to a file referenced by the global LAYOUT_CODE variable
# so that we must also use that global variable name in this script
# but with a special value only for this script here:
orig_LAYOUT_CODE="$LAYOUT_CODE"
LAYOUT_CODE=$VAR_DIR/layout/hpraid.sh

# Initialize our special LAYOUT_CODE:
cat <<EOF >$LAYOUT_CODE
# Recreate HP Smart Array hardware RAID
LogPrint "Recreating HP Smart Array hardware RAID"
set -e

# Unload CCISS module to make sure nothing is using it
rmmod cciss || Error "CCISS failed to unload, something is still using it !"

# Unload CCISS kernel module to make sure nothing is using it:
rmmod cciss || Error "Failed to unload 'cciss' kernel module, something is using it"
modprobe cciss
sleep 2
EOF

restored_controllers=()

# Start by clearing all controllers
while read -u 3 type name junk ; do
# 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 -p "To recreate HP SmartArray controller $name, type exactly 'YES': " 0<&6 1>&7 2>&8
if [ "$REPLY" = "YES" ] ; then
create_device "$name" "smartarray"
restored_controllers=( "${restored_controllers[@]}" $name )
# First recreate HP Smart Array controllers or skip some via user dialog:
controllers_to_be_recreated=()
echo "# First recreate HP Smart Array controllers" >>$LAYOUT_CODE
while read type name junk ; do
prompt="Recreate HP Smart Array controller '$name' (yes/no)?"
input_value=""
wilful_input=""
# Generate a runtime-specific user_input_ID so that for each HP Smart Array controller
# a different user_input_ID is used for the UserInput call so that the user can specify
# for each HP Smart Array controller a different predefined user input.
# Only uppercase letters and digits are used to ensure the user_input_ID is a valid bash variable name
# (otherwise the UserInput call could become invalid which aborts 'rear recover' with a BugError) and
# hopefully only uppercase letters and digits are sufficient to distinguish different controllers:
controller_basename_alnum_uppercase="$( basename "$name" | tr -d -c '[:alnum:]' | tr '[:lower:]' '[:upper:]' )"
test "$controller_basename_alnum_uppercase" || controller_basename_alnum_uppercase="CONTROLLER"
user_input_ID="HP_SMART_ARRAY_$controller_basename_alnum_uppercase"
input_value="$( UserInput -I $user_input_ID -p "$prompt" -D 'YES' )" && wilful_input="yes" || wilful_input="no"
if is_true "$input_value" ; then
is_true "$wilful_input" && LogPrint "User confirmed recreating HP Smart Array controller '$name'" || LogPrint "Recreating HP Smart Array controller '$name' by default"
echo "# Recreate HP Smart Array controller '$name'" >>$LAYOUT_CODE
create_device "$name" 'smartarray'
controllers_to_be_recreated=( "${controllers_to_be_recreated[@]}" $name )
fi
done 3< <(grep "^smartarray " "$LAYOUT_FILE")
done < <( grep '^smartarray ' $LAYOUT_FILE )

# Now, recreate all logical drives whose controller was cleared.
# Then recreate all logical drives for those controllers that will be recreated:
echo "# Then recreate all logical drives for those controllers that were recreated" >>$LAYOUT_CODE
while read type name remainder junk ; do
ctrl=$(echo "$remainder" | cut -d " " -f1 | cut -d "|" -f1)
if IsInArray "$ctrl" "${restored_controllers[@]}" ; then
create_device "$name" "logicaldrive"
ctrl=$( echo "$remainder" | cut -d " " -f1 | cut -d "|" -f1 )
if IsInArray "$ctrl" "${controllers_to_be_recreated[@]}" ; then
echo "# Recreate logical drive '$name'" >>$LAYOUT_CODE
create_device "$name" 'logicaldrive'
fi
done < <(grep "^logicaldrive " "$LAYOUT_FILE")
done < <( grep '^logicaldrive ' $LAYOUT_FILE )

### engage scsi can fail in certain cases
cat <<'EOF' >>"$LAYOUT_CODE"
# Finally engage SCSI for the hosts in /proc/driver/cciss/cciss?
cat <<'EOF' >>$LAYOUT_CODE
# Finally engage SCSI for the hosts in /proc/driver/cciss/cciss?
# engage scsi can fail in certain cases
set +e

# make the CCISS tape device visible
for host in /proc/driver/cciss/cciss?; do
for host in /proc/driver/cciss/cciss? ; do
Log "Engage SCSI on host $host"
echo engage scsi >$host
done

sleep 2
EOF

if [ ${#restored_controllers} -ne 0 ] ; then
define_HPSSACLI # call function to find proper Smart Storage Administrator CLI command - define $HPSSACLI var
RESTORE_OK=
while [[ -z "$RESTORE_OK" ]]; do
(
. "$LAYOUT_CODE"
)

if (( $? == 0 )); then
RESTORE_OK=y
else
LogPrint "Could not configure an HP SmartArray controllers."
Print ""

# TODO: Provide a skip option (needs torough consideration)
choices=(
"View Relax-and-Recover log"
"Go to Relax-and-Recover shell"
# "Edit disk layout (disklayout.conf)"
"Edit restore script (hpraid.sh)"
"Restart restore script"
"Abort Relax-and-Recover"
)

timestamp=$(stat --format="%Y" "$LAYOUT_CODE")
# 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):
select choice in "${choices[@]}"; do
timestamp=$(stat --format="%Y" "$LAYOUT_FILE")
case "$REPLY" in
(1) less "$RUNTIME_LOGFILE";;
(2) rear_shell "" "$HPSSACLI ctrl all show detail
$HPSSACLI ctrl all show config detail
$HPSSACLI ctrl all show config
";;
# (3) vi $LAYOUT_FILE;;
(3) vi "$LAYOUT_CODE";;
(4) if (( $timestamp < $(stat --format="%Y" "$LAYOUT_CODE") )); then
break
else
Print "Script $LAYOUT_CODE has not been changed, restarting has no impact."
fi
;;
(5) break;;
esac

# Reprint menu options when returning from less, shell or vi
Print ""
for (( i=1; i <= ${#choices[@]}; i++ )); do
Print "$i) ${choices[$i-1]}"
done
done 0<&6 1>&7 2>&8

Log "User selected: $REPLY) ${choices[$REPLY-1]}"

if (( REPLY == ${#choices[@]} )); then
abort_recreate

Error "There was an error restoring the HP SmartArray drives. See $RUNTIME_LOGFILE for details."
fi
fi
# Run the HP Smart Array recreation script only if at least one HP Smart Array controller will be recreated:
if test ${#controllers_to_be_recreated} -gt 0 ; then
# Call function to find proper Smart Storage Administrator CLI command
# (it defines the HPSSACLI variable):
define_HPSSACLI
# Run our special LAYOUT_CODE
# i.e. actually recreate the HP Smart Array stuff here
# cf. the code in layout/recreate/default/200_run_layout_code.sh
rear_workflow="rear $WORKFLOW"
rear_shell_history="$( echo -e "$HPSSACLI ctrl all show detail\n$HPSSACLI ctrl all show config detail\n$HPSSACLI ctrl all show config" )"
unset choices
choices[0]="Rerun HP Smart Array recreation script ($LAYOUT_CODE)"
choices[1]="View '$rear_workflow' log file ($RUNTIME_LOGFILE)"
choices[2]="Edit HP Smart Array recreation script ($LAYOUT_CODE)"
choices[3]="Use Relax-and-Recover shell and return back to here"
choices[4]="Abort '$rear_workflow'"
prompt="The HP Smart Array recreation script failed"
choice=""
wilful_input=""
# When USER_INPUT_HP_SMART_ARRAY_CODE_RUN has any 'true' value be liberal in what you accept and
# assume choices[0] 'Run disk recreation script again' was actually meant:
is_true "$USER_INPUT_HP_SMART_ARRAY_CODE_RUN" && USER_INPUT_HP_SMART_ARRAY_CODE_RUN="${choices[0]}"
# Run the disk layout recreation code (diskrestore.sh)
# again and again until it succeeds or the user aborts:
while true ; do
# Run LAYOUT_CODE in a sub-shell because it sets 'set -e'
# so that it exits the running shell in case of an error
# but that exit must not exit this running bash here:
( source $LAYOUT_CODE )
# Since bash 4.x one must explicitly test whether or not $? is zero in a separated bash command
# otherwise the 'set -e' inside the sourced script would be noneffective
# cf. layout/recreate/default/200_run_layout_code.sh
# and https://github.com/rear/rear/pull/1573#issuecomment-344303590
# Break the outer while loop when LAYOUT_CODE succeeded:
(( $? == 0 )) && break
# Run an inner while loop with a user dialog so that the user can fix things when LAYOUT_CODE failed:
while true ; do
choice="$( UserInput -I LAYOUT_CODE_RUN -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no"
case "$choice" in
(${choices[0]})
# Rerun disk recreation script:
is_true "$wilful_input" && LogPrint "User reruns HP Smart Array recreation script" || LogPrint "Rerunning HP Smart Array recreation script by default"
# Only break the inner while loop (i.e. the user dialog loop):
break
;;
(${choices[1]})
# Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
less $RUNTIME_LOGFILE 0<&6 1>&7 2>&8
;;
(${choices[2]})
# Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
vi $LAYOUT_CODE 0<&6 1>&7 2>&8
;;
(${choices[3]})
# rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
rear_shell "" "$rear_shell_history"
;;
(${choices[4]})
abort_recreate
Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}"
;;
esac
done
done
fi

LAYOUT_CODE="$ORIG_LAYOUT_CODE"
# It is crucial for the subsequent scripts
# that the normal LAYOUT_CODE value is restored:
LAYOUT_CODE="$orig_LAYOUT_CODE"

46 changes: 0 additions & 46 deletions usr/share/rear/layout/prepare/default/500_confirm_layout.sh

This file was deleted.

55 changes: 55 additions & 0 deletions usr/share/rear/layout/prepare/default/500_confirm_layout_file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# In migration mode let the user confirm the
# disk layout file (disklayout.conf) content.
#

# Skip that unless in migration mode:
test "$MIGRATION_MODE" || return 0

rear_workflow="rear $WORKFLOW"
original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt"
rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $LAYOUT_FILE\nless $LAYOUT_FILE" )"
unset choices
choices[0]="Confirm disk layout and continue '$rear_workflow'"
choices[1]="Edit disk layout ($LAYOUT_FILE)"
choices[2]="View disk layout ($LAYOUT_FILE)"
choices[3]="View original disk space usage ($original_disk_space_usage_file)"
choices[4]="Use Relax-and-Recover shell and return back to here"
choices[5]="Abort '$rear_workflow'"
prompt="Confirm or edit the disk layout file"
choice=""
wilful_input=""
# When USER_INPUT_LAYOUT_FILE_CONFIRMATION has any 'true' value be liberal in what you accept and
# assume choices[0] 'Confirm disk layout' was actually meant:
is_true "$USER_INPUT_LAYOUT_FILE_CONFIRMATION" && USER_INPUT_LAYOUT_FILE_CONFIRMATION="${choices[0]}"
while true ; do
choice="$( UserInput -I LAYOUT_FILE_CONFIRMATION -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no"
case "$choice" in
(${choices[0]})
# Confirm disk layout file and continue:
is_true "$wilful_input" && LogPrint "User confirmed disk layout file" || LogPrint "Continuing '$rear_workflow' by default"
break
;;
(${choices[1]})
# Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
vi $LAYOUT_FILE 0<&6 1>&7 2>&8
;;
(${choices[2]})
# Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
less $LAYOUT_FILE 0<&6 1>&7 2>&8
;;
(${choices[3]})
# Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
less $original_disk_space_usage_file 0<&6 1>&7 2>&8
;;
(${choices[4]})
# rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
rear_shell "" "$rear_shell_history"
;;
(${choices[5]})
abort_recreate
Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}"
;;
esac
done

Loading