Last active
November 15, 2023 19:03
-
-
Save activeeon-bot/dcbe0758c9da6bdb3f4a5dfb7e87af0f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 | |
# while ! [ -f /tmp/go ]; | |
# do | |
# sleep 1 | |
# done | |
# 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/rhel/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 -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm | |
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 '<ns1:CustomData>\K.*?(?=</ns1:CustomData>)' /var/lib/waagent/ovf-env.xml | base64 -d) | |
else | |
JSONCONFIG="" | |
echo "Custom data not found in the system, aborting" | |
exit 1 | |
fi | |
echo "Json Config:" | |
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="<QueueMessage><MessageText>$DEBUGCONTENT</MessageText></QueueMessage>" | |
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 '<MessageText>\K[^<]+' | base64 -d` | |
msgId=`echo $msg | grep -oP '<MessageId>\K[^<]+'` | |
popReceipt=`echo $msg | grep -oP '<PopReceipt>\K[^<]+'` | |
# Encode popReceipt query param | |
popReceipt=$(echo $popReceipt | jq -R -r @uri) | |
dequeueCount=`echo $msg | grep -oP '<DequeueCount>\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 <<EOL | |
[Unit] | |
After=sshd.service | |
[Service] | |
WorkingDirectory=/tmp/node | |
EnvironmentFile=-/etc/environment | |
${EXECSTARTPRE}ExecStart=/usr/bin/java -jar /tmp/node/node.jar ${JVMPARAMETERS} -Dpython.path=/tmp/node/lib/jython-standalone-2.7.0.jar/Lib -v ${CREDVALUE} -w ${NODEINSTANCES} -r ${RMURL} -n ${NODEBASENAME} -s ${NODESOURCENAME} | |
User=activeeon | |
[Install] | |
WantedBy=default.target | |
EOL | |
chmod 664 /etc/systemd/system/proactive-node.service | |
# Install ProActive Node Service | |
systemctl daemon-reload | |
systemctl enable proactive-node.service | |
sysctl fs.inotify.max_user_watches=524288 # Support for large number of nodes | |
# Debug message posted on debug queue | |
IP=$(hostname -i) | |
debug "$HOSTNAME INFO: Service is ready to start: $IP , $NODEBASENAME , $NODEINSTANCES" | |
############################### | |
############################### | |
# Let's start the ProActive node service | |
############################### | |
systemctl start proactive-node.service |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment