diff --git a/ehdd/start-encrypted.sh b/ehdd/start-encrypted.sh index 5492fc6b..0cd5b644 100755 --- a/ehdd/start-encrypted.sh +++ b/ehdd/start-encrypted.sh @@ -35,5 +35,6 @@ if [ $? -eq 0 ]; then ehdd/postinstall.sh || exit 1 else echo "setup/start.sh failed" + exit 1 fi diff --git a/management/hooks.py b/management/hooks.py index bc286ff7..526bcf3c 100644 --- a/management/hooks.py +++ b/management/hooks.py @@ -20,12 +20,29 @@ log = logging.getLogger(__name__) # update_hook_handlers() for the format # mutex = Lock() +initialized = False handlers = [] -mods_env = {} # dict derived from /etc/mailinabox_mods.conf +mods_env = {} # dict of /etc/mailinabox.conf and /etc/mailinabox_mods.conf def update_hook_handlers(): global handlers, mods_env + + # load /etc/mailinabox.conf and /etc/mailinabox_mods.conf + new_mods_env = load_environment() + if os.path.isfile('/etc/mailinabox_mods.conf'): + load_env_vars_from_file( + '/etc/mailinabox_mods.conf', + strip_quotes=True, + merge_env=new_mods_env + ) + new_handlers= [] + + if 'LOCAL_MODS_DIR' in new_mods_env: + dir = new_mods_env['LOCAL_MODS_DIR'] + if dir not in sys.path: + sys.path.append(dir) + for dir in sys.path: hooks_dir = os.path.join(dir, "management_hooks_d") if not os.path.isdir(hooks_dir): @@ -47,19 +64,11 @@ def update_hook_handlers(): new_handlers = sorted(new_handlers, key=lambda path: path['sort_id']) log.info('%s hook handlers', len(new_handlers)) - # load /etc/mailinabox_mods.conf - new_mods_env = load_environment() - if os.path.isfile('/etc/mailinabox_mods.conf'): - load_env_vars_from_file( - '/etc/mailinabox_mods.conf', - strip_quotes=True, - merge_env=new_mods_env - ) - # update globals mutex.acquire() handlers = new_handlers mods_env = new_mods_env + initialized = True mutex.release() @@ -68,6 +77,9 @@ def exec_hooks(hook_name, data): # contents of which are specific to the type of hook. Handlers may # modify the dictionary to return updates to the caller. + if not initialized: + update_hook_handlers() + mutex.acquire() cur_handlers = handlers cur_mods_env = mods_env diff --git a/setup/functions.sh b/setup/functions.sh index e0d218e7..749c916c 100644 --- a/setup/functions.sh +++ b/setup/functions.sh @@ -317,18 +317,54 @@ say() { echo "$@" } +wait_for_management_daemon() { + local progress="${1:-progress}" # show progress? "progress"/"no-progress" + local max_wait="${2:-60}" # seconds, 0=forever + local start=$(date +%s) + local elapsed=0 now + [ "$max_wait" = "forever" ] && max_wait=0 + + # Wait for the management daemon to start... + until nc -z -w 4 127.0.0.1 10222 + do + now=$(date +%s) + # let returns 1 if the equasion evaluates to zero, which will + # cause the script to exit because of set -e. add one. + [ $now -eq $start ] && let now+=1 + let elapsed="$now - $start" + if [ $max_wait -ne 0 -a $elapsed -gt $max_wait ]; then + echo "Timeout waiting for Mail-in-a-Box management daemon to start" + return 1 + fi + if [ "$progress" = "progress" ]; then + echo Waiting for the Mail-in-a-Box management daemon to start... + fi + sleep 2 + done +} + install_hook_handler() { # this is used by local setup mods to install a hook handler for - # the management daemon + # the management daemon. source /etc/mailinabox.conf before + # calling local handler_file="$1" local dst="${LOCAL_MODS_DIR:-local}/management_hooks_d" - mkdir -p "$dst" - cp "$handler_file" "$dst" - # let the daemon know there's a new hook handler - tools/hooks_update >/dev/null + if [ ! -d "$dst" -o -e "$dst/$(basename "$handler_file")" ]; then + mkdir -p "$dst" + cp "$handler_file" "$dst" + if systemctl is-active --quiet mailinabox; then + systemctl restart mailinabox + wait_for_management_daemon no-progress + fi + else + cp "$handler_file" "$dst" + # let the daemon know there's a new hook handler + tools/hooks_update >/dev/null + fi } remove_hook_handler() { + # source /etc/mailinabox.conf before calling local hook_py=$(basename "$1") local dst="${LOCAL_MODS_DIR:-local}/management_hooks_d/$hook_py" if [ -e "$dst" ]; then diff --git a/setup/management.sh b/setup/management.sh index 385390bd..b2447c69 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -103,7 +103,7 @@ tr -cd '[:xdigit:]' < /dev/urandom | head -c 32 > /var/lib/mailinabox/api.key chmod 640 /var/lib/mailinabox/api.key source $venv/bin/activate -export PYTHONPATH=$(pwd)/management:${LOCAL_MODS_DIR:-$(pwd)/local} +export PYTHONPATH=$(pwd)/management exec gunicorn --log-level ${MGMT_LOG_LEVEL:-info} -b localhost:10222 -w 1 --timeout 630 wsgi:app EOF chmod +x $inst_dir/start diff --git a/setup/start.sh b/setup/start.sh index 50eed4a0..2547ce3b 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -105,6 +105,9 @@ if [ ! -f $STORAGE_ROOT/mailinabox-ldap.version ]; then chown $STORAGE_USER.$STORAGE_USER $STORAGE_ROOT/mailinabox-ldap.version fi +# normalize the directory path for setup mods +LOCAL_MODS_DIR="$(realpath -m "${LOCAL_MODS_DIR:-${DEFAULT_LOCAL_MODS_DIR:-local}}")" + # Save the global options in /etc/mailinabox.conf so that standalone # tools know where to look for data. The default MTA_STS_MODE setting # is blank unless set by an environment variable, but see web.sh for @@ -118,6 +121,7 @@ PUBLIC_IPV6=$PUBLIC_IPV6 PRIVATE_IP=$PRIVATE_IP PRIVATE_IPV6=$PRIVATE_IPV6 MTA_STS_MODE=${DEFAULT_MTA_STS_MODE:-enforce} +LOCAL_MODS_DIR=$LOCAL_MODS_DIR EOF # Start service configuration. @@ -139,11 +143,7 @@ source setup/management-capture.sh source setup/munin.sh # Wait for the management daemon to start... -until nc -z -w 4 127.0.0.1 10222 -do - echo Waiting for the Mail-in-a-Box management daemon to start... - sleep 2 -done +wait_for_management_daemon progress forever # ...and then have it write the DNS and nginx configuration files and start those # services. @@ -174,9 +174,9 @@ fi # # Run setup mods # -if [ -d "${LOCAL_MODS_DIR:-local}" ]; then - for mod in $(ls "${LOCAL_MODS_DIR:-local}" | grep -v '~$'); do - mod_path="${LOCAL_MODS_DIR:-local}/$mod" +if [ -d "$LOCAL_MODS_DIR" ]; then + for mod in $(ls "$LOCAL_MODS_DIR" | grep -v '~$'); do + mod_path="$LOCAL_MODS_DIR/$mod" if [ -f "$mod_path" -a -x "$mod_path" ]; then echo "" echo "Running mod: $mod_path"