autoNAS / scripts / autonas-sync-systemd-ordering.sh
5bf8614 3 months ago History
1 contributor
128 lines | 3.361kb
#!/bin/bash

set -euo pipefail

CONFIG_FILE="${AUTONAS_CONFIG_FILE:-/etc/pve/autonas/disks.conf}"
STORAGE_CFG="${AUTONAS_STORAGE_CFG:-/etc/pve/storage.cfg}"
DROPIN_DIR="/etc/systemd/system/nfs-server.service.d"
DROPIN_FILE="${DROPIN_DIR}/50-autonas-self-hosted-proxmox.conf"

require_root() {
    if [[ "${EUID}" -ne 0 ]]; then
        echo "ERROR: this action must be run as root" >&2
        exit 1
    fi
}

collect_local_autonas_ips() {
    [[ -f "${CONFIG_FILE}" ]] || return 0

    local -A current_ip_map=()
    local current_ip=""
    while IFS= read -r current_ip; do
        [[ -n "${current_ip}" ]] && current_ip_map["${current_ip}"]=1
    done < <(ip -o -4 addr show up scope global | awk '{print $4}' | cut -d/ -f1 | sort -u)

    [[ "${#current_ip_map[@]}" -gt 0 ]] || return 0

    local cfg_ip=""
    while IFS=: read -r _ _ cfg_ip _ _ _; do
        [[ -z "${cfg_ip}" || "${cfg_ip}" == "LOCAL" || "${cfg_ip}" == "IMPORT" ]] && continue
        [[ -n "${current_ip_map[${cfg_ip}]:-}" ]] && echo "${cfg_ip}"
    done < <(grep -v '^[[:space:]]*#' "${CONFIG_FILE}" || true)
}

collect_self_hosted_mount_units() {
    [[ -f "${STORAGE_CFG}" ]] || return 0

    local -A local_ip_map=()
    local ip=""
    while IFS= read -r ip; do
        [[ -n "${ip}" ]] && local_ip_map["${ip}"]=1
    done < <(collect_local_autonas_ips)

    [[ "${#local_ip_map[@]}" -gt 0 ]] || return 0

    local -A mount_unit_map=()
    local server=""
    local path=""
    local type=""
    local line=""

    emit_candidate() {
        if [[ "${type}" == "nfs" && -n "${server}" && -n "${path}" && -n "${local_ip_map[${server}]:-}" ]]; then
            mount_unit_map["$(systemd-escape --path --suffix=mount "${path}")"]=1
        fi
    }

    while IFS= read -r line || [[ -n "${line}" ]]; do
        if [[ "${line}" =~ ^[[:space:]]*# ]]; then
            continue
        fi

        if [[ "${line}" =~ ^[[:space:]]*$ ]]; then
            emit_candidate
            type=""
            server=""
            path=""
            continue
        fi

        if [[ ! "${line}" =~ ^[[:space:]] ]]; then
            emit_candidate
            type="${line%%:*}"
            server=""
            path=""
            continue
        fi

        if [[ "${line}" =~ ^[[:space:]]*server[[:space:]]+(.+)$ ]]; then
            server="${BASH_REMATCH[1]}"
            continue
        fi

        if [[ "${line}" =~ ^[[:space:]]*path[[:space:]]+(.+)$ ]]; then
            path="${BASH_REMATCH[1]}"
            continue
        fi
    done < "${STORAGE_CFG}"

    emit_candidate

    printf '%s\n' "${!mount_unit_map[@]}" | sort
}

write_dropin() {
    local units=("$@")

    if [[ "${#units[@]}" -eq 0 ]]; then
        rm -f "${DROPIN_FILE}"
        rmdir "${DROPIN_DIR}" 2>/dev/null || true
        return 0
    fi

    mkdir -p "${DROPIN_DIR}"
    {
        echo "# Managed by AutoNAS."
        echo "# Keep self-hosted Proxmox NFS client mounts ordered before nfs-server shutdown."
        echo "[Unit]"
        printf 'Before='
        printf '%s ' "${units[@]}"
        printf '\n'
    } > "${DROPIN_FILE}"
}

main() {
    require_root

    local units=()
    local unit=""
    while IFS= read -r unit; do
        [[ -n "${unit}" ]] && units+=("${unit}")
    done < <(collect_self_hosted_mount_units)

    write_dropin "${units[@]}"
    systemctl daemon-reload
}

main "$@"