Skip to content

A library update never restarts incusd under live terminals - #335

Merged
udaychandra merged 5 commits into
mainfrom
agent/sail-host-needrestart-policy
Oct 22, 2026
Merged

udaychandra merged 5 commits into
mainfrom
agent/sail-host-needrestart-policy

Conversation

@udaychandra

@udaychandra udaychandra commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Spec: sail-host-needrestart-policy.

On 2026-09-18 and again on 2026-10-22, an unattended Ubuntu security update had needrestart restart incus.service in automatic mode. incusd kills every interactive incus exec on shutdown, so every container terminal in every project ended.

What changed

  • NeedrestartPolicy.DROP_IN (sail-harness, beside SshdKeepalive) is /etc/needrestart/conf.d/50-sail.conf: $nrconf{override_rc}{qr(^incus)} = 0;. Both drop-ins are now one HostDropIn record (name, path, content, reload). It owns the one install script, which writes atomically with mode 0644 and passes the content to bash as an argument. The sshd drop-in's write becomes atomic as a result.
  • sail migrate (so every sail upgrade) writes both drop-ins from one list, through one catch ladder. The wiring is now under test (ensureHostDropIns); before, nothing tested that migrate wrote the sshd drop-in at all.
  • sail host init writes the policy first in step 1, before apt-get upgrade, so a library that upgrade replaces does not restart incusd. An incus package upgraded by a re-run still restarts it, as any incus upgrade does; the README says so. Init fails fast if the write fails, and --dry-run prints the command.
  • sail host update is deleted. host status (JSON and banner, now under HostStatusCommandTest) runs incus version live through one parser (HostProvisioner.incusVersion), which init now shares; the copy in HostUpdateCommand went with it. HostYaml.withIncusVersion is deleted (it had no caller left).
  • The sail-api unit gains SuccessExitStatus=143. reconcile() carries it to installed boxes from their next upgrade on: the upgrade's reconcile runs in the old binary (a migrate-written unit would be reverted by it on the same hop), so the CHANGELOG says so. sudo sail host init writes it at once.
  • README: host packages are the operator's to upgrade, with sudo sail session ls first. CHANGELOG entry.

Takeover (943e546): HostDropIn.install(shell, target) is the one checked write; migrate's own exec/ok/throw copy is gone, and its warning no longer says "not written" when only the reload failed. The concurrent-install test gives up after ten seconds instead of spinning on a hung bash. Independent delta review: 1 MEDIUM (the 143 claim, fixed in wording), 2 shape/robustness LOW (fixed), 1 LOW wording (fixed); no HIGH. Seven fix-reverting mutants red: init omits the policy, prerequisites omit it, the write is not atomic, a silent daemon reads as zero containers, the unit drops 143, migrate omits the policy, the regex names sail. Local -Pintegration verify green before and after the delta.

Deleted: HostUpdateCommand (108 lines), HostYaml.withIncusVersion, a duplicate incus version parser, the sshd drop-in's own install script and accessors (folded into HostDropIn), host update from ROOT_ONLY, RootRequiredTest and the LifecycleCommandTest help test. git diff --shortstat: 30 files changed, 729 insertions(+), 314 deletions(-).

Deviation: the drop-in comment says "Restart incus on purpose, when no terminal into a container is open." instead of naming sail session ls / sail host update. The verb is gone, and OperatorHintsTest forbids sail <verb> literals outside OperatorCommand, which sail-harness cannot reach. EnrollCommand already said sudo sail upgrade on main, so nothing changed there.

Tests that bite (fix-reverting mutants, all killed): migrate omits the policy; init omits the policy; the unit drops 143; the banner reads host.yaml; the regex says ^sail; the status JSON reads host.yaml.

…honest 143 claim

HostDropIn.install(shell, target) is the one checked write; migrate used its own
exec/ok/throw copy and said "not written" when the write had landed and only the
reload failed. The concurrent-install test now gives up after ten seconds instead of
spinning forever on a hung bash. The CHANGELOG said sail upgrade rewrites an installed
sail-api unit with SuccessExitStatus=143; the upgrade's reconcile runs in the old
binary, so a box gets the line from its next upgrade on, and the entry says so.
@udaychandra
udaychandra merged commit a157608 into main Oct 22, 2026
5 checks passed
@udaychandra
udaychandra deleted the agent/sail-host-needrestart-policy branch October 22, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant