Newer
Older
#!/bin/bash
API_BASE_URL=https://labmanager-api.edu-al.unipmn.it/api/1.0
# curl uses an increasing delay. 5 retries are tried in about 30 seconds,
# so it's too quick for us. I increased it to 7, which is about 2 minutes.
# Note: the same variable was also used in the `retry` function.
MAX_RETRY=7
RETRY_DELAY=5
NORMAL_CONFIG_NAME=normale
DEBUG=0
# Sysadmin can override local vars here:
CONFFILE=/etc/default/labmanager
# Load configuration override if present:
if [ -e ${CONFFILE} ]; then
. ${CONFFILE}
fi
if [[ "-d" == "$2" ]]; then
DEBUG=1
fi
# execute a task and on fail execute it again MAX_RETRY times every RETRY_DELAY seconds
retry() {
local n=1
local max=$MAX_RETRY
local delay=$RETRY_DELAY
while true; do
"$@"
if [[ $? == 0 ]]; then
break
else
if [[ $n -lt $max ]]; then
((n++))
echo "Failed. Attempt $n/$max..." >&2
sleep $delay;
else
echo "Command failed after $n attempts." >&2
exit 1
fi
fi
done
}
debug() {
if [[ "${DEBUG}" == 1 ]]; then
echo >&2 "$@"
fi
}
# authenticate and get the token
getTokenJSON() {
# store the whole response with the status at the end
HTTP_RESPONSE=$(curl --retry-all-errors --retry ${MAX_RETRY} -s -k -w "HTTPSTATUS:%{http_code}" --max-time 10 -X POST -H "Content-Type: application/json" -d "{\"login\":\"guest\",\"pwd\":\"\"}" ${API_BASE_URL}/login)
ret=$?
if [[ $ret != 0 ]]; then
echo "Invalid authentication request!"
return $ret
fi
# extract the status
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
# check the status
if [[ $HTTP_STATUS -ne 200 ]]; then
echo "Authentication failed!"
return 1
else
# extract the body
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
echo $HTTP_BODY
fi
}
# extract a value from a JSON structure
jsonValue() {
KEY=$1
num=$2
awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/\042'$KEY'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p
}
stop() {
if [[ "$1" == "bootstop" ]]; then
echo "STOP esame-get-config-boot"
else
echo "STOP esame-get-config"
fi
}
# get configuration from WS
getConfigVars() {
echo "Authenticating to WS..."
TOKEN_JSON=`getTokenJSON`
if [[ "$TOKEN_JSON" == "" ]]; then
return 2
fi
TOKEN=`echo ${TOKEN_JSON} | jsonValue token 1`
MACHINE_NAME=`hostname`
echo "Getting machine configuration..."
MACHINE_JSON=`/usr/bin/curl --retry-all-errors --retry ${MAX_RETRY} -s -k --max-time 10 -H "Authorization: Bearer ${TOKEN}" -X GET ${API_BASE_URL}/machines/name/${MACHINE_NAME}`
MACHINE_ID=`echo $MACHINE_JSON | jsonValue id 1`
MACHINE_CONFIGS_ID=`echo $MACHINE_JSON | jsonValue configs_id 1`
CONFIG_NAME=`echo $MACHINE_JSON | jsonValue name 2`
EXAM_ID=`echo $MACHINE_JSON | jsonValue examid 1`
# web service returns "null" if there is no exam
# just set an empty string as value
if [[ "${EXAM_ID}" == "null" ]]; then
EXAM_ID=""
fi
if [[ "${CONFIG_NAME}" == "" ]]; then
echo "Error fetching machine configuration!"
return 1
fi
MACHINE_CONFIGS_ID_PREV=''
CONFIG_NAME_PREV=''
if [[ -e /local/config_name ]]
then
CONFIG_NAME_PREV=`cat /local/config_name`
fi
}
getConfigFile() {
echo "Downloading machine config file..."
# get configuration file
if [[ "${MACHINE_ID}" == "" ]]; then
echo "Error downloading config file (machine_id empty, maybe it is not in LabManager's DB)"
return 1
fi
HTTP_STATUS=`/usr/bin/curl --retry-all-errors --retry ${MAX_RETRY} -s -k -w "%{http_code}" -o /local/esame-machine.conf --max-time 10 --header "Authorization: Bearer ${TOKEN}" -X GET ${API_BASE_URL}/machines/${MACHINE_ID}/configfile`
if [[ $HTTP_STATUS -ne 200 ]]
then
echo "Error downloading config file (http_status=$HTTP_STATUS)"
return 1
else
echo "Downloaded config file (http_status=$HTTP_STATUS)"
fi
}
getIpConfigFile() {
echo "Downloading machine iptables config file..."
# get ipconfig file
HTTP_STATUS=`/usr/bin/curl --retry-all-errors --retry ${MAX_RETRY} -s -k -w "%{http_code}" -o /local/iptables --max-time 10 --header "Authorization: Bearer ${TOKEN}" -X GET ${API_BASE_URL}/machines/${MACHINE_ID}/ipconfigfile`
if [[ $HTTP_STATUS -ne 200 ]]
then
echo "Error downloading iptables config file (http_status=$HTTP_STATUS)"
return 1
else
echo "Downloaded iptables config file (http_status=$HTTP_STATUS)"
fi
}
updateCurrentConfigId() {
# Update this machine's current config id
HTTP_STATUS=`/usr/bin/curl --retry-all-errors --retry ${MAX_RETRY} -s -k -w "%{http_code}" -o /dev/null --max-time 10 -H "Content-Type: application/json" -H "Authorization: Bearer ${TOKEN}" \
-X PUT -d "{\"current_configs_id\":\"$MACHINE_CONFIGS_ID\"}" ${API_BASE_URL}/machines/${MACHINE_ID}/currentconfig`
if [[ $HTTP_STATUS -ne 200 ]]
then
echo "Error updating current config (http_status=$HTTP_STATUS)"
exit 1
else
echo "Updated current config (http_status=$HTTP_STATUS)"
fi
}
getConfig() {
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
getConfigVars
while [[ $? != 0 ]]; do
echo "Error fetching machine info!"
echo "If this is a new machine, did you add it into labmanager-admin?"
sleep 30;
getConfigVars
done
# back config files up
cp -f /local/esame-machine.conf /local/esame-machine.conf.prev >/dev/null 2>&1
cp -f /local/iptables /local/iptables.prev >/dev/null 2>&1
getConfigFile
if [[ $? != 0 ]]; then
echo "Error fetching machine config file!"
return 1
fi
getIpConfigFile
if [[ $? != 0 ]]; then
echo "Error fetching machine iptables file!"
return 1
fi
return 0
}
start() {
if [[ "$1" == "boot" ]]; then
echo "START esame-get-config-boot"
else
echo "START esame-get-config"
fi
getConfig
RESULT=$?
#echo "TOKEN_JSON: $TOKEN_JSON"
#echo "TOKEN: $TOKEN"
#echo "MACHINE_NAME: $MACHINE_NAME"
#echo "MACHINE_JSON: $MACHINE_JSON"
#echo "MACHINE_ID: $MACHINE_ID"
#echo "Exam ID: $EXAM_ID"
#echo "MACHINE_CONFIGS_ID: $MACHINE_CONFIGS_ID"
#echo "MACHINE_CONFIGS_ID_PREV: $MACHINE_CONFIGS_ID_PREV"

Alberto LIVIO BECCARIA
committed
# any error?
if [[ $RESULT != 0 ]]; then
if [[ "$1" == "boot" ]]; then
echo "Fatal error(s): aborting esame and switching machine to normal state..."
# reset and remove exam configuration files
echo "$NORMAL_CONFIG_NAME" > /local/config_name
echo "" > /local/examid
#rm /local/esame-machine.conf >/dev/null 2>&1
#rm /local/esame-machine.conf.prev >/dev/null 2>&1
rm /local/iptables >/dev/null 2>&1
rm /local/iptables.prev >/dev/null 2>&1
rm /local/mk-homedir >/dev/null 2>&1
/usr/bin/systemctl start graphical && exit 0
fi
echo "Fatal error(s): missing or wrong web service reply, abort."
exit 1
fi
# extract systemd target name from configuration file
# default target on error/empty target
ESAME_TARGET="graphical"
RES_TARGET=`awk -F= -v key="ESAME_TARGET" '$1==key {print $2}' /local/esame-machine.conf | sed "s/\"//g"`
if [[ "${RES_TARGET}" != "" ]]; then
ESAME_TARGET=${RES_TARGET}
fi
# extract ESAME_USBGUARD from configuration file
ESAME_USB_GUARD=0
RES_USB_GUARD=`awk -F= -v key="ESAME_USB_GUARD" '$1==key {print $2}' /local/esame-machine.conf | sed "s/\"//g"`
if [[ "${RES_USB_GUARD}" != "" ]]; then
ESAME_USB_GUARD=${RES_USB_GUARD}
fi
# extract ESAME_AMQP from configuration file
ESAME_AMQP=0
RES_AMQP=`awk -F= -v key="ESAME_AMQP" '$1==key {print $2}' /local/esame-machine.conf | sed "s/\"//g"`
if [[ "${RES_AMQP}" != "" ]]; then
ESAME_AMQP=${RES_AMQP}
fi
if [[ -n "${CONFIG_NAME}" ]]; then
echo "Configuration: ${CONFIG_NAME}"
if [ "${EXAM_ID}" != "" ]; then
echo "Exam ID: ${EXAM_ID}"
fi
if [ "${ESAME_TARGET}" != "" ]; then
echo "Systemd Target:: ${ESAME_TARGET}"
fi
fi

Alberto LIVIO BECCARIA
committed
# the PC is already up and running
if [[ "$1" != "boot" ]]; then
# get current examid (if any)
EXAM_ID_CURRENT=""
if [[ -f /local/examid ]]; then
EXAM_ID_CURRENT=`cat /local/examid`
fi
# different examid?
if [[ "${EXAM_ID}" != "${EXAM_ID_CURRENT}" ]]; then

Alberto LIVIO BECCARIA
committed
# reboot => normal
if [[ "${EXAM_ID}" == "" ]]; then

Alberto LIVIO BECCARIA
committed
echo "Reboot to Normal!"
# reboot => exam
else
echo "Reboot to Exam (exam id: ${EXAM_ID})"

Alberto LIVIO BECCARIA
committed
fi
/usr/bin/systemctl reboot
fi
else

Alberto LIVIO BECCARIA
committed
# at boot time
# update config_name file
echo "${CONFIG_NAME}" > /local/config_name
# no exam
# if [[ "$CONFIG_NAME" == "$NORMAL_CONFIG_NAME" ]]; then
if [[ "${EXAM_ID}" == "" ]]; then
# remove some files used by exam mode
#rm /local/esame-machine.conf >/dev/null 2>&1
#rm /local/esame-machine.conf.prev >/dev/null 2>&1
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
rm /local/iptables >/dev/null 2>&1
rm /local/iptables.prev >/dev/null 2>&1
rm /local/mk-homedir >/dev/null 2>&1
rm /local/usbguard >/dev/null 2>&1
# this is just cleaned up
echo "" > /local/examid
else
# if the examid of the session before the boot is different,
# then clean the exam user home (if the profile requires it)
EXAM_ID_PREV=""
# if the exam is already started, get examid from file
if [[ -f /local/examid ]]; then
EXAM_ID_PREV=`cat /local/examid`
fi
# different examid?
if [[ "${EXAM_ID}" != "${EXAM_ID_PREV}" ]]; then
# update the file with the current examid
echo "${EXAM_ID}" > /local/examid
# clean home dir if requested by the profile
touch /local/mk-homedir
fi
if [[ ${ESAME_USB_GUARD} == 1 ]]; then
touch /local/usbguard
else
rm /local/usbguard >/dev/null 2>&1

Alberto LIVIO BECCARIA
committed
fi
# if we use AMQP server, just disable esame-get-config.timer
if [[ ${ESAME_AMQP} == 1 ]]; then
systemctl disable esame-get-config.timer
systemctl stop esame-get-config.timer
# otherwise, enable it
else
systemctl enable esame-get-config.timer
systemctl start esame-get-config.timer
fi

Alberto LIVIO BECCARIA
committed
# choose the correct target
# we have just booted/rebooted, update the current configuration via web service
updateCurrentConfigId
systemctl start ${ESAME_TARGET}.target && exit 0
# case "$CONFIG_NAME" in
# $NORMAL_CONFIG_NAME) # normal
# systemctl start graphical.target && exit 0
# ;;
# 'kiosk-dir' | 'kiosk-dir-esami' | 'kiosk-escher' | 'kiosk-freebrowsing' | 'kiosk-teco') # kiosk mode
# systemctl start esamekiosk.target && exit 0
# ;;
# 'show') # show mode, an exam mode with no limitations on USB ports and network
# systemctl start esameshow.target && exit 0
# ;;
# *) # all full desktop exams
# systemctl start esame.target && exit 0
# ;;
# esac

Alberto LIVIO BECCARIA
committed
if [[ "$CONFIG_NAME" != "$NORMAL_CONFIG_NAME" ]]; then
# check if parameters are changed
cmp --silent /local/esame-machine.conf /local/esame-machine.conf.prev
if [[ $? -ne 0 ]]; then
/usr/bin/systemctl daemon-reload
echo "Configuration parameters changed: restart some services... "
# restart some exam services
#echo -n "USB..."
#/usr/bin/systemctl restart esame-usb
#echo " done."
KIOSK_URL_CHANGED=$(diff /local/esame-machine.conf /local/esame-machine.conf.prev | grep ESAME_KIOSK_URL -c)
if [[ $KIOSK_URL_CHANGED -ne 0 ]]; then
echo -n "Firefox Home..."
FIREFOX_PID=$(pgrep firefox)
if [[ "${FIREFOX_PID}" != "" ]]; then
FIREFOX_USER=$(ps -o user= -p ${FIREFOX_PID})

Alberto LIVIO BECCARIA
committed
rm -f /local/${FIREFOX_USER}/.mozilla/firefox/n3bac2sw.default-release/lock
pkill firefox
sleep 2
/usr/bin/systemctl restart esame-firefox-home
echo " done."
# no way to restart firefox, I must miss something :(
#echo -n "Restarting Firefox..."
#su - ${FIREFOX_USER} -c 'nohup /usr/bin/firefox --display=:0.0 &'
#echo " done."
else
/usr/bin/systemctl restart esame-firefox-home
echo " done."
fi
fi
# USBGuard
if [[ ${ESAME_USB_GUARD} == 1 ]]; then
touch /local/usbguard
/usr/bin/systemctl restart usbguard
else
rm /local/usbguard >/dev/null 2>&1
# this one will not work anyway, as it is applied by kernel,
# so it needs a reboot
/usr/bin/systemctl stop usbguard
fi
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
echo
echo "All done."
fi
fi
}
args=("$@")
case "$1" in
'bootstart')
start "boot"
;;
'bootstop')
stop "boot"
;;
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
*)
echo "Usage: $0 { bootstart | bootstop | start | stop | restart }";
exit 1;
;;
esac
exit 0