Skip to content

feat(host): prepare a guarded NetworkManager route-metric change and an isolated fixture for it - #240

Merged
Mearman merged 4 commits into
mainfrom
feat/nm-connectivity-disable
Nov 7, 2026
Merged

Mearman merged 4 commits into
mainfrom
feat/nm-connectivity-disable

Conversation

@Mearman

@Mearman Mearman commented Nov 7, 2026

Copy link
Copy Markdown
Member

Prepares the work for changing a Linux host's NetworkManager route metrics safely, and changes nothing on a host: every path that would make the change still refuses.

The role and the connectivity module fail closed, because a global NetworkManager change needs a rollback that survives a crash and none is wired in yet. What this adds is the pieces and the evidence for them. A durable transaction with a host-owned watchdog unit, a read-only collector that plans which default route controls which flow, and a transaction adapter that addresses one daemon process by its unique bus name. A fixture and a KVM harness run a real NetworkManager 1.54.3 in a disposable offline guest, and measured the following:

  • A write held in PolicyKit is not cancelled when its client disconnects.
  • version-id rejects a stale write within one daemon lifetime and is reused after a restart, so the fence is the bus owner plus the version, with the profile found by UUID.
  • A device checkpoint rolls back a runtime Reapply but not a persistent edit.
  • A crash mid-change loses the checkpoint and leaves the changed route behind, which only a host-owned watchdog can remove.
  • An edit of the netplan profile followed by a reload moves the version, and the stale write is rejected.

Not covered: real PolicyKit instead of the stand-in, and wiring the transaction to the role.

…t-owned rollback

The Linux host role can describe a NetworkManager connectivity-check change, but it refuses to
make it: the module and the role task fail closed until a rollback that survives a crash is
proven safe. A durable transaction snapshots the drop-in under a host lock with boot-scoped
deadlines, and a host-owned watchdog unit restores it if the change is not committed in time.
The tests drive the module's logic through a copy of it with its one refusal statement removed,
and separately assert that both the shipped module and the role refuse and change nothing.
…ion to one daemon

The metric plan module reads the active NetworkManager profiles and the IPv4 routes and rules,
classifies which flows each default route controls, and returns no candidate and no change.
The metric transaction adapter addresses every call to the unique bus name the daemon owned
when the adapter was created, so a read made before a NetworkManager restart cannot be followed
by a write after it. A restart resets each profile version and renumbers its object path, which
a version alone cannot detect. The transaction still refuses to run until it is wired to a
host-owned watchdog.
…that runs it

The fixture starts a private D-Bus, a PolicyKit stand-in and a real NetworkManager inside a
disposable guest, and sends a non-root Update2 that stays held while its client disconnects.
The QEMU launch requires KVM, checks the child's identity once its argument area is published,
and has no network or host share. The harness builds a guest layer from a signature-verified
base image and runs the scenarios: a held write survives a disconnect, a version fence holds
within one daemon lifetime but not across a restart, a checkpoint rolls back a runtime
Reapply but not a persistent edit, a crash mid-change leaves the changed route behind, and an
external edit of a netplan profile is rejected against a stale write.
…he harness script lint

A lint of the repository cannot resolve a module name that exists only while a test runs, so
the playbook that calls the test copy of the module is written to the test's temporary
directory instead of being committed. The harness scenario script drops an unused loop
variable and quotes its character translation by octal value, which shellcheck accepts.
@Mearman
Mearman marked this pull request as ready for review November 7, 2026 18:17
@Mearman
Mearman merged commit 64b229a into main Nov 7, 2026
16 checks passed
@Mearman
Mearman deleted the feat/nm-connectivity-disable branch November 7, 2026 18:17
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.45.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant