Skip to content

Commit

Permalink
Add 4.x πŸ‘€
Browse files Browse the repository at this point in the history
Not making this `latest` yet, but getting started with something.  I think I need some better tests here, especially for my shell code. πŸ€”
  • Loading branch information
tianon committed Sep 19, 2024
1 parent 8596fb2 commit a927413
Show file tree
Hide file tree
Showing 3 changed files with 305 additions and 0 deletions.
129 changes: 129 additions & 0 deletions 4/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
FROM debian:bookworm-slim

RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
# mfscli (and cgi) are Python-based
python3 \
# mfsmount needs "fusermount"
fuse \
; \
rm -rf /var/lib/apt/lists/*; \
# allow running mfsmount as non-root
grep '^#user_allow_other$' /etc/fuse.conf; \
sed -ri 's/^#user_allow_other$/user_allow_other/' /etc/fuse.conf; \
grep '^user_allow_other$' /etc/fuse.conf

RUN set -eux; \
groupadd \
--gid 9400 \
--system \
mfs \
; \
useradd \
--comment 'MooseFS' \
--gid mfs \
--home-dir /var/lib/mfs \
--no-create-home \
--system \
--uid 9400 \
mfs \
; \
mkdir /var/lib/mfs; \
chown mfs:mfs /var/lib/mfs; \
id mfs

# https://github.com/moosefs/moosefs/releases
ENV MOOSEFS_VERSION 4.56.5

RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
wget \
\
dpkg-dev \
file \
gcc \
libc6-dev \
libfuse-dev \
libpcap-dev \
make \
pkg-config \
zlib1g-dev \
; \
rm -rf /var/lib/apt/lists/*; \
\
wget -O moosefs.tgz "https://github.com/moosefs/moosefs/archive/v${MOOSEFS_VERSION}.tar.gz"; \
mkdir /usr/local/src/moosefs; \
tar --extract \
--file moosefs.tgz \
--directory /usr/local/src/moosefs \
--strip-components 1 \
; \
rm moosefs.tgz; \
\
( \
cd /usr/local/src/moosefs; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--disable-static \
--enable-option-checking=fatal \
--localstatedir=/var/lib \
--sysconfdir=/etc \
--with-default-group=mfs \
--with-default-user=mfs \
; \
); \
make -C /usr/local/src/moosefs -j "$(nproc)"; \
make -C /usr/local/src/moosefs install; \
ldconfig; \
rm -rf /usr/local/src/moosefs; \
\
# prep the default configuration so things generally work Out-of-the-Box
chown -R mfs:mfs /etc/mfs; \
for sample in /etc/mfs/*.sample; do \
cfg="${sample%.sample}"; \
[ -s "$cfg" ] || cp -avT "$sample" "$cfg"; \
done; \
cp -avT /etc/mfs /etc/mfs.sample; \
rm -v /etc/mfs.sample/*.sample; \
cp -avT /var/lib/mfs /var/lib/mfs.sample; \
cp -avT /var/lib/mfs/metadata.mfs.empty /var/lib/mfs/metadata.mfs; \
\
# allow us to run as an arbitrary user but still modify configuration
chmod 777 /etc/mfs; \
chmod 1777 /var/lib/mfs; \
\
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \
| sort -u \
| xargs -r dpkg-query --search 2>/dev/null \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
mfsmount --version; \
mfscli -v; \
mfschunkserver -v; \
mfsmaster -v; \
mfschunktool -v; \
mfsmetalogger -v

RUN set -eux; \
# prep a scratch space with appropriate permissions to be able to do quick prototyping Out-of-the-Box
mkdir /mnt/mfs; \
chown mfs:mfs /mnt/mfs

# without this, the Python-based mfscli "-f" flag refuses to use UTF-8 box-drawing characters
ENV LANG=C.UTF-8

COPY docker-entrypoint.sh docker-chunkservers.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["bash"]
142 changes: 142 additions & 0 deletions 4/docker-chunkservers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env bash
set -Eeuo pipefail

chunkservers="${MFS_CHUNKSERVERS:?set MFS_CHUNKSERVERS to the base directory of all chunkservers}"
cd "$chunkservers"

temp="$(mktemp -d)"
trap "$(printf 'rm -rf %q' "$temp")" EXIT

# if "ALLOW_STARTING_WITH_INVALID_DISKS" isn't set, let's change the default from 0 to 1
# (otherwise, a chunkserver with invalid disks stops ALL our chunkservers from starting)
: "${MFSCHUNKSERVER_ALLOW_STARTING_WITH_INVALID_DISKS:=1}"
export MFSCHUNKSERVER_ALLOW_STARTING_WITH_INVALID_DISKS

copy_etc() {
local dir="$1"; shift
cp -aT /etc/mfs "$dir"
find "$dir" -type f -exec sed -ri "s!/etc/mfs!$dir!g" '{}' +
}

declare -A pids=() cfgs=()

all_still_up() {
local name pid cfg
for name in "${!pids[@]}"; do
pid="${pids["$name"]}"
if [ ! -d "/proc/$pid" ]; then
if cfg="${cfgs["$name"]:-}" && [ -n "$cfg" ] && [ ! -s "$cfg" ]; then
# if a process is dead, and we had a config file but it's now empty or gone, we should ignore this process (was probably a removed drive/server)
unset pids["$name"] cfgs["$name"]
continue
fi
return 1
fi
done
if [ "${#pids[@]}" -eq 0 ]; then
# if we've emptied the full list of processes, we're not "up" anymore :)
return 1
fi
return 0
}
any_still_up() {
local pid
for pid in "${pids[@]}"; do
if [ -d "/proc/$pid" ]; then
return 0
fi
done
return 1
}
kill_all() {
local pid
for pid in "${pids[@]}"; do
if [ -d "/proc/$pid" ]; then
# try to make sure the process is still running before signalling it to avoid "pid X doesn't exist" over and over again if one is hung and we're trying to stop
kill "$@" "$pid"
fi
done
}
end_session() {
while any_still_up; do
kill_all
sleep 1
# TODO timeout?
done
exit "$@"
}
hup_all() {
if any_still_up; then
kill_all -HUP
fi
}
trap 'end_session 0' ABRT ALRM INT KILL PIPE QUIT STOP TERM USR1 USR2
trap 'end_session 1' ERR
trap 'hup_all' HUP

# backwards compatibility
for cfg in */mfshdd.cfg; do
[ -f "$cfg" ] || continue
dir="$(dirname "$cfg")"
new="$dir-mfshdd.cfg"
if [ ! -f "$new" ]; then
mv -vT "$cfg" "$new"
fi
done

