Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
31d88a6
Preserver the terraform mess
stanbrub Jan 23, 2026
9a713ae
Got working with API and default user
stanbrub Jan 28, 2026
2dc5e1b
updated sudo access for setup since we're using non-root
stanbrub Jan 29, 2026
8a3de30
Remove group add docker, since it already exists
stanbrub Jan 29, 2026
7c6ca69
refresh docker group
stanbrub Jan 29, 2026
f10ba1b
Added docker restart for the group add
stanbrub Jan 29, 2026
895c63c
Rework docker group adding
stanbrub Jan 29, 2026
527f856
More sudo
stanbrub Jan 29, 2026
e1bd335
Fixed default Test Class spec
stanbrub Jan 29, 2026
c34fc34
Add user to docker compose path instead of root
stanbrub Jan 29, 2026
2c59846
Remove sudo from restart controller
stanbrub Jan 29, 2026
462e7e3
Use user home for resource directory root
stanbrub Jan 29, 2026
f6ec413
Removed root from fetch results
stanbrub Jan 29, 2026
39f1cbd
Remove cloud-init read, since it doesn't work
stanbrub Jan 29, 2026
eec3f69
Updated to ubuntu 24
stanbrub Jan 29, 2026
5e1d958
Rework server-up checking to not use SSH
stanbrub Jan 30, 2026
8872fc9
Fixed status check on adhoc deploy
stanbrub Feb 2, 2026
8e039f5
Use apt-get and noninteractive. Check APT locks first
stanbrub Feb 2, 2026
85b0407
Dealt with some noninterative grouping issues
stanbrub Feb 3, 2026
38bd78f
Disabled auto updaters
stanbrub Feb 3, 2026
db86920
Fix
stanbrub Feb 3, 2026
3f56c2a
Reload correct ssh service
stanbrub Feb 3, 2026
6d4770d
Added metal purge to workflow
stanbrub Feb 3, 2026
bca6cfe
Standardized the adhoc server name prefix
stanbrub Feb 3, 2026
b53044a
Added purge servers to the remote workflow
stanbrub Feb 3, 2026
6b0ba79
Get PNAP auth for purge
stanbrub Feb 3, 2026
260dc21
Fixed temurin check
stanbrub Feb 3, 2026
5787915
Moved purge expired metal to its own always-run job
stanbrub Feb 4, 2026
571256a
Set adhoc server expiration to 24 hours
stanbrub Feb 4, 2026
1fc0acc
Add slack channel for testing
stanbrub Feb 4, 2026
93773b0
Made ssh lookup safer
stanbrub Feb 4, 2026
eac8291
Removed test slack channel for adhoc
stanbrub Feb 4, 2026
65ac6b5
Disable ASLR. Updated some workflows to 24.04
stanbrub Feb 4, 2026
4d327ec
Fixed a missing done
stanbrub Feb 4, 2026
7268f97
Review updates
stanbrub Feb 5, 2026
3ffcee4
Fix bad comparison
stanbrub Feb 5, 2026
860b991
Removed userHome slashes
stanbrub Feb 5, 2026
721bb8e
Allow running nightly on PNAP from fork
stanbrub Feb 5, 2026
6fb4426
Change ASLR disable to just current session
stanbrub Feb 5, 2026
c2d81ff
remove bc and some other things
stanbrub Feb 9, 2026
169aed7
More delete metal more robust. Share function between single and purge
stanbrub Feb 10, 2026
16c2e67
Remove spaces from test class pattern
stanbrub Feb 10, 2026
13ad899
Re-enabled the nightly cron job and fork ban
stanbrub Feb 13, 2026
1a0e663
Added sudo to more docker commands during setup
stanbrub Feb 13, 2026
bf7874b
Added governor setting to setup
stanbrub Feb 18, 2026
588b76b
Trying performance scaling with turbo boost turned off
stanbrub Feb 18, 2026
d9a1ad9
Turn turbo boost back on
stanbrub Feb 18, 2026
4c1d1f5
Test powersave with turboboost on
stanbrub Feb 18, 2026
31a82c3
Add bigger timeout for deephaven server ready
stanbrub Feb 19, 2026
ccf7633
Test Performance mode
stanbrub Feb 19, 2026
632fdad
Fixed broken action condition. Test cstate
stanbrub Feb 19, 2026
1d66b47
Revert cstate, since it requires a reboot
stanbrub Feb 19, 2026
8c2f7de
Try performance with turbo off
stanbrub Feb 20, 2026
eb21993
Changed to schedutil turbo on
stanbrub Feb 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/resources/adhoc-scale-benchmark.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ timestamp.test.results=

