#!/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 <