Files
OmniSocketGo/scripts/boot/common.sh

254 lines
6.5 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
BOOT_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEV_SCRIPT_DIR="$(cd "${BOOT_SCRIPT_DIR}/../dev" && pwd)"
source_with_nounset_off() {
set +u
# shellcheck disable=SC1090
source "$1"
set -u
}
blitz_host_from_addr() {
local value="${1:-}"
if [[ -z "${value}" ]]; then
return 1
fi
if [[ "${value}" == \[*\]:* ]]; then
value="${value#\[}"
printf '%s\n' "${value%%]:*}"
return 0
fi
printf '%s\n' "${value%%:*}"
}
blitz_load_boot_env() {
local env_file
local default_time_server
if [[ "${BLITZ_BOOT_ENV_LOADED:-0}" == "1" ]]; then
return 0
fi
# shellcheck disable=SC1091
source "${DEV_SCRIPT_DIR}/load-env.sh"
for env_file in \
"${BOOT_SCRIPT_DIR}/robot-boot.env" \
"${BOOT_SCRIPT_DIR}/robot-boot.env.local"
do
if [[ -f "${env_file}" ]]; then
set -a
# shellcheck disable=SC1090
source "${env_file}"
set +a
fi
done
default_time_server="$(blitz_host_from_addr "${ROBOT_SIDE_OMNISOCKET_SERVER_ADDR:-}" || true)"
export BLITZ_BOOT_DELAY_SEC="${BLITZ_BOOT_DELAY_SEC:-30}"
export BLITZ_LOG_FILE="${BLITZ_LOG_FILE:-/var/log/blitz-robot/startup.log}"
export BLITZ_RUNTIME_DIR="${BLITZ_RUNTIME_DIR:-/run/blitz-robot}"
export BLITZ_5G_DIAL_DIR="${BLITZ_5G_DIAL_DIR:-${BOOT_SCRIPT_DIR}}"
export BLITZ_5G_SERIAL_PORT="${BLITZ_5G_SERIAL_PORT:-/dev/ttyUSB7}"
export BLITZ_5G_INTERFACE="${BLITZ_5G_INTERFACE:-}"
export BLITZ_5G_MODEM_SUBNET="${BLITZ_5G_MODEM_SUBNET:-192.168.224.0/22}"
export BLITZ_5G_GATEWAY="${BLITZ_5G_GATEWAY:-192.168.225.1}"
export BLITZ_5G_SKIP_DHCP="${BLITZ_5G_SKIP_DHCP:-0}"
export BLITZ_5G_REMOVE_DEFAULT_ROUTE="${BLITZ_5G_REMOVE_DEFAULT_ROUTE:-1}"
export BLITZ_5G_ROUTE_TARGETS="${BLITZ_5G_ROUTE_TARGETS:-106.55.173.235}"
export BLITZ_5G_INFO_JSON="${BLITZ_5G_INFO_JSON:-${BLITZ_5G_DIAL_DIR}/modem_network_info.json}"
export BLITZ_5G_DISABLE_INTERFACES="${BLITZ_5G_DISABLE_INTERFACES:-}"
export BLITZ_5G_SERIAL_WAIT_SEC="${BLITZ_5G_SERIAL_WAIT_SEC:-60}"
export BLITZ_5G_ROUTE_WAIT_SEC="${BLITZ_5G_ROUTE_WAIT_SEC:-30}"
export BLITZ_TIME_SERVER_IP="${BLITZ_TIME_SERVER_IP:-${default_time_server}}"
export BLITZ_ROS_USER="${BLITZ_ROS_USER:-nvidia}"
export BLITZ_ROS_SOCKET_WAIT_SEC="${BLITZ_ROS_SOCKET_WAIT_SEC:-20}"
export BLITZ_WATCHDOG_INTERVAL_SEC="${BLITZ_WATCHDOG_INTERVAL_SEC:-5}"
export BLITZ_HEALTH_STALE_SEC="${BLITZ_HEALTH_STALE_SEC:-15}"
export BLITZ_OMNID_THREAD_HEARTBEAT_TIMEOUT_SEC="${BLITZ_OMNID_THREAD_HEARTBEAT_TIMEOUT_SEC:-15}"
export BLITZ_NETWORK_FAIL_THRESHOLD="${BLITZ_NETWORK_FAIL_THRESHOLD:-3}"
export BLITZ_NETWORK_RECOVERY_COOLDOWN_SEC="${BLITZ_NETWORK_RECOVERY_COOLDOWN_SEC:-30}"
export BLITZ_WATCHDOG_ALLOW_FAULT_INJECTION="${BLITZ_WATCHDOG_ALLOW_FAULT_INJECTION:-0}"
export BLITZ_BOOT_ENV_LOADED="1"
}
blitz_timestamp() {
date '+%Y-%m-%d %H:%M:%S%z'
}
blitz_sanitize_detail() {
local detail="${1:-}"
detail="${detail//$'\n'/ ; }"
detail="${detail//$'\r'/ }"
printf '%s' "${detail}"
}
blitz_log() {
local step="${1:-unknown-step}"
local action="${2:-unknown-action}"
local result="${3:-info}"
local details="${4:-}"
local exit_code="${5:-0}"
printf '%s | %s | %s | %s | %s | %s\n' \
"$(blitz_timestamp)" \
"${step}" \
"${action}" \
"${result}" \
"$(blitz_sanitize_detail "${details}")" \
"${exit_code}"
}
blitz_join_cmd() {
local cmd=()
local arg
for arg in "$@"; do
cmd+=("$(printf '%q' "${arg}")")
done
printf '%s' "${cmd[*]}"
}
blitz_require_command() {
local command_name="$1"
local step="${2:-precheck}"
if command -v "${command_name}" >/dev/null 2>&1; then
blitz_log "${step}" "require-command" "success" "command=${command_name}" 0
return 0
fi
blitz_log "${step}" "require-command" "failure" "missing command: ${command_name}" 127
return 127
}
blitz_require_file() {
local path="$1"
local step="${2:-precheck}"
if [[ -f "${path}" ]]; then
blitz_log "${step}" "require-file" "success" "path=${path}" 0
return 0
fi
blitz_log "${step}" "require-file" "failure" "missing file: ${path}" 1
return 1
}
blitz_require_executable() {
local path="$1"
local step="${2:-precheck}"
if [[ -x "${path}" ]]; then
blitz_log "${step}" "require-executable" "success" "path=${path}" 0
return 0
fi
blitz_log "${step}" "require-executable" "failure" "missing executable: ${path}" 1
return 1
}
blitz_require_root() {
local step="${1:-precheck}"
if [[ "${EUID}" -eq 0 ]]; then
blitz_log "${step}" "require-root" "success" "uid=${EUID}" 0
return 0
fi
blitz_log "${step}" "require-root" "failure" "root privileges are required" 1
return 1
}
blitz_run() {
local step="$1"
local action="$2"
local rc
shift 2
blitz_log "${step}" "${action}" "start" "$(blitz_join_cmd "$@")" 0
if "$@"; then
blitz_log "${step}" "${action}" "success" "$(blitz_join_cmd "$@")" 0
return 0
else
rc=$?
fi
blitz_log "${step}" "${action}" "failure" "$(blitz_join_cmd "$@")" "${rc}"
return "${rc}"
}
blitz_route_ready() {
local target_ip="$1"
local expected_interface="${2:-}"
local route_output
route_output="$(ip route get "${target_ip}" 2>&1 || true)"
if [[ -z "${route_output}" ]]; then
return 1
fi
if [[ "${route_output}" == *"unreachable"* || "${route_output}" == *"prohibit"* ]]; then
return 1
fi
if [[ -n "${expected_interface}" && "${route_output}" != *" dev ${expected_interface} "* && "${route_output}" != *" dev ${expected_interface}" ]]; then
return 1
fi
printf '%s\n' "${route_output}"
return 0
}
blitz_resolve_5g_interface() {
local explicit_interface="${BLITZ_5G_INTERFACE:-}"
local info_json="${BLITZ_5G_INFO_JSON:-}"
if [[ -n "${explicit_interface}" ]]; then
printf '%s\n' "${explicit_interface}"
return 0
fi
if [[ -z "${info_json}" || ! -f "${info_json}" ]]; then
return 1
fi
python3 - "${info_json}" <<'PY'
import json
import sys
path = sys.argv[1]
try:
with open(path, "r", encoding="utf-8") as handle:
payload = json.load(handle)
except Exception:
raise SystemExit(1)
interface = str(payload.get("interface") or "").strip()
if not interface:
raise SystemExit(1)
print(interface)
PY
}
blitz_prepare_runtime_dir() {
local runtime_dir
blitz_load_boot_env
runtime_dir="${BLITZ_RUNTIME_DIR}"
mkdir -p "${runtime_dir}"
if [[ "${EUID}" -eq 0 ]]; then
chown "root:${BLITZ_ROS_USER}" "${runtime_dir}"
chmod 0775 "${runtime_dir}"
else
chmod 0775 "${runtime_dir}" 2>/dev/null || true
fi
blitz_log "runtime-dir" "prepare" "success" "path=${runtime_dir}" 0
}