#!/bin/bash set -euo pipefail PROJECT_ID="thunderbolts" ORG_ID="xdev" INSTALL_DIR="/usr/local/lib/${ORG_ID}/${PROJECT_ID}" DOC_DIR="/usr/local/share/doc/${ORG_ID}/${PROJECT_ID}" RECOVER_CANONICAL="${INSTALL_DIR}/tb-recover.sh" RECOVER_WRAPPER="/usr/local/sbin/tb-recover.sh" UNINSTALL_PATH="${INSTALL_DIR}/uninstall.sh" UNINSTALL_WRAPPER="/usr/local/sbin/${ORG_ID}-${PROJECT_ID}-uninstall" UDEV_RULE_PATH="/etc/udev/rules.d/90-thunderbolt-net-systemd.rules" TB_BRIDGE_UNIT="/etc/systemd/system/tb-bridge.service" TB_ENLIST_UNIT="/etc/systemd/system/tb-enlist@.service" TB_RECOVER_UNIT="/etc/systemd/system/tb-recover.service" TB_RECOVER_TIMER="/etc/systemd/system/tb-recover.timer" SOURCE_DIR="" usage() { cat <] Install shared thunderbolt runtime artifacts on the current host. This workflow does NOT modify /etc/network/interfaces or interfaces.d/10-thunderbolt. EOF } require_root() { if [[ "${EUID}" -ne 0 ]]; then echo "ERROR: this script must be run as root" >&2 exit 1 fi } resolve_source_dir() { if [[ -n "${SOURCE_DIR}" ]]; then SOURCE_DIR="$(cd "${SOURCE_DIR}" && pwd)" else SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" fi } validate_source_tree() { local required_files=( "${SOURCE_DIR}/deploy/attempt1/common/sbin/tb-recover.sh" "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-bridge.service" "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-enlist@.service" "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-recover.service" "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-recover.timer" "${SOURCE_DIR}/deploy/attempt1/common/udev/rules.d/90-thunderbolt-net-systemd.rules" "${SOURCE_DIR}/scripts/uninstall.sh" "${SOURCE_DIR}/README.md" "${SOURCE_DIR}/INSTALL.md" "${SOURCE_DIR}/CHANGELOG.md" ) local file="" for file in "${required_files[@]}"; do if [[ ! -f "${file}" ]]; then echo "ERROR: missing required source file: ${file}" >&2 exit 1 fi done } run_existing_uninstall() { if [[ -x "${UNINSTALL_PATH}" ]]; then echo "Existing installation detected. Running canonical uninstall first..." "${UNINSTALL_PATH}" --force || true else bash "${SOURCE_DIR}/scripts/uninstall.sh" --force || true fi } install_docs() { mkdir -p "${DOC_DIR}" cp "${SOURCE_DIR}/README.md" "${DOC_DIR}/" cp "${SOURCE_DIR}/INSTALL.md" "${DOC_DIR}/" cp "${SOURCE_DIR}/CHANGELOG.md" "${DOC_DIR}/" } main() { while [[ $# -gt 0 ]]; do case "$1" in --source-dir) SOURCE_DIR="$2" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "ERROR: unknown option: $1" >&2 usage exit 1 ;; esac done require_root resolve_source_dir validate_source_tree echo "=== Installing ${PROJECT_ID} shared runtime ===" run_existing_uninstall mkdir -p "${INSTALL_DIR}" "${DOC_DIR}" /usr/local/sbin /etc/udev/rules.d /etc/systemd/system install -m 0755 "${SOURCE_DIR}/deploy/attempt1/common/sbin/tb-recover.sh" "${RECOVER_CANONICAL}" ln -sfn "${RECOVER_CANONICAL}" "${RECOVER_WRAPPER}" install -m 0755 "${SOURCE_DIR}/scripts/uninstall.sh" "${UNINSTALL_PATH}" ln -sfn "${UNINSTALL_PATH}" "${UNINSTALL_WRAPPER}" install -m 0644 "${SOURCE_DIR}/deploy/attempt1/common/udev/rules.d/90-thunderbolt-net-systemd.rules" "${UDEV_RULE_PATH}" install -m 0644 "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-bridge.service" "${TB_BRIDGE_UNIT}" install -m 0644 "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-enlist@.service" "${TB_ENLIST_UNIT}" install -m 0644 "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-recover.service" "${TB_RECOVER_UNIT}" install -m 0644 "${SOURCE_DIR}/deploy/attempt1/common/systemd/system/tb-recover.timer" "${TB_RECOVER_TIMER}" install_docs systemctl daemon-reload udevadm control --reload-rules systemctl enable --now tb-bridge.service systemctl enable --now tb-recover.timer systemctl start tb-recover.service || true udevadm trigger --subsystem-match=net --action=add || true echo "Installed paths:" echo " runtime: ${INSTALL_DIR}" echo " recover wrapper: ${RECOVER_WRAPPER}" echo " uninstall: ${UNINSTALL_PATH}" echo " udev rule: ${UDEV_RULE_PATH}" echo " systemd units: tb-bridge.service tb-enlist@.service tb-recover.service tb-recover.timer" echo " docs: ${DOC_DIR}" echo "" echo "Network interface files were left untouched." echo "Installation completed." } main "$@"