#!/bin/bash API_BASE_URL=https://labmanager-api.edu-al.unipmn.it/api/1.0 MAX_RETRY=5 RETRY_DELAY=5 NORMAL_CONFIG_NAME=normale DEBUG=0 # Sysadmin can override local vars here: CONFFILE=/etc/sysconfig/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 function 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 } function debug() { if [[ "${DEBUG}" == 1 ]]; then echo >&2 "$@" fi } # authenticate and get the token function getTokenJSON() { # store the whole response with the status at the end HTTP_RESPONSE=$(curl -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 function 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=`retry getTokenJSON` if [[ "$TOKEN_JSON" == "" ]]; then return 2 fi TOKEN=`echo ${TOKEN_JSON} | jsonValue token 1` MACHINE_NAME=`hostname` echo "Getting machine configuration..." MACHINE_JSON=`retry /usr/bin/curl -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` 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=`retry /usr/bin/curl -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=`retry /usr/bin/curl -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 -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 } function getConfig() { 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 "MACHINE_CONFIGS_ID: $MACHINE_CONFIGS_ID" #echo "MACHINE_CONFIGS_ID_PREV: $MACHINE_CONFIGS_ID_PREV" if [[ -n "$CONFIG_NAME" ]]; then echo "Configuration: $CONFIG_NAME" fi 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 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.target && exit 0 fi echo "Fatal error(s): missing or wrong web service reply, abort." exit 1 fi # configuration profile is changed if [[ "$CONFIG_NAME" != "$CONFIG_NAME_PREV" ]] then # update config_name file echo "${CONFIG_NAME}" > /local/config_name # no exam, set normal target if [[ "$CONFIG_NAME" == "$NORMAL_CONFIG_NAME" ]] then # stop some services to revert system files 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 echo "Normal!" #systemctl isolate graphical && exit 0 /usr/bin/systemctl reboot #--force else echo "Exam!" touch /local/mk-homedir #systemctl isolate esame.target && exit 0 /usr/bin/systemctl reboot #--force fi else # at boot time choose the correct target if [[ "$1" == "boot" ]] then # we have just rebooted, update the current configuration via web service updateCurrentConfigId 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 fi fi # Runtime parameters 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}) rm -f /local/${FIREFOX_USER}/.mozilla/firefox/44bu2eyb.default/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 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