Skip to content
Snippets Groups Projects

start-vnc: pass all sbatch options with one script option

Merged Mathis Rosenhauer requested to merge fold-options into master
+ 93
110
#!/bin/bash
#
# Copyright 2019 Deutsches Klimarechenzentrum GmbH
# Copyright 2022 Deutsches Klimarechenzentrum GmbH
#
# All rights reserved.
#
@@ -35,15 +35,15 @@
# Ubuntu or Fedora Linux or macOS (tested). Other Unix flavors,
# including WSL on Microsoft Windows, may work as well. The script
# allows you to connect to one of DKRZ's HPC nodes to work in a
# desktop environment on that node..
# desktop environment on that node.
#
# Technically, it starts a VNC server on one of the nodes by
# submitting a generated job script. A local vncviewer client is used
# to connect to the server over an encypted ssh tunnel. After the
# to connect to the server over an encrypted ssh tunnel. After the
# client shuts down, the server job is terminated. TigerVNC, TightVNC,
# and TurboVNC are known to work.
#
# In case of problems contact support@dkrz.de.
# In case of problems, contact support@dkrz.de.
#
set -eufo pipefail
@@ -51,13 +51,22 @@ set -eufo pipefail
# Default settings
#
# You can change the settings here or override them with command line
# options. SVNC_ACCTCODE is the only parameter you have to provide if
# your local username matches your username on the frontend and if
# vncviewer is installed in the search path (tight/tigervnc on Linux
# for example).
# options. SVNC_SBATCH_OPTIONS is the only parameter you have to
# provide if your local username matches your username on the frontend
# and if vncviewer is installed in the search path (Tight/TigerVNC on
# Linux for example).
# Project account code
SVNC_ACCTCODE=""
# These options get passed to sbatch(1). Here you have to specify your
# account code and resource requirements.
SVNC_SBATCH_OPTIONS=""
# SVNC_SBATCH_OPTIONS="-A bk0555 -p interactive -n 4"
#
# This example would start a VNC session on the interactive partition
# with two physical (4 SMT) cores and 7680 MB of RAM (default). You
# have to fill in your project's account code (-A option). Adapt to
# your needs. In particular, if you need more memory.
# LDAP username
#
@@ -67,53 +76,32 @@ SVNC_USERNAME="$(id -un)"
# Path to local vncviewer
#
# If your local vnc client is not in the search path or named
# differently (e.g. TurboVNC, macOS), then change this parameter.
# If your local VNC client is not in the search path or named
# differently (e.g. TurboVNC on macOS), then change this parameter.
SVNC_CLIENT="vncviewer"
# Server options
# VNC Server options
#
# More options for the vncserver. TurboVNC on A Mac may produce
# a 'javax.net.ssl.SSLHandshakeException' in this case adding
# ' -securitytypes none' to SVNC_SERVER_OPTIONS may help.
# More options for the vncserver. TurboVNC on a Mac may produce a
# 'javax.net.ssl.SSLHandshakeException'. In this case, adding '
# -securitytypes none' to SVNC_SERVER_OPTIONS may help.
SVNC_SERVER_OPTIONS="-geometry 1920x1200"
# Session run time in minutes
SVNC_RUNTIME=240
# Number of nodes.
SVNC_NODES="1"
# Number of tasks per node.
SVNC_NTASKS_PER_NODE="1"
# Partition for the job
SVNC_PARTITION="interactive"
# Quality of service
SVNC_QOS="normal"
# Use a reservation
SVNC_RESERVATION=""
# Constraint for feature selection (GPU and/or memory)
SVNC_CONSTRAINT=""
# Uncomment this if you use TurboVNC as vncviewer.
#
# TurboVNC will work without this option but then it will use its own
# implementation of ssh which dosen't support public key auth among other
# things.
# implementation of ssh which doesn't support public key
# authentication among other things.
#
# readonly SVNC_CLIENT_OPTIONS="-extssh"
# SVNC_CLIENT_OPTIONS="-extssh"
# Frontend host
#
# Must be directly accessible from client. The frontend and the node
# Must be directly accessible from client. The front end and the node
# where vncserver is running need a shared home file system.
readonly SVNC_FRONTEND_HOST="levante.dkrz.de"
# Copy vncpassword temporarily to the local workstation
# Copy VNC password temporarily to the local workstation
#
# If your vncviewer client has trouble with TurboVNC's password format,
# then disable this option (set to "false" or comment).
@@ -141,7 +129,7 @@ clean_up () {
ssh_frontend "scancel -Q ${SVNC_JOB_ID}; sleep 1; \
rm -f .startvnc/out.${SVNC_JOB_ID}"
else
echo "Job ID not available. Make sure the vncjob is not running!"
echo "Job ID not known. You may have to kill the job manually."
ssh_frontend "squeue -u ${SVNC_USERNAME}"
fi
else
@@ -149,9 +137,9 @@ clean_up () {
fi
ssh_frontend "" "-O exit"
rmdir "${ssh_socket_dir}"
rmdir "${SVNC_SOCKET_DIR}"
# Remove local vnc PasswordFile
# Remove local VNC password file
if [[ "${SVNC_PASSWORD}" = true ]]; then
rm -f "vnc_passwd"
fi
@@ -164,117 +152,93 @@ Usage: $(basename "$0") [OPTION]
Available values for OPTION include:
-A acctcode acctcode of job
-C list constraint for feature selection
-N nodes number of nodes
-n ntasks number of tasks per node
-p partition run job on partition
-q qos job qos
-r reservation use reservation
-s options addidtional options for vncserver
-t time job runtime
-b options options passed to sbatch
-s options additional options for vncserver
-u username use username for login
-v path path to vncviewer program
-x options addidtional options for vncviewer
-x options additional options for vncviewer
EXAMPLE
start-vnc -b "-A bk0555 -p interactive -n 4"
This would start a VNC session on the interactive partition with two
physical (4 SMT) cores. You have to fill in your project's account
code (-A option). Adapt to your needs. In particular, if you need more
memory.
EOF
}
ssh_frontend () {
local command="$1"
local extra_options="${2:-}"
local options
options="${extra_options} -o ForwardAgent=no -o ForwardX11=no \
-o ControlPath=${ssh_socket_dir}/control:%h:%p:%r"
local options="${2:-}"
options+=" -o ForwardAgent=no -o ForwardX11=no \
-o ControlPath=${SVNC_SOCKET_DIR}/control:%h:%p:%r"
ssh ${options} "${SVNC_USERNAME}@${SVNC_FRONTEND_HOST}" "${command}"
}
parse_options () {
local option
while getopts 'A:C:N:n:p:q:r:s:t:u:v:x:' option; do
while getopts 'b:s:u:v:x:?h' option; do
case ${option} in
A) SVNC_ACCTCODE="$OPTARG"
;;
C) SVNC_CONSTRAINT="$OPTARG"
;;
N) SVNC_NODES="$OPTARG"
;;
n) SVNC_NTASKS_PER_NODE="$OPTARG"
;;
p) SVNC_PARTITION="$OPTARG"
;;
q) SVNC_QOS="$OPTARG"
;;
r) SVNC_RESERVATION="$OPTARG"
b) SVNC_SBATCH_OPTIONS="$OPTARG"
;;
s) SVNC_SERVER_OPTIONS="$OPTARG"
;;
t) SVNC_RUNTIME="$OPTARG"
;;
u) SVNC_USERNAME="$OPTARG"
;;
v) SVNC_CLIENT="$OPTARG"
;;
x) SVNC_CLIENT_OPTIONS="$OPTARG"
;;
?) usage
h|?) usage
exit 1
;;
esac
done
readonly SVNC_ACCTCODE
readonly SVNC_CONSTRAINT
readonly SVNC_NODES
readonly SVNC_NTASKS_PER_NODE
readonly SVNC_PARTITION
readonly SVNC_QOS
readonly SVNC_RESERVATION
readonly SVNC_SBATCH_OPTIONS
readonly SVNC_SERVER_OPTIONS
readonly SVNC_RUNTIME
readonly SVNC_USERNAME
readonly SVNC_CLIENT
readonly SVNC_CLIENT_OPTIONS
if [[ -z ${SVNC_ACCTCODE} ]]; then
printf "ERROR: Please specify an acctcode.\n\n" >&2
if [[ -z ${SVNC_SBATCH_OPTIONS} ]]; then
echo "No sbatch options provided. Set -b option or edit script."
usage
exit 1
fi
}
prepare_vncserver () {
vnc_password_check () {
if ! ssh_frontend "test -s .vnc/passwd"; then
echo "No VNC password found. Please set now."
echo "Do not use your LDAP password. Eight characters maximum."
echo "Wait for the prompt."
ssh_frontend "salloc -Q -n1 -p${SVNC_PARTITION} \
--reservation=${SVNC_RESERVATION} \
-A${SVNC_ACCTCODE} \
srun --pty /opt/TurboVNC/bin/vncpasswd" "-t"
cat <<EOF
Set your VNC password now.
Do not use your LDAP password. Eight characters maximum.
Wait for the prompt.
EOF
ssh_frontend "salloc -Q ${SVNC_SBATCH_OPTIONS} \
srun -n1 --pty /opt/TurboVNC/bin/vncpasswd" "-t"
fi
}
submit_vnc_job () {
ssh_frontend "mkdir -p .startvnc && cd .startvnc && sbatch" <<EOF
ssh_frontend "mkdir -p .startvnc && sbatch ${SVNC_SBATCH_OPTIONS}" <<EOF
#!/bin/bash -l
#SBATCH --job-name=vncserver
#SBATCH --partition=${SVNC_PARTITION}
#SBATCH --constraint=${SVNC_CONSTRAINT}
#SBATCH --nodes=${SVNC_NODES}
#SBATCH --ntasks-per-node=${SVNC_NTASKS_PER_NODE}
#SBATCH --qos=${SVNC_QOS}
#SBATCH --reservation=${SVNC_RESERVATION}
#SBATCH --time=${SVNC_RUNTIME}
#SBATCH --account=${SVNC_ACCTCODE}
#SBATCH --output=out.%j
#SBATCH --output=.startvnc/out.%j
#SBATCH --parsable
cd \${HOME}
/opt/TurboVNC/bin/vncserver -fg -localhost ${SVNC_SERVER_OPTIONS}
EOF
}
get_vnc_host_and_display () {
# Extract host name and display number from server output.
# Print heartbeat every second so this script fails if the
# ssh connection to the main script breaks down.
ssh_frontend "/bin/bash -s" <<EOF
logfile=\${HOME}/.startvnc/out.${SVNC_JOB_ID}
while [[ -z \${host_and_display} ]]; do
@@ -285,7 +249,7 @@ while [[ -z \${host_and_display} ]]; do
printf "." >&2
done
printf "\n" >&2
echo \${host_and_display}
echo "SUCCESS:\${host_and_display}"
EOF
}
@@ -301,19 +265,34 @@ get_jumphost_options () {
main () {
parse_options "$@"
trap clean_up INT QUIT TERM ERR EXIT
# Create ssh socket dir
mkdir -p "${HOME}/.ssh"
ssh_socket_dir="$(mktemp -d "${HOME}/.ssh/socket.XXXXX")"
SVNC_SOCKET_DIR="$(mktemp -d "${HOME}/.ssh/socket.XXXXX")"
# Connection sharing set-up
ssh_frontend "" "-MNf"
prepare_vncserver
# Check for password and set if missing
vnc_password_check
# Submit server job
echo "Submitting vncserver job."
SVNC_JOB_ID="$(submit_vnc_job)"
# Get host and display once job started
printf "Waiting for job ${SVNC_JOB_ID} to start" >&2
saved_IFS=${IFS}
IFS=: read -r SVNC_HOST SVNC_DISPLAY <<< "$(IFS=${saved_IFS} get_vnc_host_and_display)"
local saved_IFS=${IFS}
local status
IFS=: read -r status SVNC_HOST SVNC_DISPLAY <<< "$(IFS=${saved_IFS} get_vnc_host_and_display)"
if [[ "${status}" != "SUCCESS" ]]; then
printf "\nCould not start VNC server\n" >&2
exit 1
fi
echo "Vncserver started on node ${SVNC_HOST} display :${SVNC_DISPLAY}."
# Establish tunnel
#
# WSL doesn't seem to detect used ports so randomize
# local port to reduce risk of masking.
local vnc_port_local=$((5900 + RANDOM % 100))
@@ -328,12 +307,16 @@ main () {
vnc_port_local=$((5900 + RANDOM % 100))
echo "Trying local port ${vnc_port_local}."
done
# Build client options including password
local client_options="${SVNC_CLIENT_OPTIONS:-}"
if [[ "${SVNC_PASSWORD}" = true ]]; then
echo "Fetching password from frontend."
ssh_frontend "cat .vnc/passwd" > vnc_passwd
client_options+=" -passwd vnc_passwd"
fi
# Start client
echo "Connecting vncviewer to ${SVNC_HOST}"
"${SVNC_CLIENT}" ${client_options} :$(( vnc_port_local - 5900 ))
}
Loading