mirror of
https://github.com/ergosteur/ergo-proxmox-scripts.git
synced 2026-10-28 13:00:37 -04:00
Adding a PCIe card can renumber the buses behind it, so a hostpci entry that names a PCI address can pass through the wrong device. These start the VM only after finding each device by vendor/device/subsystem ID or by its MAC-pinned interface, repoint its resource mapping if it moved, and refuse to start on anything ambiguous. Its dependents then wait for a port on it to answer before starting, so they find their shares up.
118 lines
3.8 KiB
Bash
Executable File
118 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# Start the guests that depend on the passthrough VM, once it is serving.
|
|
#
|
|
# Usage:
|
|
# ./start-dependents.sh [--check]
|
|
#
|
|
# Run at boot by dependents-start.service, after passthrough-vm-start.service
|
|
# has started the VM they need (a NAS, typically). The guests to start, in
|
|
# order, are listed in conf/dependents.conf; give each of them onboot: 0 so that
|
|
# only this starts them. VM and container IDs both work.
|
|
#
|
|
# Before starting anything it waits for WAIT_FOR (host:port) to accept a TCP
|
|
# connection, for up to WAIT_SECS seconds, because a VM that has started is not
|
|
# yet one that is serving. If it never answers the guests are started anyway,
|
|
# with a warning, which is no worse than not waiting at all.
|
|
#
|
|
# A guest that fails to start does not stop the others; the script exits
|
|
# non-zero at the end so the unit shows as failed. Guests already running are
|
|
# left alone. Nothing is started while prox-maintenance-mode.sh has autostart
|
|
# disabled.
|
|
#
|
|
# Options:
|
|
# --check Show what would be started and test WAIT_FOR once; start nothing
|
|
#
|
|
# The config is looked for relative to this script, so this works both in a
|
|
# checkout and deployed at /opt/ergosteur. Override with DEPENDENTS_CONFIG.
|
|
|
|
set -uo pipefail
|
|
|
|
# Print the header comment block: everything from line 2 up to the first blank line.
|
|
usage() {
|
|
sed -n '2,/^$/p' "$0" | sed -e 's/^#//' -e 's/^ //'
|
|
}
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
CONFIG=${DEPENDENTS_CONFIG:-$SCRIPT_DIR/conf/dependents.conf}
|
|
MAINT_STATE=/var/tmp/proxmox-autostart-backup.txt # written by prox-maintenance-mode.sh --enable
|
|
CHECK_ONLY=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help) usage; exit 0 ;;
|
|
--check) CHECK_ONLY=true; shift ;;
|
|
*) echo "Error: unknown option '$1'." >&2; usage >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
[[ -r $CONFIG ]] || { echo "Error: cannot read $CONFIG" >&2; exit 1; }
|
|
GUESTS=()
|
|
WAIT_FOR=""
|
|
WAIT_SECS=300
|
|
# shellcheck source=conf/dependents.conf.example
|
|
source "$CONFIG"
|
|
|
|
if [[ -e $MAINT_STATE ]]; then
|
|
echo "maintenance mode is on ($MAINT_STATE exists); not starting anything"
|
|
exit 0
|
|
fi
|
|
if [[ ${#GUESTS[@]} -eq 0 ]]; then
|
|
echo "no GUESTS listed in $CONFIG; nothing to do"
|
|
exit 0
|
|
fi
|
|
|
|
# True once host:port accepts a TCP connection.
|
|
answers() {
|
|
timeout 3 bash -c "exec 3<>/dev/tcp/${1%:*}/${1##*:}" 2>/dev/null
|
|
}
|
|
|
|
if [[ -n $WAIT_FOR ]]; then
|
|
if $CHECK_ONLY; then
|
|
if answers "$WAIT_FOR"; then
|
|
echo "$WAIT_FOR answers"
|
|
else
|
|
echo "$WAIT_FOR is not answering right now"
|
|
fi
|
|
else
|
|
echo "waiting up to ${WAIT_SECS}s for $WAIT_FOR"
|
|
deadline=$((SECONDS + WAIT_SECS))
|
|
until answers "$WAIT_FOR"; do
|
|
if (( SECONDS >= deadline )); then
|
|
echo "WARNING: $WAIT_FOR still not answering after ${WAIT_SECS}s; starting the guests anyway"
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
answers "$WAIT_FOR" && echo "$WAIT_FOR answers"
|
|
fi
|
|
fi
|
|
|
|
failed=0
|
|
for id in "${GUESTS[@]}"; do
|
|
if [[ -e /etc/pve/qemu-server/$id.conf ]]; then
|
|
tool=qm conf=/etc/pve/qemu-server/$id.conf
|
|
elif [[ -e /etc/pve/lxc/$id.conf ]]; then
|
|
tool=pct conf=/etc/pve/lxc/$id.conf
|
|
else
|
|
echo "ERROR: no VM or container $id on this node" >&2
|
|
failed=1
|
|
continue
|
|
fi
|
|
if grep -q '^onboot: 1' "$conf"; then
|
|
echo "WARNING: $id has onboot: 1, so Proxmox starts it before the VM it needs; set onboot: 0"
|
|
fi
|
|
if [[ $($tool status "$id" 2>/dev/null) == "status: running" ]]; then
|
|
echo "$id is already running"
|
|
continue
|
|
fi
|
|
if $CHECK_ONLY; then
|
|
echo "would start $id ($tool)"
|
|
elif $tool start "$id"; then
|
|
echo "started $id ($tool)"
|
|
else
|
|
echo "ERROR: $tool start $id failed" >&2
|
|
failed=1
|
|
fi
|
|
done
|
|
exit "$failed"
|