# Experimental: Docker compose file (e.g. /mypath/docker-compose.yml)
# Empty means no docker restart attempt will be made
docker.compose.file=/root/deephaven/docker-compose.yml
docker.compose.file=${userHome}/deephaven/docker-compose.yml

# The url used for posting messages to slack
slack.token=
Expand Down
14 changes: 14 additions & 0 deletions .github/resources/adhoc-server-deploy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hostname": "my-server",
"description": "Ephemeral adhoc benchmark server",
"os": "ubuntu/noble",
"type": "s2.c2.small",
"location": "CHI",
"installDefaultSshKeys": true,
Comment thread
stanbrub marked this conversation as resolved.
"publicIpAddresses": [
{
"type": "PRIMARY"
}
]
}

2 changes: 1 addition & 1 deletion .github/resources/compare-scale-benchmark.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ timestamp.test.results=

# Experimental: Docker compose file (e.g. /mypath/docker-compose.yml)
# Empty means no docker restart attempt will be made
docker.compose.file=/root/deephaven/docker-compose.yml
docker.compose.file=${userHome}/deephaven/docker-compose.yml

2 changes: 1 addition & 1 deletion .github/resources/nightly-scale-benchmark.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ timestamp.test.results=

# Experimental: Docker compose file (e.g. /mypath/docker-compose.yml)
# Empty means no docker restart attempt will be made
docker.compose.file=/root/deephaven/docker-compose.yml
docker.compose.file=${userHome}/deephaven/docker-compose.yml

# The url used for posting messages to slack
slack.token=${slackToken}
Expand Down
2 changes: 1 addition & 1 deletion .github/resources/release-scale-benchmark.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ timestamp.test.results=

# Experimental: Docker compose file (e.g. /mypath/docker-compose.yml)
# Empty means no docker restart attempt will be made
docker.compose.file=/root/deephaven/docker-compose.yml
docker.compose.file=${userHome}/deephaven/docker-compose.yml
170 changes: 116 additions & 54 deletions .github/scripts/adhoc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,34 @@
set -o errexit
set -o pipefail

# Copyright (c) 2023-2024 Deephaven Data Labs and Patent Pending
# Copyright (c) 2023-2026 Deephaven Data Labs and Patent Pending

# 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
# ex. adhoc.sh scale-nums 10 5
# ex. adhoc.sh deploy-metal api-key project-id s2.c2.small server-name
# ex. adhoc.sh delete-metal api-key project-id device-id server-name
# ex. adhoc.sh purge-metal api-key project-id

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

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

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
PREFIX="$1"
SUFFIX="$2"
if [[ $2 == *"@sha"*":"* ]]; then
SUFFIX=$(echo "$2" | sed 's/@sha.*:/_/g' | head -c 20)
elif [[ $2 == *":"* ]]; then
Expand All @@ -42,75 +39,113 @@ getSetLabel() {
echo "${PREFIX}_${SUFFIX}" | sed -E 's/(^[0-9])/_\1/g' | sed 's/[^0-9a-zA-Z_]/_/g'
}

getApiToken() {
curl -s -X POST "https://auth.phoenixnap.com/auth/realms/BMC/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=$1" --data-urlencode "client_secret=$2" | jq -r '.access_token'
}

deleteMetal() {
TOKEN="$1"
DEVICE_ID="$2"
DEVICE_NAME="$3"
echo "Deleting server ${DEVICE_NAME}"
RESP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: Bearer ${TOKEN}" "https://api.phoenixnap.com/bmc/v1/servers/${DEVICE_ID}")
CURL_EXIT=$?
if (( ${CURL_EXIT} != 0 )); then
echo "Failed deleting server ${DEVICE_NAME} with exit code ${CURL_EXIT}"
exit 1
fi
if (( ${RESP_CODE} != 404 && (${RESP_CODE} < 200 || ${RESP_CODE} >= 300) )); then
echo "Failed deleting server ${DEVICE_NAME} with http code ${RESP_CODE}"
exit 1
fi
echo "Successfully deleted server ${DEVICE_NAME}"
}


# 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

# Format some number used for scaling the tests
# Format some numbers 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
# Deploy a bare metal server using the Phoenix NAP 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
ACTOR=$(echo "${SERVER_NAME_PREFIX}$5-"$(${SCRIPT_DIR}/base.sh $(date +%s%03N) 36) | tr '[:upper:]' '[:lower:]')
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": "sv",
"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

