scripts/dell/start-virtual-console.bash

424 lines
13 KiB
Bash
Raw Normal View History

#!/bin/bash
#
# Purpose {{{
# This script will try to start an iDrac 6/7 virtual console
# 1. Ask for an host if not given with the option.
# 2. Ask for a user if not given with the option.
# 3. Ask for the password.
#
# Inspired from : https://gist.github.com/xbb/4fd651c2493ad9284dbcb827dc8886d6
#
# 2023-02-15
# }}}
# Flags {{{
## Exit on error {{{
set -o errexit
## }}}
## Exit on unset var {{{
### Use "${VARNAME-}" to test a var that may not have been set
set -o nounset
## }}}
## Pipeline command is treated as failed {{{
### Not available in POSIX sh https://github.com/koalaman/shellcheck/wiki/SC3040
#set -o pipefail
## }}}
## Help with debugging {{{
### Call the script by prefixing it with "TRACE=1 ./script.sh"
if [ "${TRACE-0}" -eq 1 ]; then set -o xtrace; fi
## }}}
# }}}
# Vars {{{
PROGNAME=$(basename "${0}"); readonly PROGNAME
PROGDIR=$(readlink --canonicalize-missing $(dirname "${0}")); readonly PROGDIR
ARGS="${*}"; readonly ARGS
readonly NBARGS="${#}"
[ -z "${DEBUG-}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG
## Default values for some vars
readonly IDRAC_USERNAME_DEFAULT="root"
readonly IDRAC_PORT_DEFAULT="443"
readonly JAVA_DISABLE_ALGO_DEFAULT="SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, anon, NULL, include jdk.disabled.namedCurves"
readonly JAVA_SECURITY_FILENAME="idrac.java.security"
readonly TEMP_DIR_BASE="/tmp"
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat <<- HELP
usage: $PROGNAME [-d|-h] [--user idrac_username] [--host idrac.hostname] [--port port.number] [--temp /path/to/temp/directory]
Try to start an iDrac 6/7 virtual console with given informations.
The password will always be asked and not displayed.
EXAMPLES:
- Start the script and wait for prompt to enter informations
${PROGNAME}
- Start virtual console of a given host
${PROGNAME} --host "oob-myserver.domain.tld"
- Start virtual console with SSH Port forwarding
${PROGNAME} --host "localhost:7200"
- Use specific username
${PROGNAME} --user "admin"
- Store downloaded files and informations in a specific temp directory
${PROGNAME} --temp /tmp/my.idrac.temp.dir
OPTIONS:
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
--host
Define the iDrac host to connect.
Fallback: It will be asked to the user.
-p,--port
Define the iDrac port to use.
The script will try to parse the given value of hostname and extract a port number
Fallback: It will be asked to the user.
Default : ${IDRAC_PORT_DEFAULT}
-u,--user
Define the iDrac username.
Fallback: It will be asked to the user.
Default : ${IDRAC_USERNAME_DEFAULT}
--temp,--temp-dir,--temp-directory
Define the temp directoy to store downloaded files and informations.
Default : ${TEMP_DIR_BASE}/idrac.given_hostname
--java-disable-algo
Override global java security settings.
To allow old console to work on new java environment.
Default : ${JAVA_DISABLE_ALGO_DEFAULT}
For more informations, see : https://gist.github.com/xbb/4fd651c2493ad9284dbcb827dc8886d6?permalink_comment_id=4006481#gistcomment-4006481
HELP
}
# }}}
debug_message() { # {{{
local_debug_message="${1}"
## Print message if DEBUG is enable (=0)
[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG ${PROGNAME}: ${local_debug_message}"
unset local_debug_message
return 0
}
# }}}
error_message() { # {{{
local_error_message="${1}"
local_error_code="${2}"
## Print message
printf '%b\n' "ERROR ${PROGNAME}: ${RED}${local_error_message}${RESET}" >&2
unset local_error_message
exit "${local_error_code:=66}"
}
# }}}
define_vars() { # {{{
## If idrac_host_temp wasn't defined (argument) {{{
if [ -z "${idrac_host_temp-}" ]; then
### Ask the user to enter a username
printf -- '%b' 'Enter iDrac host (eg. "oob-myserver.domain.tld", "localhost:7200"…): '
read -r idrac_host_temp
fi
## }}}
## If idrac_host_temp is still empty {{{
if [ -z "${idrac_host_temp-}" ]; then
error_message "iDrac host can't be empty, please check your input or use --host option. For more informations, see the help message (--help)." 11
fi
## }}}
## If idrac_host_temp is still empty {{{
if [ -z "${idrac_host_temp-}" ]; then
error_message "iDrac host can't be empty, please check your input or use --host option. For more informations, see the help message (--help)." 11
fi
## }}}
## If idrac_host_temp contains a port number {{{
if printf '%b' "${idrac_host_temp}" | awk 'BEGIN { FS = ":" } ; /^[a-zA-Z]+.*:[0-9]+$/' >/dev/null; then
### Extract hostname and port number
idrac_host=$(printf '%b' "${idrac_host_temp}" | awk 'BEGIN { FS = ":" } ; /^[a-zA-Z]+.*:[0-9]+$/ { print $1 }')
idrac_port=$(printf '%b' "${idrac_host_temp}" | awk 'BEGIN { FS = ":" } ; /^[a-zA-Z]+.*:[0-9]+$/ { print $2 }')
else
### Simply use idrac_host_temp as hostname
idrac_host="${idrac_host_temp}"
fi
## }}}
## If idrac_username wasn't defined (argument) {{{
if [ -z "${idrac_username-}" ]; then
### Ask the user to enter a username
printf -- '%b' "Enter iDrac username (default ${RED}${IDRAC_USERNAME_DEFAULT}${RESET}): "
read -r idrac_username
fi
## }}}
## If idrac_username is still empty {{{
if [ -z "${idrac_username-}" ]; then
### Use default value
readonly idrac_username="${IDRAC_USERNAME_DEFAULT}"
fi
## }}}
## If idrac_port wasn't defined (argument or by idrac_host_temp) {{{
if [ -z "${idrac_port-}" ]; then
### Ask the user to enter a port number
printf -- '%b' "Enter iDrac port (default ${RED}${IDRAC_PORT_DEFAULT}${RESET}): "
read -r idrac_port
fi
## }}}
## If idrac_port is still empty {{{
if [ -z "${idrac_port-}" ]; then
idrac_port="${IDRAC_PORT_DEFAULT}"
fi
## }}}
## Ask for idrac_password {{{
printf -- '%b' "Enter iDrac password (it won't be displayed): "
read -r -s idrac_password
printf -- '%b\n' ""
## }}}
## If idrac_password is empty, ask again {{{
if [ -z "${idrac_password-}" ]; then
printf -- '%b' "A password is required to connect iDrac host (it won't be displayed): "
read -r -s idrac_password
printf -- '%b\n' ""
fi
## }}}
## If idrac_password is still empty {{{
if [ -z "${idrac_password-}" ]; then
error_message "iDrac password can't be empty, please check your input. For more informations, see the help message (--help)." 12
fi
## }}}
## If java_disable_algo wasn't defined (argument) {{{
if [ -z "${java_disable_algo-}" ]; then
### Use default value
readonly java_disable_algo="${JAVA_DISABLE_ALGO_DEFAULT}"
fi
## }}}
## If temp_dir wasn't defined (argument) {{{
if [ -z "${temp_dir-}" ]; then
### Use default value
readonly temp_dir="${TEMP_DIR_BASE}/idrac.${idrac_host}"
fi
## }}}
}
# }}}
is_command_available() { # {{{
local_command_available_cmd="${1}"
debug_prefix="${2:-}"
## Return False by default
return_command_available="1"
if [ "$(command -v ${local_command_available_cmd})" ]; then
debug_message "${debug_prefix}is_command_available \
${RED}${local_command_available_cmd}${COLOR_DEBUG} seems present on this host."
return_command_available="0"
else
debug_message "${debug_prefix}is_command_available \
${RED}${local_command_available_cmd}${COLOR_DEBUG} is not available on this host."
return_command_available="1"
fi
unset local_command_available_cmd
unset debug_prefix
return "${return_command_available}"
}
# }}}
is_file_empty() { # {{{
local_file="${1}"
debug_prefix="${2:-}"
## File is empty by default
return_is_file_empty="0"
## Check if the file is empty
if [ ! -s "${local_file}" ]; then
return_is_file_empty="0"
debug_message "${debug_prefix}is_file_empty \
The file ${RED}${local_file}${COLOR_DEBUG} is empty or doesn't exists."
else
return_is_file_empty="1"
debug_message "${debug_prefix}is_file_empty \
The file ${RED}${local_file}${COLOR_DEBUG} exists and has a size greater than zero."
fi
unset local_file
unset debug_prefix
return "${return_is_file_empty}"
}
# }}}
main() { # {{{
debug_message "--- MAIN BEGIN"
## If java command is not available {{{
### Exit with error message
is_command_available "java" "| " \
|| error_message "No java command available. Please install a openjdk-*-jre package with your package manager." 01
## }}}
## If wget command is not available {{{
### Exit with error message
is_command_available "wget" "| " \
|| error_message "No wget command available. Please install =>wget<= package with your package manager." 02
## }}}
## Define all vars
define_vars
debug_message "| Define vars"
debug_message "| Given informations are :
idrac_host: ${RED}${idrac_host}${COLOR_DEBUG}
idrac_port: ${RED}${idrac_port}${COLOR_DEBUG}
idrac_username: ${RED}${idrac_username}${COLOR_DEBUG}
idrac_password: ${RED}HIDDEN${COLOR_DEBUG}
temp_dir: ${RED}${temp_dir}${COLOR_DEBUG}"
## Create and move to temp directory
debug_message "| Create and move to temp directory (${RED}${temp_dir}${COLOR_DEBUG})."
mkdir --parents -- "${temp_dir}"
cd -- "${temp_dir}" || error_message "Can't move to temp directory (${temp_dir})." 21
## Set Java security parameters
debug_message "| Set java security parameters (to ${RED}${JAVA_SECURITY_FILENAME}${COLOR_DEBUG} file)."
true > "${JAVA_SECURITY_FILENAME}"
printf '%b\n' "jdk.tls.disabledAlgorithms=${JAVA_DISABLE_ALGO_DEFAULT}" >> "${JAVA_SECURITY_FILENAME}"
## Try to download main jar file from idrac host
avctkmv_filename="avctKVM.jar"
avctkvm_url="https://${idrac_host}:${idrac_port}/software/${avctkmv_filename}"
debug_message "| Try to download ${RED}${avctkmv_filename}${COLOR_DEBUG} file from URL (${RED}${avctkvm_url}${COLOR_DEBUG})."
wget --timestamping --no-check-certificate --quiet -- "${avctkvm_url}"
is_file_empty "${avctkmv_filename}" "| " \
&& error_message "Downloaded ${avctkmv_filename} file is empty (from ${avctkvm_url} URL)." 22
## Librairies
## TODO? Download avctKVMIOLinux64.jar and avctVMLinux64.jar files to extract librairies (for keyboard…).
## Try to start iDrac console with java
printf '%b\n' "Try to start ${RED}${idrac_host}:${idrac_port}${RESET} virtual console with user (${RED}${idrac_username}${RESET}) and given password."
java -cp "${avctkmv_filename}" -Djava.security.properties=idrac.java.security -Djava.library.path=./lib com.avocent.idrac.kvm.Main ip="${idrac_host}" kmport=5900 vport=5900 user="${idrac_username}" passwd="${idrac_password}" apcp=1 version=2 vmprivilege=true "helpurl=https://${idrac_host}:${idrac_port}/help/contents.html"
cd -- - >/dev/null || error_message "Can't move to previous directory (before ${temp_dir})." 23
debug_message "--- MAIN END"
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to argument management
if [ ! "${NBARGS}" -eq "0" ]; then
manage_arg="0"
## If the first argument ask for help (h|help|-h|-help|-*h|-*help) {{{
if printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-*h(elp)?$"; then
usage
exit 0
fi
## }}}
## If the first argument is not an option
if ! printf -- '%s' "${1}" | grep --quiet --extended-regexp -- "^-+";
then
## Print help message and exit
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-+"; do
case "${1}" in
-d|--debug ) ## debug
DEBUG=0
debug_message "--- Manage argument BEGIN"
;;
--host ) ## Define idrac_host_temp with given arg
## Move to the next argument
shift
## Define var
readonly idrac_host_temp="${1}"
;;
-p,--port ) ## Define idrac_port with given arg
## Move to the next argument
shift
## Define var
readonly idrac_port="${1}"
;;
-u|--user ) ## Define idrac_username with given arg
## Move to the next argument
shift
## Define var
readonly idrac_username="${1}"
;;
--temp,--temp-dir,--temp-directory ) ## Define temp_dir with given arg
## Move to the next argument
shift
## Define var
readonly temp_dir="${1}"
;;
--java-disable-algo ) ## Define java_disable_algo with given arg
## Move to the next argument
shift
## Define var
readonly java_disable_algo="${1}"
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
debug_message "| ${RED}${1}${COLOR_DEBUG} option managed."
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
done
debug_message "| ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
debug_message "| No arguments/options to manage."
fi
debug_message "--- Manage argument END"
# }}}
main
exit 0