# auto-detect and prepare new chunkservers
for chunks in */chunks/; do
chunks="${chunks%/}"
[ -d "$chunks" ] || continue
dir="$(dirname "$chunks")"
cfg="$dir-mfshdd.cfg"
if [ ! -s "$cfg" ]; then
readlink -ve "$chunks" >> "$cfg"
fi
done

port='9422'
for cfg in *-mfshdd.cfg; do
[ -f "$cfg" ] || continue

base="${cfg%-mfshdd.cfg}"
name="$(basename "$base")"
dir="$(dirname "$base")"

var="$dir/.var-lib-mfs-$name"
if [ ! -d "$var" ]; then
if [ -d "$dir/$name/var-lib-mfs" ]; then
# backwards compatibility
mv -vT "$dir/$name/var-lib-mfs" "$var"
else
# pre-seed our new state directory with the standard "empty" contents
cp -aT /var/lib/mfs "$var"
chmod 755 "$var" || :
fi
fi

copy_etc "$temp/$name"

sed -r "s!/etc/mfs!$temp/$name!g" /usr/local/bin/docker-entrypoint.sh > "$temp/$name/entrypoint.sh"
chmod +x "$temp/$name/entrypoint.sh"

cfg="$(readlink -ve "$cfg")"
var="$(readlink -ve "$var")"
MFSCHUNKSERVER_CSSERV_LISTEN_PORT="$port" \
MFSCHUNKSERVER_SYSLOG_IDENT="$name" \
MFSCHUNKSERVER_HDD_CONF_FILENAME="$cfg" \
MFSCHUNKSERVER_DATA_PATH="$var" \
"$temp/$name/entrypoint.sh" \
mfschunkserver -func "$temp/$name/mfschunkserver.cfg" &
pid="$!"
pids["$name"]="$pid"
cfgs["$name"]="$cfg"

(( port++ )) || :
all_still_up || end_session 1
done

while any_still_up; do
all_still_up || end_session 1
sleep 5
done
34 changes: 34 additions & 0 deletions 4/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -Eeuo pipefail

# see http://stackoverflow.com/a/2705678/433558
sed_escape_lhs() {
sed -e 's/[]\/$*.^|[]/\\&/g' <<<"$*"
}
sed_escape_rhs() {
sed -e 's/[\/&]/\\&/g' <<<"$*"
}

# magic with environment variables
for cfg in \
/etc/mfs/mfschunkserver.cfg \
/etc/mfs/mfsmaster.cfg \
/etc/mfs/mfsmetalogger.cfg \
; do
base="$(basename "$cfg" '.cfg')" # "mfsmaster", etc
base="${base^^}_" # "MFSMASTER_"
eval 'envs=( "${!'"$base"'@}" )' # envs=( "${!MFSMASTER_@}" )
for env in "${envs[@]}"; do
var="${env#$base}" # "HDD_CONF_FILENAME"
val="${!env}" # "/mnt/mfs/mfshdd.cfg"
sedVar="$(sed_escape_lhs "$var")"
sedVal="$(sed_escape_rhs "$val")"
sed -ri -e 's/^([[:space:]]*#)?[[:space:]]*('"$sedVar"')[[:space:]]*=.*$/\2 = '"$sedVal"'/' "$cfg"
if ! grep -qE "^$sedVar =" "$cfg"; then
echo >&2 "warning: $var ($env) was not found in '$cfg' (so might be a typo!)"
{ echo; echo "$var = $val"; } >> "$cfg"
fi
done
done

exec "$@"

0 comments on commit a927413

Please sign in to comment.