pushd ${SCRIPT_DIR}/../resources
TOKEN=$(getApiToken "${PROJECT_ID}" "${API_KEY}")
Comment thread
stanbrub marked this conversation as resolved.

echo "Making Deploy POST"
jq --arg hostname "${ACTOR}" --arg plan "${PLAN}" \
'.hostname = $hostname | .type = $plan' adhoc-server-deploy.json > adhoc-server-deploy-final.json
echo "Finished Deploy POST"

echo "Running Deploy API"
RESPONSE=$(curl -s -X POST "https://api.phoenixnap.com/bmc/v1/servers" -H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" -d @adhoc-server-deploy-final.json)

IP_ADDRESS=$(jq -r '.publicIpAddresses[0] // empty' <<< "${RESPONSE}")
DEVICE_ID=$(jq -r '.id // empty' <<< "${RESPONSE}")
if [[ -z "$IP_ADDRESS" || -z "$DEVICE_ID" ]]; then
echo "Failed Getting IP Address and Device ID"
exit 1
else
echo "Got Address ${IP_ADDRESS} and Device Id ${DEVICE_ID}"
fi
popd

echo "Waiting for Server Ready"
STATUS=0
for i in {1..60}; do
STATUS_RESPONSE=$(curl -s -H "Authorization: Bearer ${TOKEN}" "https://api.phoenixnap.com/bmc/v1/servers/${DEVICE_ID}")
SERVER_STATUS=$(echo "${STATUS_RESPONSE}" | jq -r '.status')
if [[ "${SERVER_STATUS}" == "powered-on" ]]; then
if nc -z -w 2 "${IP_ADDRESS}" 22 >/dev/null 2>&1; then
Comment thread
stanbrub marked this conversation as resolved.
STATUS=1
break
fi
fi
sleep 10
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"
if [[ ${STATUS} -eq 0 ]]; then
echo "Failed to provision device ${ACTOR} after ${DURATION} seconds"
echo "Last provision attempt status: ${SERVER_STATUS}"
exit 1
fi

Expand All @@ -119,23 +154,50 @@ if [[ ${ACTION} == "deploy-metal" ]]; then
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
# Delete a bare metal server with the given id
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
PROJECT_ID=$3
DEVICE_ID=$4
DEVICE_NAME=$5

TOKEN=$(getApiToken "${PROJECT_ID}" "${API_KEY}")
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getApiToken function is called but the token is not validated. Same issue as in deploy-metal: if authentication fails, TOKEN will be "null" or empty, causing the delete operation to fail silently or with a cryptic error.

Copilot uses AI. Check for mistakes.
echo "Deleting Server ${DEVICE_NAME}"
deleteMetal ${TOKEN} ${DEVICE_ID} ${DEVICE_NAME}

echo "ACTION=${ACTION}" | tee -a ${OUTPUT_NAME}
Comment thread
stanbrub marked this conversation as resolved.
echo "DEVICE_NAME=${DEVICE_NAME}" | tee -a ${OUTPUT_NAME}
echo "DEVICE_ID=${DEVICE_ID}" | tee -a ${OUTPUT_NAME}
fi


# Purge all ephemeral metal that's past its expiration date
if [[ ${ACTION} == "purge-metal" ]]; then
API_KEY=$2
PROJECT_ID=$3
EXPIRATION_HOURS=24
Comment thread
stanbrub marked this conversation as resolved.

echo "Starting Ephemeral Server Cleanup"
echo "Max Hours to Expiration: ${EXPIRATION_HOURS}"
TOKEN=$(getApiToken "${PROJECT_ID}" "${API_KEY}")
THRESHOLD=$(( EXPIRATION_HOURS * 3600 ))
NOW=$(date +%s)

servers=$(curl -s -H "Authorization: Bearer ${TOKEN}" https://api.phoenixnap.com/bmc/v1/servers)
Comment thread
stanbrub marked this conversation as resolved.
echo "$servers" | jq -c '.[]' | while read server; do
id=$(echo "$server" | jq -r '.id')
name=$(echo "$server" | jq -r '.hostname')
created=$(echo "$server" | jq -r '.provisionedOn')
[ "$created" = "null" ] && continue
created_epoch=$(date -d "$created" +%s)
age_seconds=$(( NOW - created_epoch ))
echo "Found Server $name Aged $(( age_seconds / 3600 )) Hours"

if [[ "$name" == "${SERVER_NAME_PREFIX}"* ]] && (( age_seconds > THRESHOLD )); then
deleteMetal ${TOKEN} $id $name
fi
done
echo "ACTION=${ACTION}" | tee -a ${OUTPUT_NAME}
fi

12 changes: 7 additions & 5 deletions .github/scripts/build-benchmark-artifact-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ set -o errexit
set -o pipefail
set -o nounset

# Copyright (c) 2023-2026 Deephaven Data Labs and Patent Pending

# Build benchmark artifact on the remote side
# Assumes git branch is available and docker is running

HOST=`hostname`
GIT_DIR=/root/git/benchmark
RUN_DIR=/root/run
DEEPHAVEN_DIR=/root/deephaven
GIT_DIR=${HOME}/git/benchmark
RUN_DIR=${HOME}/run
DEEPHAVEN_DIR=${HOME}/deephaven

if [ ! -d "${GIT_DIR}" ]; then
echo "$0: Missing one or more Benchmark setup directories"
Expand All @@ -28,10 +30,10 @@ mvn verify
title "-- Cleanup After Build --"
cd ${DEEPHAVEN_DIR};
docker compose down
rm -f data/*.*
sudo rm -f data/*.*

title "-- Copying Artifact and Tests to Run Directory --"
rm -rf ${RUN_DIR}
sudo rm -rf ${RUN_DIR}
mkdir -p ${RUN_DIR}/
cp ${GIT_DIR}/target/deephaven-benchmark-*.jar ${RUN_DIR}/
mv ${RUN_DIR}/deephaven-benchmark-*-tests.jar ${RUN_DIR}/standard-tests.jar
Expand Down
6 changes: 4 additions & 2 deletions .github/scripts/build-docker-image-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
set -o errexit
set -o pipefail

# Copyright (c) 2023-2026 Deephaven Data Labs and Patent Pending

# Build a local docker image on the remote side
# Ensure the docker image is running in the Deephaven directory

HOST=`hostname`
GIT_DIR=/root/git
DEEPHAVEN_DIR=/root/deephaven
GIT_DIR=${HOME}/git
DEEPHAVEN_DIR=${HOME}/deephaven
DEEPHAVEN_VERSION_FILE=${GIT_DIR}/deephaven-core/build/version

if [ ! -d "${DEEPHAVEN_DIR}" ]; then
Expand Down
6 changes: 3 additions & 3 deletions .github/scripts/build-server-distribution-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -o errexit
set -o pipefail

# Copyright (c) 2023-2024 Deephaven Data Labs and Patent Pending
# Copyright (c) 2023-2026 Deephaven Data Labs and Patent Pending

# Assemble the Deephaven server artifacts on the remote side if needed
# The supplied argument can be an image name or <owner>::<branch>
Expand All @@ -15,8 +15,8 @@ if [[ $# != 1 ]]; then
fi

HOST=`hostname`
GIT_DIR=/root/git
DEEPHAVEN_DIR=/root/deephaven
GIT_DIR=${HOME}/git
DEEPHAVEN_DIR=${HOME}/deephaven
DOCKER_IMG=$1
BRANCH_DELIM=":"
BUILD_JAVA=temurin-17-jdk-amd64
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/fetch-results-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ RUN_TYPE=$4
ACTOR=$5
SET_LABEL=${6:-$(echo -n "set-"; ${SCRIPT_DIR}/base.sh $(date +%s%03N) 62)}
DOCKER_IMG=$7
RUN_DIR=/root/run
RUN_DIR=/home/${USER}/run
OUTPUT_NAME=fetch-results-local.out

rm -f ${OUTPUT_NAME}; touch ${OUTPUT_NAME}
Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/manage-deephaven-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -o errexit
set -o pipefail

# Copyright (c) 2023-2024 Deephaven Data Labs and Patent Pending
# Copyright (c) 2023-2026 Deephaven Data Labs and Patent Pending

# Start or Stop a Deephaven image based on the given directive and image/branch name
# The directives argument can be start or stop
Expand All @@ -18,7 +18,7 @@ DIRECTIVE=$1
DOCKER_IMG=$2
CONFIG_OPTS="${@:3}"
HOST=`hostname`
DEEPHAVEN_DIR=/root/deephaven
DEEPHAVEN_DIR=${HOME}/deephaven

if [ ! -d "${DEEPHAVEN_DIR}" ]; then
echo "$0: Missing one or more Benchmark setup directories"
Expand Down
Loading