mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
031f0a4cdd
* fix: preserve running guests across target restart, harden state write spinifex-shutdown.service's ExecStop fired on any spinifex.target stop, including the stop half of `systemctl restart spinifex.target`, draining every guest via QMP even though the host never went down. Gate the drain behind `systemctl is-system-running` == "stopping", which only holds once systemd is genuinely unwinding into shutdown.target (reboot/poweroff), so a target restart or plain `systemctl stop` now leaves QEMU/nbdkit running (KillMode=process) for the daemon to reconnect to on the way back up. Daemon.WriteState returned as soon as the local state file write failed, skipping the independent JetStream KV write entirely. A crash in that window left a live VM with no durable record anywhere. Attempt the KV write regardless of local disk health, then still surface the local write error to callers, mirroring finalizeTerminated's handling of the same fault class on the terminate path. * fix: gate the shutdown drain via an spx flag, not a shell script Replace the shutdown-drain-gate.sh gate with a --only-if-host-stopping flag on `spx admin node drain`. The unit now points at /usr/local/bin/spx directly (already required for the node to function) instead of a script installed under the data directory, which a partial rebuild of that directory could silently drop without ever failing ExecStop. The gate logic also becomes a plain Go function with injectable state lookup, so it gets real table-driven coverage instead of only a live reboot. hostIsStopping() drains only on a literal "stopping" from `systemctl is-system-running`. Every other recognized state (running/degraded/...) and any unrecognized output skip the drain; a fully unreachable systemctl fails toward draining, since a skipped drain on a real shutdown hard-kills guests and loses unflushed writes, while a spurious drain on a restart only costs an extra graceful stop/relaunch cycle. Run by hand without the flag, the command still drains unconditionally as it always has. * refactor: split the shutdown-gate comments to sit with the code they explain