#!/bin/bash # This script is used as internalCustomStartupScript to setup the VM of the Azure Scale Set. # This setup is for CENTOS 7, and involves: # - setting up Docker and Docker-Compose # - setting up ProActive Node service with PNP # - starting the ProActive Node service # - install and setup the required packages/libs for the various script engine # mount /tmp folder systemctl start tmp.mount # Be sure the variables below is OK, depending on your context # The URL from where to retrieve the JRE tarball JRE_TARBALL_URL="https://s3.amazonaws.com/ci-materials/Latest_jre/jre-8u382b05-linux-x64.tar.gz" set -x set -e # Prerequisites: Install Docker and Docker Compose, add 'activeeon' user to docker group yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io groupadd docker usermod -aG docker activeeon curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ############################### # Downloads and install ProActive Node as a Systemd service ############################### mkdir -p /opt/proactive mkdir -p /tmp/node cd /tmp/node # Install dependencies yum install -y epel-release yum install -y jq # Install Java 8 # [MODIFY] modify if needed the URL to get the JRE wget --no-clobber $JRE_TARBALL_URL tar zxf jre-8u382b05-linux-x64.tar.gz ln -s /tmp/node/jre1.8.0_382b05 /tmp/node/java # making Java 8 available system-wide update-alternatives --install /usr/bin/java java /tmp/node/java/bin/java 1 update-alternatives --set java /tmp/node/java/bin/java # Retrieve NS config from CustomData if [ -f /var/lib/waagent/CustomData ]; then JSONCONFIG=$(base64 -d /var/lib/waagent/CustomData) elif [ -f /var/lib/cloud/instance/user-data.txt ]; then JSONCONFIG=$(cat /var/lib/cloud/instance/user-data.txt) elif [ -f /var/lib/waagent/ovf-env.xml ]; then JSONCONFIG=$(grep -oP '\K.*?(?=)' /var/lib/waagent/ovf-env.xml | base64 -d) else JSONCONFIG="" echo "Custom data not found in the system, aborting" exit 1 fi echo $JSONCONFIG export RMURL=`echo $JSONCONFIG | jq '.rmurl' -r` export CREDVALUE=`echo $JSONCONFIG | jq '.credentials' -r` export NODESOURCENAME=`echo $JSONCONFIG | jq '.nodesourcename' -r` export STORAGEACCOUNT=`echo $JSONCONFIG | jq '.storageaccount' -r` export SASKEY=`echo $JSONCONFIG | jq '.saskey' -r` export USERCUSTOMSCRIPTURL=`echo $JSONCONFIG | jq '.usercustomscripturl' -r` export EXTERNALSTORAGEACCOUNT=`echo $JSONCONFIG | jq '.externalstorageaccount' -r` export JVMPARAMETERS=`echo $JSONCONFIG | jq '.jvmparameters' -r` export NODEPRECOMMAND=`echo $JSONCONFIG | jq '.nodeprecommand' -r | sed -e 's/\\\\n/\n/g'` ############################### # Bash function used by the VM to send debug messages to the dedicated Azure Queue ############################### function debug { DEBUGCONTENT=`echo $1 | base64 -w 0` DEBUGMESSAGE="$DEBUGCONTENT" curl -X POST -d "$DEBUGMESSAGE" "https://$STORAGEACCOUNT.queue.core.windows.net/debug/messages?$SASKEY" } # debug debug "$HOSTNAME INFO: CustomData read properly (as I can write this message)" # Override custom script if specified if [ ! -z "$USERCUSTOMSCRIPTURL" ]; then curl -X GET "$USERCUSTOMSCRIPTURL" > user_custom_script.sh chmod +x user_custom_script.sh ./user_custom_script.sh >> user_script_stdout 2>>user_script_stderr if [ $? -ne 0 ]; then debug "$HOSTNAME FATAL: User custom script exited with error: $?" fi fi # Getting node.jar curl -X GET "https://$STORAGEACCOUNT.blob.core.windows.net/nodefiles/node.jar?$SASKEY" > node.jar # Change ownership to /tmp/node chown -R activeeon:activeeon /tmp/node # debug NOW=`date` debug "$HOSTNAME INFO: Start filling the Table on $NOW" start_time=$(date +%s) # Max time to try de delete msg from queue timeout_minutes=30 isValidMessage="false" while [[ "$isValidMessage" == "false" ]]; do # Read Azure Queue to get node name Deletion is performed on NS Side when nodes are properly registered msg=$(curl "https://$STORAGEACCOUNT.queue.core.windows.net/nodeconfig/messages?visibilitytimeout=300&$SASKEY") JSONMSG=`echo $msg | grep -oP '\K[^<]+' | base64 -d` msgId=`echo $msg | grep -oP '\K[^<]+'` popReceipt=`echo $msg | grep -oP '\K[^<]+'` # Encode popReceipt query param popReceipt=$(echo $popReceipt | jq -R -r @uri) dequeueCount=`echo $msg | grep -oP '\K[^<]+'` NODEBASENAME=`echo $JSONMSG | jq '.nodebasename' -r` NODEINSTANCES=`echo $JSONMSG | jq '.nodeinstances' -r` if [ -z "$NODEBASENAME" ]; then echo "$HOSTNAME ERROR: Unable to retrieve node configuration from 'nodeconfig' queue message $msg" # Check if 30 minutes have passed current_time=$(date +%s) elapsed_time=$((current_time - start_time)) if [ "$elapsed_time" -ge $((timeout_minutes * 60)) ]; then echo "Timeout of $timeout_minutes minutes reached for azure queue deletion." exit 5 fi echo "Retrying..." sleep 10 continue #halt #sleep 9999 #exit -1 fi # Try to delete message from queue URL="https://${STORAGEACCOUNT}.queue.core.windows.net/nodeconfig/messages/${msgId}?popreceipt=${popReceipt}&${SASKEY}" delete_response=$(curl -w "%{http_code}" -X DELETE $URL) echo "$delete_response" http_code=$(tail -n1 <<< "$delete_response") if [[ $http_code -ne 204 ]]; then echo "$HOSTNAME WARN: Could not delete Azure message from queue" fi if [[ "$dequeueCount" == "1" ]]; then isValidMessage="true" fi done # Retrieve instance metadata INSTANCE_NAME=$(curl -H Metadata:true "http://169.254.169.254/metadata/instance/compute?api-version=2017-12-01" | jq .name | sed 's/"//g') INSTANCE_ID=$(echo -n "$INSTANCE_NAME" | rev | cut -d'_' -f1 | rev) # Update Azure Table ENTITY="{'PartitionKey':'$HOSTNAME','RowKey':'$NODEBASENAME', 'NodesCount':'$NODEINSTANCES', 'InstanceId': '$INSTANCE_ID'}" curl -H "Content-Type: application/json" -d "$ENTITY" -X POST "https://$STORAGEACCOUNT.table.core.windows.net/nodesperhost?$SASKEY" if [ $? -ne 0 ]; then debug "$HOSTNAME FATAL: Unable to register the host into 'nodesperhost' table" exit 3 fi NOW=`date` debug "$HOSTNAME INFO: Terminated to fill the Table on $NOW" # Install py4j curl -O https://bootstrap.pypa.io/get-pip.py python2 get-pip.py pip install py4j pip install numpy # Generate the ExecStartPre commands if they were provided by the user EXECSTARTPRE='' if [ ! -z "$NODEPRECOMMAND" ]; then while read -r line; do EXECSTARTPRE=$EXECSTARTPRE`echo "ExecStartPre=$line"`$'\n' done <<< "$NODEPRECOMMAND" fi # Generate proactive-node systemd service unit file cat > /etc/systemd/system/proactive-node.service <