fix(swap): never reduce active swap to zero in a rollback [P0]

The previous fix closed one branch and left its neighbours open. Both remaining paths could
still end with the host having no swap, and one of them said the opposite in its own error
message.

1. The message claimed a fallback that was no longer running.

   The forward path deactivates the staging swap *before* renaming it onto the managed
   path. A failure at that rename, or at anything after it, therefore reached the rollback
   with staging_active = false. The rollback then returned "the staging swap is left
   active" - which was false: it had been switched off several steps earlier, and with the
   original also unable to activate, the host had nothing.

   The rollback now brings the replacement back up as the fallback when it is not running,
   and the error describes what is actually active rather than assuming.

2. The replacement was deleted before the original was known to work.

   With new_installed the rollback removed the file at the managed path to make room for
   the restore. That discarded the only other swap area on the host before finding out
   whether the original could be activated. The replacement is now moved aside to the
   staging name instead, so it is still available as the fallback if the restore fails.

3. An installed replacement could be moved while the kernel was swapping to it.

   ReplacementState had no way to express "installed and active", so a failure in the final
   verification - a failed read of /proc/swaps after a successful swapon - left the
   rollback moving a live swapfile. new_active closes that: if the replacement is active it
   is deactivated first, and if that fails the rollback stops and reports that the
   replacement is in place and serving, because a working swap is the outcome to keep.

Also from the same audit:

- mkswap --file creates the file itself, so a non-zero exit is not a guarantee that nothing
  was left behind. Both creation paths now remove the file on failure; previously a failed
  mkswap left an unowned file at the managed path, which the next run correctly called
  Foreign and refused, wedging the module.
- stale_ownership_help gave advice that could not work. Removing the ownership record
  leaves the file Foreign, which is refused just as firmly, so "mv previous main, delete the
  record" only changed which error appeared. Both cases now give one recipe that actually
  restores managed state: swapoff, remove the three files and the record, re-run
  ensure-swap. Swap holds no persistent data, so a rebuild loses nothing.
- LastActionState kept a single error slot shared by all subsystems, so a successful
  firewall reconcile cleared a live traffic failure and logged firewall=recovered for
  something that had never failed. Errors are now tracked per subsystem; the shared field
  that status reads mirrors whatever is still outstanding.
- tools/README.md still showed 0.1.6.

Five rollback tests covering the branches that exist: original unrestorable with staging
running, original unrestorable with staging already stopped (it is reactivated and never
released), an installed replacement preserved by being moved aside rather than deleted,
the success path releasing the replacement only after the original is back, and the
no-op case.

cargo fmt --check, clippy -D warnings, cargo test --locked --workspace --release: 193 + 4
passed.
This commit is contained in:
2026-08-07 05:42:09 +05:00
parent 6b3e5d1b2f
commit 61dcea2d25
3 changed files with 295 additions and 104 deletions
+3 -3
View File
@@ -24,10 +24,10 @@ reboot_module -> awg2-reboot-scheduler
cd awg2_harness
chmod +x tools/build.sh
./tools/build.sh --prepare-build-env --bootstrap-rust --yes
./tools/build.sh --package --version 0.1.6
./tools/build.sh --package --version 0.3.0
(cd dist && sha256sum -c SHA256SUMS)
dpkg-deb -I dist/awg2-harness_0.1.6_amd64.deb
dpkg-deb -c dist/awg2-harness_0.1.6_amd64.deb | sort
dpkg-deb -I dist/awg2-harness_0.3.0_amd64.deb
dpkg-deb -c dist/awg2-harness_0.3.0_amd64.deb | sort
```
## Что делает default запуск