The release validator caught it: in a container there is no
/etc/network/interfaces at all, and a missing file was being treated as
a read failure, so --check printed nothing and said nothing was wrong
rather than saying there was nothing to do.
A machine with no ifupdown configuration is the ordinary case for a
fresh install, and the answer is simply that this command has no work.
Co-Authored-By: Claude Opus 5 <[email protected]>
The Bible study laptop had working internet and a panel that said there
was no connection. Both were true, and one thing caused both.
Measured on the machine:
nmcli device status wlp2s0 wifi unmanaged
nmcli networking connectivity none while curl fetched fine
nmcli device wifi list nothing, with the radio enabled
/run/network/ifstate wlp2s0=wlp2s0
a second wpa_supplicant, -i wlp2s0, with no -c config file
dhcpcd holding the lease
/etc/network/interfaces 0600 root:root
Debian's installer had been given the Wi-Fi, so it wrote it into
/etc/network/interfaces and ifupdown brings it up. NetworkManager ships
with plugins=ifupdown and [ifupdown] managed=false, so an interface named
in that file is UNMANAGED — which is why the applet had nothing to report
and why scanning found nothing. An unmanaged device is not a radio
NetworkManager will scan with. rfkill was ruled out separately: the radio
is enabled.
managed=false stays; it is what keeps a tower's static Ethernet where an
administrator put it. Only a wireless interface is moved.
classroom-wifi grows --check, --adopt (with --dry-run) and --rollback.
--adopt builds a NetworkManager SYSTEM connection from the SSID and key
already in that root-only file, so the password never leaves the machine
and never reaches a human or a log; it lands in a 0600 root file with
psk-flags=0, the same shape 0.2.4 established, and the polkit rules
protecting it are untouched.
Deliberately NOT run by the upgrade. It moves a machine's only link
between managers and the machine it could strand is a laptop in a locked
room, so classroom-migrate only looks and prints what it found. An
administrator runs it over SSH while watching.
Two things this learned from testing the rollback rather than from
reading the code, and both are why the rollback is worth testing:
* ifdown was missing in the lab, subprocess raised FileNotFoundError,
and the exception escaped AFTER the stanza was commented out. No
rollback ran. Every hand-over command now goes through a runner that
tolerates a missing binary, and the whole hand-over is inside a guard
that restores the file on any failure at all.
* it now refuses to start when ifdown or ifup are absent, because
without them the hand-over would be a one-way door.
Success also requires the interface itself to be carrying the connection,
not merely that the machine is online — a machine with a second link
would otherwise report a failed migration as a success.
Verified in the lab against real NetworkManager with a real ifupdown
file: --check and --dry-run leave it byte-identical, a failed --adopt
rolls back byte-identically, and --rollback restores a half-migrated
machine byte-identically and exits 0. The one thing no lab can do is the
hand-over succeeding, which needs the laptop's radio.
Co-Authored-By: Claude Opus 5 <[email protected]>
On the laptop the browser jumped behind the disc player the moment it was
opened. 0.2.4 caused that, and the cause is two lines of the stock applet:
main.qml:153 hideActivatedLaunchers: tasks.iconsOnly || ...
main.qml:155 launchInPlace: tasks.iconsOnly && sortingStrategy === 1
For an icons-only bar the first is always true — a launcher is hidden the
instant its application starts — and the second is what puts the running
window back where the launcher was. It only does that at sortingStrategy
1. 0.2.4 set it to 0 to stop teachers dragging the icons about, so the
launcher vanished and the window was appended after the others.
Reproduced in the lab with a real Chrome window before changing anything,
and the bar read off the screen: Wonder Ink, the player, then the
browser. With 1 it is Wonder Ink, the browser, the player, through
opening, a second window, another application opening beside it, and
every close.
The launcher identity was suspected and cleared: only one browser button
appears, because google-chrome.desktop already carries Chrome's own file
name and StartupWMClass for exactly this reason.
THE COST, AND IT IS REAL. Manual sorting is also the only mode in which
MouseHandler.qml accepts a reordering drop, so a teacher who knows to drag
can rearrange the bar again. There is no value that gives both and no
Kiosk key that separates them. classroom-desktop-reset already rebuilds
the bar from the package at every login, so a drag never outlives the
session. docs/testing.md states the trade rather than burying it, and the
configuration escape is written down there too as still open.
tools/lab/order-check is the test this needed and did not have. 0.2.4
passed a full set of configuration assertions while the bar did something
else, so this one opens real application windows and reads the panel
strip as pixels — there is no image library in the lab, so it captures
PPM and names each icon by colour. Six checks, all of them behaviour.
Co-Authored-By: Claude Opus 5 <[email protected]>