mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
fix(ci): unblock e2e-s3tests startup and create disk dirs for distributed volumes (#4768)
The scheduled e2e-s3tests sweep failed at "Wait for RustFS ready" in both topologies because the server never started (issue #4762). Two independent startup faults, both surfaced now that the local physical-disk-independence guard is enforced: - single: RUSTFS_VOLUMES=/data/rustfs{0...3} all live on one physical device on the runner, so the guard aborts startup. Set the CI-sanctioned RUSTFS_UNSAFE_BYPASS_DISK_CHECK=true (what the guard's own error message and the e2e tests already use). - multi: the entrypoint's process_data_volumes skipped every non-absolute entry, so the distributed URL form "http://rustfs{1...4}:9000/data/rustfs{0...3}" never created /data/rustfs0..3. LocalDisk init then aborts with VolumeNotFound because resolve_local_disk_root no longer auto-creates the disk root. This also broke the shipped .docker/compose/docker-compose.cluster.yaml for real distributed docker deployments. entrypoint.sh now: 1. Expands multiple {N...M} ranges per token (the URL form carries two). The previous single-pass expander collapsed it to "http://rustfs1" and dropped the disk path; it now re-scans until no ranges remain, operating on only the first brace to keep multi-range tokens intact. 2. Creates the local filesystem path for URL-form endpoints (stripping scheme://host:port) without appending them as CLI args — rustfs reads the distributed form from RUSTFS_VOLUMES directly. Absolute-path and default (/data) inputs expand byte-identically to before. The multi compose also gets the CI disk-check bypass, since the four disks share one device inside each node's container.
This commit is contained in:
@@ -174,6 +174,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
docker network inspect rustfs-net >/dev/null 2>&1 || docker network create rustfs-net
|
docker network inspect rustfs-net >/dev/null 2>&1 || docker network create rustfs-net
|
||||||
docker rm -f rustfs-single >/dev/null 2>&1 || true
|
docker rm -f rustfs-single >/dev/null 2>&1 || true
|
||||||
|
# The four disks share one physical device on the runner (a single
|
||||||
|
# loopback filesystem), so the local physical-disk-independence guard
|
||||||
|
# would refuse to start. Bypass it — this is the CI use case the guard
|
||||||
|
# explicitly sanctions via RUSTFS_UNSAFE_BYPASS_DISK_CHECK.
|
||||||
docker run -d --name rustfs-single \
|
docker run -d --name rustfs-single \
|
||||||
--network rustfs-net \
|
--network rustfs-net \
|
||||||
-p "${S3_PORT}:9000" \
|
-p "${S3_PORT}:9000" \
|
||||||
@@ -181,6 +185,7 @@ jobs:
|
|||||||
-e RUSTFS_ACCESS_KEY="${S3_ACCESS_KEY}" \
|
-e RUSTFS_ACCESS_KEY="${S3_ACCESS_KEY}" \
|
||||||
-e RUSTFS_SECRET_KEY="${S3_SECRET_KEY}" \
|
-e RUSTFS_SECRET_KEY="${S3_SECRET_KEY}" \
|
||||||
-e RUSTFS_VOLUMES="/data/rustfs{0...3}" \
|
-e RUSTFS_VOLUMES="/data/rustfs{0...3}" \
|
||||||
|
-e RUSTFS_UNSAFE_BYPASS_DISK_CHECK=true \
|
||||||
-v /tmp/rustfs-single:/data \
|
-v /tmp/rustfs-single:/data \
|
||||||
rustfs-ci
|
rustfs-ci
|
||||||
|
|
||||||
@@ -200,6 +205,10 @@ jobs:
|
|||||||
RUSTFS_ACCESS_KEY: ${S3_ACCESS_KEY}
|
RUSTFS_ACCESS_KEY: ${S3_ACCESS_KEY}
|
||||||
RUSTFS_SECRET_KEY: ${S3_SECRET_KEY}
|
RUSTFS_SECRET_KEY: ${S3_SECRET_KEY}
|
||||||
RUSTFS_VOLUMES: "http://rustfs{1...4}:9000/data/rustfs{0...3}"
|
RUSTFS_VOLUMES: "http://rustfs{1...4}:9000/data/rustfs{0...3}"
|
||||||
|
# Each node's four disks share one physical device inside its
|
||||||
|
# container, so bypass the local physical-disk-independence guard
|
||||||
|
# (the CI use case it explicitly sanctions).
|
||||||
|
RUSTFS_UNSAFE_BYPASS_DISK_CHECK: "true"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
rustfs1:
|
rustfs1:
|
||||||
|
|||||||
+60
-31
@@ -191,43 +191,72 @@ process_data_volumes() {
|
|||||||
# Convert comma/tab to space
|
# Convert comma/tab to space
|
||||||
VOLUME_LIST_RAW=$(echo "$VOLUME_RAW" | tr ',\t' ' ')
|
VOLUME_LIST_RAW=$(echo "$VOLUME_RAW" | tr ',\t' ' ')
|
||||||
|
|
||||||
VOLUME_LIST=""
|
# Manually expand {N...M} ranges since sh doesn't support brace expansion on
|
||||||
for vol in $VOLUME_LIST_RAW; do
|
# variables. A single token can carry MORE than one range — the distributed
|
||||||
# Helper to manually expand {N..M} since sh doesn't support it on variables
|
# form "http://rustfs{1...4}:9000/data/rustfs{0...3}" has two — so expand the
|
||||||
if echo "$vol" | grep -E -q "\{[0-9]+\.\.\.?[0-9]+\}"; then
|
# FIRST range in each token and re-scan until no ranges remain. Operating on
|
||||||
PREFIX=${vol%%\{*}
|
# only the first brace (via #*{ / %%}* rather than ##*} / %}) is what keeps
|
||||||
SUFFIX=${vol##*\}}
|
# multi-range tokens intact; the previous single-pass expander collapsed them
|
||||||
RANGE=${vol#*\{}
|
# to "http://rustfs1" and silently dropped the disk path.
|
||||||
RANGE=${RANGE%\}}
|
VOLUME_LIST="$VOLUME_LIST_RAW"
|
||||||
RANGE=$(echo "$RANGE" | sed 's/\.\.\./../')
|
while echo "$VOLUME_LIST" | grep -E -q "\{[0-9]+\.\.\.?[0-9]+\}"; do
|
||||||
START=${RANGE%%..*}
|
NEXT_LIST=""
|
||||||
END=${RANGE##*..}
|
for vol in $VOLUME_LIST; do
|
||||||
|
if echo "$vol" | grep -E -q "\{[0-9]+\.\.\.?[0-9]+\}"; then
|
||||||
# Check if START and END are numbers
|
PREFIX=${vol%%\{*}
|
||||||
if [ "$START" -eq "$START" ] 2>/dev/null && [ "$END" -eq "$END" 2>/dev/null ]; then
|
REST=${vol#*\}}
|
||||||
i=$START
|
RANGE=${vol#*\{}
|
||||||
while [ "$i" -le "$END" ]; do
|
RANGE=${RANGE%%\}*}
|
||||||
VOLUME_LIST="$VOLUME_LIST ${PREFIX}${i}${SUFFIX}"
|
RANGE=$(echo "$RANGE" | sed 's/\.\.\./../')
|
||||||
i=$((i+1))
|
START=${RANGE%%..*}
|
||||||
done
|
END=${RANGE##*..}
|
||||||
else
|
|
||||||
# Fallback if not numbers
|
# Check if START and END are numbers
|
||||||
VOLUME_LIST="$VOLUME_LIST $vol"
|
if [ "$START" -eq "$START" ] 2>/dev/null && [ "$END" -eq "$END" 2>/dev/null ]; then
|
||||||
fi
|
i=$START
|
||||||
else
|
while [ "$i" -le "$END" ]; do
|
||||||
VOLUME_LIST="$VOLUME_LIST $vol"
|
NEXT_LIST="$NEXT_LIST ${PREFIX}${i}${REST}"
|
||||||
fi
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Fallback if not numbers
|
||||||
|
NEXT_LIST="$NEXT_LIST $vol"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
NEXT_LIST="$NEXT_LIST $vol"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
VOLUME_LIST="$NEXT_LIST"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# CREATE_DIRS holds every local filesystem path that must exist before
|
||||||
|
# startup. DATA_VOLUMES holds only the paths that are also appended as CLI
|
||||||
|
# args (bare absolute paths). Distributed URL-form endpoints are read from
|
||||||
|
# RUSTFS_VOLUMES by rustfs directly, so they must NOT be appended as args,
|
||||||
|
# but their local path component still has to exist on disk — otherwise
|
||||||
|
# LocalDisk init aborts with VolumeNotFound (rustfs no longer auto-creates
|
||||||
|
# the disk root).
|
||||||
|
CREATE_DIRS=""
|
||||||
for vol in $VOLUME_LIST; do
|
for vol in $VOLUME_LIST; do
|
||||||
case "$vol" in
|
case "$vol" in
|
||||||
/*) DATA_VOLUMES="$DATA_VOLUMES $vol" ;;
|
/*)
|
||||||
*) : ;; # skip non-absolute paths (including http(s):// URLs)
|
DATA_VOLUMES="$DATA_VOLUMES $vol"
|
||||||
|
CREATE_DIRS="$CREATE_DIRS $vol"
|
||||||
|
;;
|
||||||
|
*://*)
|
||||||
|
# e.g. http://node0:9000/data/rustfs0 -> /data/rustfs0
|
||||||
|
vol_rest=${vol#*://}
|
||||||
|
case "$vol_rest" in
|
||||||
|
*/*) CREATE_DIRS="$CREATE_DIRS /${vol_rest#*/}" ;;
|
||||||
|
*) : ;; # URL without a path component; nothing local to create
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*) : ;; # skip anything else we don't recognize
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Initializing data directories:$DATA_VOLUMES"
|
echo "Initializing data directories:$CREATE_DIRS"
|
||||||
for vol in $DATA_VOLUMES; do
|
for vol in $CREATE_DIRS; do
|
||||||
if [ ! -d "$vol" ]; then
|
if [ ! -d "$vol" ]; then
|
||||||
echo " mkdir -p $vol"
|
echo " mkdir -p $vol"
|
||||||
mkdir -p "$vol"
|
mkdir -p "$vol"
|
||||||
|
|||||||
Reference in New Issue
Block a user