Issue 332: the service manager could neither clear a failed unit nor say what wants it
A leftover user unit stayed raised on the workstation: no seat verb showed the dangling enable link that keeps asking for it, or reset its failed record, so the only step left was a shell. Lands per ADR 0246.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
---
|
||||
status: located
|
||||
opened: 2026-10-08
|
||||
located-in: [mesh-controller internal/catalogue (seats.go, the node-service-manager seat's verbs), mesh-catalog modules/systemd (the seat's holder)]
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 332. The service manager cannot clear or explain a failed unit
|
||||
|
||||
## Symptom
|
||||
|
||||
On 2026-10-08 the workstation's machine finding (`machine.<workstation>.units`, from
|
||||
[issue 315](../315-a-failed-unit-of-a-module-was-never-raised/00-report.md)) listed a user unit of a
|
||||
clipboard tool that a module had replaced: load state `not-found`, active state `failed`, no unit file.
|
||||
The operator approved removing it. Two steps were needed, and the `node-service-manager` seat had a verb
|
||||
for neither:
|
||||
|
||||
1. **Find what still asks for the unit.** The seat's `status` says the file is gone, and its `journal`
|
||||
says when the unit last failed. Neither says which unit wants it, or whether an enable link in a
|
||||
`*.wants` directory still names it and dangles. Issue 315's diagnosis found the link from the module's
|
||||
README, not from a tool.
|
||||
2. **Clear the failed record.** A manager keeps a unit's failed state and start-limit count until they
|
||||
are reset. The seat had no verb for `systemctl reset-failed`, so the finding stays raised until the
|
||||
account's manager restarts.
|
||||
|
||||
Without either verb, the step left is a shell on the machine, which
|
||||
[ADR 0245](../../02-DECISIONS/0245-a-verb-says-what-it-replaces-and-the-agent-is-guarded-from-working-round-the-mesh.md) rules out: the missing
|
||||
tool is built in the module that owns the area, on its seat.
|
||||
|
||||
## Fix
|
||||
|
||||
Two verbs on the seat, each saying the command it replaces:
|
||||
|
||||
- **`reset-failed {unit, scope}`** clears one unit's failed record. A unit is required, so the verb never
|
||||
resets every failed unit at once. It replaces `systemctl reset-failed`.
|
||||
- **`wanted-by {unit, scope}`** is read-only. It answers what wants, requires or triggers one unit: the
|
||||
manager's reverse dependencies (`WantedBy`, `RequiredBy`, `UpheldBy`, `BoundBy`, `TriggeredBy` and the
|
||||
rest, and the units that pull those in), and every enable link naming the unit in the scope's
|
||||
configuration directories. In user scope that includes the account's own. Each link is given with where
|
||||
it points, whether it dangles and whose directory it is in. It replaces `systemctl list-dependencies
|
||||
--reverse` and reading the `*.wants` directories by hand.
|
||||
|
||||
They land in the three steps of
|
||||
[ADR 0246](../../02-DECISIONS/0246-a-seats-new-verb-is-promised-before-it-is-required.md):
|
||||
|
||||
1. The controller promises both verbs as optional (mesh-controller, this issue's first pull request).
|
||||
2. The `systemd` module serves both (mesh-catalog). Its check passes only against a controller that
|
||||
already promises them, so it merges after step 1 is delivered.
|
||||
3. The controller requires both, in a later pull request, once every holder serves them.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- mesh-controller: `TestResetFailedAndWantedByAreOptionalVerbsOfTheServiceManager` (both promised,
|
||||
optional, read back optional from the store's row, each naming the command it replaces), and the seat's
|
||||
verb list in `TestTheServiceManagerSeatServesTheUnitVerbs`.
|
||||
- mesh-catalog `modules/systemd`: the `wanted_test.go` tests (a dangling enable link in the account's own
|
||||
configuration found and named, a link matched by its target, an unreadable directory and an unreachable
|
||||
manager said rather than read as nothing, read-only), and the manifest test that the module serves exactly
|
||||
the verbs it claims.
|
||||
- Step 3 is not checked by anything yet, as ADR 0246 says of every optional verb.
|
||||
Reference in New Issue
Block a user