Skip to content
Snippets Groups Projects
get-config 13.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/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
    
        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
    }
    
    
        if [[ "${DEBUG}" == 1 ]]; then
            echo >&2 "$@"
        fi
    }
    
    # authenticate and get the token
    
        # 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
    
        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
    }
    
    
        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 [[ $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 && 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
    
    
        # 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
    
                if [[ "${EXAM_ID}" == "" ]]; then
    
                    echo "Reboot to Exam (exam id: ${EXAM_ID})"
    
                /usr/bin/systemctl reboot
            fi
        else
    
            # 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
    
                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
    
            # 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
    
    
            # 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
    
        # 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
    
                /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/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
    
                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