forked from tianon/docker-moosefs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
3 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
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
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"] |
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
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 |
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
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 "$@" |