#!/bin/ash
# This scripts runs as root and prepares the configuration
# for the dnbd3 server (...)
ERRLOG="/run/dnbd3-proxy.err"
[ -s "$ERRLOG" ] && exit 0 # already ran and failed, don't do it again
. /opt/openslx/bin/slx-tools
. /opt/openslx/config
# Normally, exit unclean to signal to systemd
islocal=
mingb=10
if [ "$SLX_RUNMODE_MODULE" != "dnbd3" ]; then
# But if its local proxy mode, always exit 0 since we don't consider this an error
islocal=true
# Not a dnbd3 proxy, see if we have a large partition to try local caching
if [ "$SLX_DNBD3_SERVERS" = "127.0.0.1" ]; then
# Already been here, do nothing
exit 0
fi
[ "x$SLX_VM_DNBD3" != "xyes" ] && exit 0 # Do not want
[ -z "$SLX_DNBD3_SERVERS" ] && exit 0 # No servers!?
[ -z "$SLX_DNBD3_MIN_GB" ] && exit 0 # Disabled
[ "$SLX_DNBD3_MIN_GB" -ge "$mingb" ] || exit 0 # Disabled
mingb="$SLX_DNBD3_MIN_GB"
fi
# Log error to server and local file in /run.
# The main startup script will check whether this file is > 0 bytes
# and start in errormsg-mode.
errormsg () {
echo "$@" >> "$ERRLOG"
if [ -z "$islocal" ]; then
slxlog -s -e "dnbd3-setup" "$@"
exit 1
fi
exit 0
}
# Get size of disk/device at given path, in GB
disksize () {
local val len
val="$( fs_path_space "$1" )"
val="${val#* }"
len="${#val}"
if [ "$len" -lt 7 ]; then
echo 0
else
echo "${val:0:$(( len - 6 ))}"
fi
}
DNBD3_PORT=5003
# Creates the DNBD3 server configuration under DNBD3_CONF_DIR
DNBD3_CONF_DIR="/etc/dnbd3-server"
if ! mkdir -p "${DNBD3_CONF_DIR}"; then
errormsg "Failed to create '${DNBD3_CONF_DIR}'."
fi
# We prefer ID45 for storage (if >= 10GB), otherwise
# fallback to /tmp if it's persistent and >= 10GB.
# For local caching, /tmp is never used.
d="/opt/openslx/persistent"
dsd="$(disksize "$d")"
e="/tmp"
dse="$(disksize "$e")"
if fs_path_ismountpoint "$d" && [ -k "$d/data" ] && [ "$dsd" -ge "$mingb" ]; then
DNBD3_BASE_DIR="$d/data"
disksize="$dsd"
elif [ -z "$islocal" ] && ! fs_path_isvolatile "$e" && [ "$dse" -ge "$mingb" ]; then
DNBD3_BASE_DIR="$e"
disksize="$dse"
# We're using /tmp, don't warn about low space
touch "/run/openslx/no-ram-warning"
else
errormsg "Neither a persistent part (ID45) nor /tmp (ID44) are available, or they are < ${mingb}GB"
fi
# now try to create the actual folder used by the server
DNBD3_DATA_DIR="${DNBD3_BASE_DIR}/dnbd3"
if ! mkdir -p "${DNBD3_DATA_DIR}"; then
for i in 0 1 2 3 4 5 $RANDOM $RANDOM; do
if mkdir -p "${DNBD3_BASE_DIR}/dnbd3.$i"; then
DNBD3_DATA_DIR="${DNBD3_BASE_DIR}/dnbd3.$i"
break
fi
done
fi
if [ ! -d "${DNBD3_DATA_DIR}" ]; then
errormsg "Failed to create '${DNBD3_BASE_DIR}/dnbd3' or any of the fallback variants"
fi
if ! chown -R dnbd3:dnbd3 "${DNBD3_DATA_DIR}"; then
errormsg "Failed to chown '${DNBD3_DATA_DIR}' to dnbd3."
fi
# user rw, group ro, other nothing
if ! chmod -R o-rwx,u+rwX,g+rX-w "${DNBD3_DATA_DIR}"; then
errormsg "Failed to chmod '${DNBD3_DATA_DIR}' to dnbd3."
fi
# Done with sanity checks, now create configs: server.conf & alt-servers
# Using the information given by the server in /opt/openslx/config
# helper to echo given list of IPs to ${DNBD3_CONF_DIR}/alt-servers
# optionally takes a single char prefix as first param and
# adds it to the IP (for private dnbd3 servers)
# Also sets FOUND_SAT if satellite IP was seen
MY_IPS=$(ip a | grep '^\s*inet\s' | awk '{print $2}')
FOUND_SAT=
add_alt_server() {
local PRE=
if [ "${#1}" = "1" ]; then
PRE="$1"
shift
fi
for ALT in "$@"; do
for ip in $MY_IPS; do
[ "x$ALT" = "x${ip%/*}" ] && return 0 # Ignore self
done
echo "${PRE}${ALT}" >> "${DNBD3_CONF_DIR}/alt-servers"
[ "x${ALT}" = "x${SLX_PXE_SERVER_IP}" ] && FOUND_SAT="oui"
done
return 0
}
rm -f -- "${DNBD3_CONF_DIR}/alt-servers"
# Local caching mode?
if [ -n "$islocal" ]; then
# Local caching mode.
DNBD3_SPARSE="true"
DNBD3_PRETEND_CLIENT="true"
DNBD3_AUTOFREE=0 # Immediately start freeing images when running out of space in local caching mode
if [ -n "$SLX_DNBD3_MIN_GB_HASH" ] && [ "$SLX_DNBD3_MIN_GB_HASH" -gt 0 ] && [ "$disksize" -ge "$SLX_DNBD3_MIN_GB_HASH" ]; then
DNBD3_BGR="hashblock"
else
DNBD3_BGR="false"
fi
DNBD3_LOOKUP="false"
DNBD3_SERVER_PENALTY="500000"
DNBD3_BGR_MIN_CLIENTS=1
MAX_REPLICATION_SIZE=500
# Use DNBD3 servers from openslx config and then patch it to say localhost
add_alt_server '-' ${SLX_DNBD3_SERVERS}
sed -i "s/^SLX_DNBD3_SERVERS=.*$/SLX_DNBD3_SERVERS='127.0.0.1'/" '/opt/openslx/config'
else
# Proxy mode
DNBD3_SPARSE="false"
DNBD3_PRETEND_CLIENT="false"
DNBD3_BGR="false"
DNBD3_BGR_MIN_CLIENTS=0
DNBD3_LOOKUP="false"
DNBD3_AUTOFREE="18h"
DNBD3_SERVER_PENALTY=2000 # no BGR = don't like other servers connecting so much
if [ -n "${SLX_DNBD3_BGR}" ]; then
DNBD3_BGR="true"
DNBD3_SERVER_PENALTY=500 # much better
# Only do chained lookup of image if we're a global proxy with BGR
[ -z "${SLX_DNBD3_WHITELIST}" ] && DNBD3_LOOKUP="true"
fi
if [ -n "${SLX_DNBD3_SPARSE}" ]; then
DNBD3_SPARSE="true"
fi
# Determine if we need sparse mode, or override BGR
if ! [ "$disksize" -gt 120 ]; then
# less than 120GiB or NaN, force
[ "$DNBD3_BGR" = "true" ] && slxlog -s -e "dnbd3-setup-small" "Cache partition < 120GiB, forcing background replication OFF and sparse mode ON"
DNBD3_SPARSE="true"
DNBD3_BGR="false"
DNBD3_SERVER_PENALTY=5000
DNBD3_LOOKUP="false"
elif [ "$disksize" -gt 2000 ]; then
# force non-sparse on > 2TiB
DNBD3_SPARSE="false"
fi
MAX_REPLICATION_SIZE=$(( disksize / 6 ))
[ "$MAX_REPLICATION_SIZE" -lt 100 ] && MAX_REPLICATION_SIZE=100
add_alt_server ${SLX_DNBD3_PUBLIC}
add_alt_server '-' ${SLX_DNBD3_PRIVATE}
rm -f "/opt/openslx/iptables/rules.d/99-dnbd3"
# now create iptables helper rules
if [ -n "${SLX_DNBD3_WHITELIST}" ] && [ "${SLX_DNBD3_WHITELIST%/*}" != "${SLX_DNBD3_WHITELIST}" ]; then
# XXX: Remove the second check above after ~ 2018-10-01 -- it's a workaround for broken slx-admin
# that won't properly calculate CIDR notion resulting in a severely locked down proxy :(
DNBD3_IPTABLES_CONF="$(mktemp)"
echo '#!/bin/ash' > "${DNBD3_IPTABLES_CONF}"
for CIDR in ${SLX_DNBD3_WHITELIST} ${SLX_KCL_SERVERS}; do
echo "iptables -I ipt-helper-INPUT 1 -p tcp -s ${CIDR} --dport ${DNBD3_PORT} -j ACCEPT"
done >> "${DNBD3_IPTABLES_CONF}"
echo "iptables -A ipt-helper-INPUT -p tcp --dport ${DNBD3_PORT} -j REJECT" >> "${DNBD3_IPTABLES_CONF}"
chmod +x "${DNBD3_IPTABLES_CONF}"
mv -f "$DNBD3_IPTABLES_CONF" "/opt/openslx/iptables/rules.d/99-dnbd3"
fi
(
echo "*******************"
echo "*** DNBD3 Proxy ***"
echo "*******************"
) | tee -a "/etc/issue" -a "/etc/issue.net" >> "/opt/openslx/etc/issue.template"
# Create a crontab for rebooting - if everything is fine, once a weekend,
# on failure, reboot every night, hoping things will get better (...)
M=$(( RANDOM % 60 ))
H=$(( RANDOM % 5 ))
if [ -s "$ERRLOG" ]; then
W="*"
else
W="0"
fi
cat > "/etc/cron.d/dnbd3-reboot" <<EOF
# OpenSLX: Reboot proxy at night
SHELL=/bin/ash
PATH=/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin
$M $H * * $W root reboot
EOF
#
fi
rm -f "${DNBD3_CONF_DIR}/server.conf"
# Refer to http://git.openslx.org/dnbd3.git/tree/conf for configuration options
cat << EOF > "${DNBD3_CONF_DIR}/server.conf"
[dnbd3]
listenPort=${DNBD3_PORT}
basePath=${DNBD3_DATA_DIR}
serverPenalty=${DNBD3_SERVER_PENALTY}
clientPenalty=0
isProxy=true
backgroundReplication=${DNBD3_BGR}
bgrMinClients=${DNBD3_BGR_MIN_CLIENTS}
bgrWindowSize=1
lookupMissingForProxy=${DNBD3_LOOKUP}
sparseFiles=${DNBD3_SPARSE}
removeMissingImages=false
uplinkTimeout=5000
clientTimeout=15000
pretendClient=${DNBD3_PRETEND_CLIENT}
autoFreeDiskSpaceDelay=${DNBD3_AUTOFREE}
[limits]
maxPayload=10M
maxReplicationSize=${MAX_REPLICATION_SIZE}G
[logging]
consoleMask=ERROR WARNING MINOR INFO
EOF
# Extra overrides - make this proerly ini aware some day. For now we don't
# have any name clashes between the ini sections so this works
for item in $SLX_DNBD3_EXTRA; do # space sep
item="${item#*.}"
key="${item%%=*}"
val="${item#*=}"
sed -i "s/^${key}=.*$/${key}=${val}/" "${DNBD3_CONF_DIR}/server.conf"
done
# To this day, only the sat IP is in SLX_KCL_SERVERS afaik
[ -z "${FOUND_SAT}" ] && add_alt_server ${SLX_KCL_SERVERS}
chmod -R a+Xr "${DNBD3_CONF_DIR}"
# create rpc.acl to allow the satellite only
rm -f "${DNBD3_CONF_DIR}/rpc.acl"
for SRV in ${SLX_KCL_SERVERS}; do
echo "$SRV ALL"
done >> "${DNBD3_CONF_DIR}/rpc.acl"
# And self
echo "127.0.0.1 STATS IMAGE_LIST" >> "${DNBD3_CONF_DIR}/rpc.acl"
if [ -n "$islocal" ]; then
# Prepare, so dnbd3-server will be launched with -m
mkdir -p /mnt/dnbd3
chown dnbd3:dnbd3 /mnt/dnbd3
adduser dnbd3 fuse
# Start service, is not symlinked when not in proxy mode
systemctl --no-block start dnbd3-proxy.service
fi
exit 0