Skip to content

Commit

Permalink
Adhoc Auto Provisioning (#342)
Browse files Browse the repository at this point in the history
  • Loading branch information
stanbrub authored Sep 25, 2024
1 parent 34f8e32 commit e3deedf
Show file tree
Hide file tree
Showing 15 changed files with 477 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .github/resources/adhoc-benchmark-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services:
volumes:
- ./data:/data
environment:
- "START_OPTS=-Xmx24g -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler"
- "START_OPTS=-DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler ${CONFIG_OPTS}"

redpanda:
command:
Expand Down
155 changes: 155 additions & 0 deletions .github/scripts/adhoc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env bash

set -o errexit
set -o pipefail

# Provides what is needed to set up an adhoc benchmark run, including bare metal and labels
# ex. adhoc.sh make-labels "where" "0.36.0" "user123:branch-name-123"
# ex. adhoc.sh metal-deploy api-key project-id c3.small.x86 server-name "2 days"
# ex. adhoc.sh metal-delete api-key device-id service-name

if [[ $# < 2 ]]; then
echo "$0: Missing action or its arguments"
exit 1
fi

ACTION=$1
SCRIPT_DIR=$(dirname "$0")
OUTPUT_NAME=adhoc-${ACTION}.out

rm -f ${OUTPUT_NAME}; touch ${OUTPUT_NAME}

# Get metal device info including ip address
getDeviceInfo() {
curl --no-progress-meter --max-time 10 -X GET -H "X-Auth-Token: $1" \
"https://api.equinix.com/metal/v1/devices/$2?include=ip_addresses,state&exclude=root_password,ssh_keys" \
| jq | tee get-device-response.json | jq -r "$3"
}

# Get the label part of an image/branch name
# ex. edge@sha256:15ab331629805076cdf5ed6666186c6b578298ab493a980779338d153214640e
# ex. user123:1111-my-pull-request
# ex. 0.36.0 or edge
getSetLabel() {
SUFFIX=$2
if [[ $2 == *"@sha"*":"* ]]; then
SUFFIX=$(echo "$2" | sed 's/@sha.*:/_/g' | head -c 20)
elif [[ $2 == *":"* ]]; then
SUFFIX=$(echo "$2" | sed 's/.*://g' | head -c 20)
fi
echo "${PREFIX}_${SUFFIX}" | sed -E 's/(^[0-9])/_\1/g' | sed 's/[^0-9a-zA-Z_]/_/g'
}

# Make set labels from a prefix and image/branch names
if [[ ${ACTION} == "make-labels" ]]; then
PREFIX=$2
IMAGE1=$3
IMAGE2=$4
echo "Making Labels: ${PREFIX}"

LABEL1=$(getSetLabel ${PREFIX} ${IMAGE1})
LABEL2=$(getSetLabel ${PREFIX} ${IMAGE2})

echo "PREFIX=${PREFIX}" | tee -a ${OUTPUT_NAME}
echo "SET_LABEL_1=${LABEL1}" | tee -a ${OUTPUT_NAME}
echo "SET_LABEL_2=${LABEL2}" | tee -a ${OUTPUT_NAME}
fi

# Make a regex from a list of wilcarded test class names
if [[ ${ACTION} == "make-test-regex" ]]; then
WILDCARDS=$2
echo "Making Test Regex: ${WILDCARDS}"

TEST_REGEX="^.*[.]("
for r in $(echo ${WILDCARDS} | sed 's/\s*,\s*/ /g'); do
TEST_REGEX="${TEST_REGEX}"$(echo "(${r}Test)|" | sed 's/\*/.*/g')
done
TEST_REGEX=$(echo ${TEST_REGEX} | sed -E 's/\|+$//g')
TEST_REGEX="${TEST_REGEX})$"

echo "WILDCARDS=${WILDCARDS}" | tee -a ${OUTPUT_NAME}
echo "TEST_CLASS_REGEX=${TEST_REGEX}" | tee -a ${OUTPUT_NAME}
fi

# Format some number used for scaling the tests
if [[ ${ACTION} == "scale-nums" ]]; then
INPUT_ROW_COUNT=$2
INPUT_ITERATIONS=$3
echo "Scaling Numbers"

TEST_ROW_COUNT=$((${INPUT_ROW_COUNT} * 1000000))
TEST_ITERATIONS=${INPUT_ITERATIONS}
if [ $((${INPUT_ITERATIONS} % 2)) == 0 ]; then
TEST_ITERATIONS=$((${INPUT_ITERATIONS} + 1))
fi

echo "INPUT_ROW_COUNT=${INPUT_ROW_COUNT}" | tee -a ${OUTPUT_NAME}
echo "INPUT_ITERATIONS=${INPUT_ITERATIONS}" | tee -a ${OUTPUT_NAME}
echo "TEST_ROW_COUNT=${TEST_ROW_COUNT}" | tee -a ${OUTPUT_NAME}
echo "TEST_ITERATIONS=${TEST_ITERATIONS}" | tee -a ${OUTPUT_NAME}
fi

# Deploy a bare metal server using the Equinix ReST API
if [[ ${ACTION} == "deploy-metal" ]]; then
API_KEY=$2
PROJECT_ID=$3
PLAN=$4
ACTOR=$(echo "adhoc-$5-"$(${SCRIPT_DIR}/base.sh $(date +%s%03N) 36) | tr '[:upper:]' '[:lower:]')
EXPIRE_WHEN=$6
echo "Deploying Server: ${ACTOR}"

BEGIN_SECS=$(date +%s)
DEVICE_ID=$(curl --fail-with-body -X POST \
-H "Content-Type: application/json" -H "X-Auth-Token: ${API_KEY}" \
"https://api.equinix.com/metal/v1/projects/${PROJECT_ID}/devices?exclude=plan,ssh_keys,provisioning_events,network_ports,operating_system" \
-d '{
"metro": "da",
"plan": "'${PLAN}'",
"operating_system": "ubuntu_22_04",
"hostname": "'${ACTOR}'",
"termination_time": "'$(date --iso-8601=seconds -d "+${EXPIRE_WHEN}")'"
}' | jq | tee create-device-response.json | jq -r '.id')

IP_ADDRESS="null"
for i in $(seq 100); do
echo -n "$i) Device Status: "
STATE=$(getDeviceInfo ${API_KEY} ${DEVICE_ID} ".state")
echo "${STATE}"
if [[ "${STATE}" == "active" ]]; then break; fi
sleep 6
done

DURATION=$(($(date +%s) - ${BEGIN_SECS}))

IP_ADDRESS=$(getDeviceInfo ${API_KEY} ${DEVICE_ID} ".ip_addresses[0].address")
STATE=$(getDeviceInfo ${API_KEY} ${DEVICE_ID} ".state")
if [[ "${IP_ADDRESS}" == "null" ]] || [[ "${STATE}" != "active" ]]; then
echo "Failed to provision device after ${DURATION} seconds"
exit 1
fi

echo "ACTION=${ACTION}" | tee -a ${OUTPUT_NAME}
echo "PROVISION_SECS=${DURATION}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_NAME=${ACTOR}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_ID=${DEVICE_ID}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_ADDR=${IP_ADDRESS}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_EXPIRE=${EXPIRE_WHEN}" | tee -a ${OUTPUT_NAME}
fi

# Delete a bare metal server using the Equlinix ReST API
if [[ ${ACTION} == "delete-metal" ]]; then
API_KEY=$2
DEVICE_ID=$3
DEVICE_NAME=$4

curl --no-progress-meter --max-time 10 --fail-with-body -X DELETE -H "X-Auth-Token: ${API_KEY}" \
"https://api.equinix.com/metal/v1/devices/${DEVICE_ID}" \
| jq | tee delete-device-response.json

echo "ACTION=${ACTION}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_NAME=${DEVICE_NAME}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_ID=${DEVICE_ID}" | tee -a ${OUTPUT_NAME}
fi



16 changes: 16 additions & 0 deletions .github/scripts/base.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -o errexit
set -o pipefail

# Convert the given Base 10 number to the given radix up to base 62
# ex. base.sh 1718738365297350992 62
# ex. base.sh $(date +%s%03N) 36

DECNUM=$1
RADIX=$2
BASE62=($(echo {0..9} {A..Z} {a..z}))

for i in $(bc <<< "obase=${RADIX}; ${DECNUM}"); do
echo -n ${BASE62[$(( 10#$i ))]}
done && echo
2 changes: 1 addition & 1 deletion .github/scripts/build-server-distribution-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ HOST=`hostname`
GIT_DIR=/root/git
DEEPHAVEN_DIR=/root/deephaven
DOCKER_IMG=$1
BRANCH_DELIM="::"
BRANCH_DELIM=":"
BUILD_JAVA=temurin-11-jdk-amd64

if [ ! -d "${DEEPHAVEN_DIR}" ]; then
Expand Down
19 changes: 12 additions & 7 deletions .github/scripts/fetch-results-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ set -o pipefail
set -o nounset

# Fetches Benchmark results and logs from the remote test server and
# compresses the runs before upload
# compresses the runs before upload. Writes an output file with the
# SET_LABEL that was used for the set directory name

if [[ $# != 7 ]]; then
echo "$0: Missing host, user, run type, script dir, actor, docker img, or run label arguments"
Expand All @@ -17,31 +18,35 @@ USER=$2
SCRIPT_DIR=$3
RUN_TYPE=$4
ACTOR=$5
RUN_LABEL=${6:-$(echo -n "set-"; ${SCRIPT_DIR}/base62.sh $(date +%s%03N))}
SET_LABEL=${6:-$(echo -n "set-"; ${SCRIPT_DIR}/base.sh $(date +%s%03N) 62)}
DOCKER_IMG=$7
RUN_DIR=/root/run
OUTPUT_NAME=fetch-results-local.out

rm -f ${OUTPUT_NAME}; touch ${OUTPUT_NAME}

# Get the date for the Set Label, since Github Workflows don't have 'with: ${{github.date}}'
if [ "${RUN_LABEL}" = "<date>" ]; then
RUN_LABEL=$(date '+%Y-%m-%d')
if [ "${SET_LABEL}" = "<date>" ]; then
SET_LABEL=$(date '+%Y-%m-%d')
fi

# Get the version for the Set Label, since Github Workflows don't have 'with: ${{github.date}}'
if [ "${RUN_LABEL}" = "<version>" ]; then
if [ "${SET_LABEL}" = "<version>" ]; then
vers=${DOCKER_IMG}
major=$(printf '%02d\n' $(echo ${vers} | cut -d "." -f 1))
minor=$(printf '%03d\n' $(echo ${vers} | cut -d "." -f 2))
patch=$(printf '%02d\n' $(echo ${vers} | cut -d "." -f 3))
RUN_LABEL="${major}.${minor}.${patch}"
SET_LABEL="${major}.${minor}.${patch}"
fi
echo "SET_LABEL=${SET_LABEL}" | tee -a ${OUTPUT_NAME}

# Pull results from the benchmark server
scp -r ${USER}@${HOST}:${RUN_DIR}/results .
scp -r ${USER}@${HOST}:${RUN_DIR}/logs .
scp -r ${USER}@${HOST}:${RUN_DIR}/*.jar .

# Move the results into the destination directory
DEST_DIR=${RUN_TYPE}/${ACTOR}/${RUN_LABEL}
DEST_DIR=${RUN_TYPE}/${ACTOR}/${SET_LABEL}
mkdir -p ${DEST_DIR}
rm -rf ${DEST_DIR}
mv results/ ${DEST_DIR}/
Expand Down
28 changes: 20 additions & 8 deletions .github/scripts/manage-deephaven-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ set -o pipefail
# The directives argument can be start or stop
# The supplied image argument can be an image name or <owner>::<branch>

if [[ $# != 2 ]]; then
echo "$0: Missing docker directive or image/branch argument"
if [[ $# -lt 3 ]]; then
echo "$0: Missing docker directive, image/branch, config options argument"
exit 1
fi

HOST=`hostname`
DEEPHAVEN_DIR=/root/deephaven
DIRECTIVE=$1
DOCKER_IMG=$2
BRANCH_DELIM="::"
CONFIG_OPTS="${@:3}"
HOST=`hostname`
DEEPHAVEN_DIR=/root/deephaven

if [ ! -d "${DEEPHAVEN_DIR}" ]; then
echo "$0: Missing one or more Benchmark setup directories"
Expand All @@ -29,11 +29,23 @@ title "- Setting up Remote Docker Image on ${HOST} -"

cd ${DEEPHAVEN_DIR}

if [[ ${DOCKER_IMG} != *"${BRANCH_DELIM}"* ]]; then
echo "DOCKER_IMG=ghcr.io/deephaven/server:${DOCKER_IMG}" > .env
if [[ ${CONFIG_OPTS} == "<default>" ]]; then
CONFIG_OPTS="-Xmx24g"
fi
echo "CONFIG_OPTS=${CONFIG_OPTS}" > .env

IS_BRANCH="false"
if [[ ${DOCKER_IMG} == *"@sha"*":"* ]]; then
IS_BRANCH="false"
elif [[ ${DOCKER_IMG} == *":"* ]]; then
IS_BRANCH="true"
fi

if [[ ${IS_BRANCH} == "false" ]]; then
echo "DOCKER_IMG=ghcr.io/deephaven/server:${DOCKER_IMG}" >> .env
docker compose pull
else
echo "DOCKER_IMG=deephaven/server:benchmark-local" > .env
echo "DOCKER_IMG=deephaven/server:benchmark-local" >> .env
fi

if [[ ${DIRECTIVE} == 'start' ]]; then
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/setup-ssh-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ PRIVATE_KEY=$2
PRIVATE_FILE=~/.ssh/id_ed25519

if [[ $# != 2 ]]; then
echo "$0: Missing host or private key arguments"
exit 1
echo "$0: Missing host or private key arguments"
exit 1
fi

mkdir -p logs
Expand Down
26 changes: 13 additions & 13 deletions .github/scripts/setup-test-server-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ title "-- Adding OS Applications --"
UPDATED=$(update-alternatives --list java | grep -i temurin; echo $?)
if [[ ${UPDATED} != 0 ]]; then
title "-- Adding Adoptium to APT registry --"
apt install -y wget apt-transport-https gpg
wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | apt-key add -
apt -y install wget apt-transport-https gpg
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null
echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
apt update
apt -y update
fi

title "-- Installing JVMs --"
apt -y install temurin-11-jdk
apt -y install temurin-21-jdk
# Look at installed packages: dpkg --list | grep jdk
# Configure default java: update-alternatives --config java

title "-- Installing Maven --"
apt -y install maven
Expand All @@ -54,16 +52,18 @@ command_exists() {
if command_exists docker; then
echo "Docker already installed... skipping"
else
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyringsA
rm -f /etc/apt/keyrings/docker.gpg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
apt -y update
apt -y install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get --assume-yes install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
apt -y update
apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
fi

title "-- Removing Git Benchmark Repositories --"
Expand Down
Loading

0 comments on commit e3deedf

Please sign in to comment.