Rename every remaining voxip name to daynivo, with a one-time migration
CI / test-bookworm (push) Successful in 29s
CI / test-latest (push) Successful in 31s

Services (daynivo-kiosk-*, daynivo-network-guard, daynivo-boot-import),
programs in /usr/lib/daynivo-kiosk, folders /etc, /var/lib, /var/log and
/var/cache daynivo-kiosk*, the system user daynivo, DAYNIVO_* settings,
the plymouth theme, network profiles daynivo-eth0/wlan0, the image stage
and its first user daynivoadmin.

install.sh moves a kiosk installed up to 1.2.x over once: old services
stopped and removed, folders moved (configuration, password, browser
profile, logs) with symlinks under the old names, the voxip user renamed
with the same uid, network profiles renamed unless a change awaits
confirmation, and old leftovers removed. Tested by upgrading a configured
1.2.0 installation in a container, and running the install a second time.

Old names keep working where people type or place them: voxip-config.json,
voxip-authorized_keys, voxip-network-reset, voxip-kiosk-ctl, and
VOXIP_DEFAULT_URL / VOXIP_DEVICE_NAME for image builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rothmanandClaude Opus 5.5 committed 2026-11-05 23:58:03 +01:00
1 parent 6733aacb6e
commit eb0242c182
68 files changed
+527 -424

No files matched your search

+18 -18
View File
@@ -35,7 +35,7 @@ def helper(paths, tmp_path, boot):
etc.mkdir()
(etc / "hosts").write_text("127.0.0.1\tlocalhost\n127.0.1.1\tkiosk\n")
run = Recorder({"nmcli -t -f": "aaaa-1111\n"})
return h.Helper(paths=paths, run=run, etc=etc, boot_dirs=(boot,), helper_path="/usr/lib/voxip-kiosk/voxip-kiosk-helper")
return h.Helper(paths=paths, run=run, etc=etc, boot_dirs=(boot,), helper_path="/usr/lib/daynivo-kiosk/daynivo-kiosk-helper")
def run_main(helper, argv, env=None, capsys=None):
@@ -45,17 +45,17 @@ def run_main(helper, argv, env=None, capsys=None):
def test_internal_verbs_refused_via_sudo(helper, capsys):
code, out = run_main(helper, ["network-restore"], {"SUDO_USER": "voxip"}, capsys)
code, out = run_main(helper, ["network-restore"], {"SUDO_USER": "daynivo"}, capsys)
assert code == 1 and out["ok"] is False
code, out = run_main(helper, ["boot-import"], {"SUDO_USER": "voxip"}, capsys)
code, out = run_main(helper, ["boot-import"], {"SUDO_USER": "daynivo"}, capsys)
assert code == 1
assert helper.run.commands == []
def test_public_verb_via_sudo(helper, capsys):
code, out = run_main(helper, ["restart-browser"], {"SUDO_USER": "voxip"}, capsys)
code, out = run_main(helper, ["restart-browser"], {"SUDO_USER": "daynivo"}, capsys)
assert code == 0 and out["ok"] is True
assert helper.run.ran("systemctl", "restart", "--no-block", "voxip-kiosk-browser.service")
assert helper.run.ran("systemctl", "restart", "--no-block", "daynivo-kiosk-browser.service")
def test_unknown_verb_and_bad_arity(helper, capsys):
@@ -99,7 +99,7 @@ ETH_STATIC = {"interface": "eth0", "method": "static", "address": "192.168.5.10/
def test_network_apply_snapshot_pending_and_timers(helper, paths):
(paths.nm_connections_dir / "Wired connection 1.nmconnection").write_text("[connection]\nid=Wired connection 1\n")
result = helper.network_apply(ETH_STATIC)
keyfile = paths.nm_connections_dir / "voxip-eth0.nmconnection"
keyfile = paths.nm_connections_dir / "daynivo-eth0.nmconnection"
assert keyfile.exists() and oct(keyfile.stat().st_mode & 0o777) == "0o600"
assert "address1=192.168.5.10/24,192.168.5.1" in keyfile.read_text()
assert (paths.network_backup_dir / "Wired connection 1.nmconnection").exists()
@@ -108,8 +108,8 @@ def test_network_apply_snapshot_pending_and_timers(helper, paths):
assert pending["deadline"] - pending["created"] == 180
assert result["pending"]["interface"] == "eth0"
runs = [c for c in helper.run.commands if c[0] == "systemd-run"]
assert runs[0][1:3] == ["--unit=voxip-network-rollback", "--on-active=180"] and runs[0][-1] == "network-restore"
assert runs[1][1:3] == ["--unit=voxip-network-activate", "--on-active=2"] and runs[1][-2:] == ["network-activate", "eth0"]
assert runs[0][1:3] == ["--unit=daynivo-network-rollback", "--on-active=180"] and runs[0][-1] == "network-restore"
assert runs[1][1:3] == ["--unit=daynivo-network-activate", "--on-active=2"] and runs[1][-2:] == ["network-activate", "eth0"]
def test_second_apply_refused_while_pending(helper):
@@ -123,8 +123,8 @@ def test_confirm_clears_pending(helper, paths):
helper.network_confirm()
assert not paths.network_pending_file.exists()
assert not paths.network_backup_dir.exists()
assert (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
assert helper.run.ran("systemctl", "stop", "voxip-network-rollback.timer")
assert (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
assert helper.run.ran("systemctl", "stop", "daynivo-network-rollback.timer")
def test_restore_puts_old_profiles_back(helper, paths):
@@ -134,7 +134,7 @@ def test_restore_puts_old_profiles_back(helper, paths):
old.unlink()
helper.network_restore()
assert old.exists()
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
assert not paths.network_pending_file.exists()
assert helper.run.ran("nmcli", "--wait", "30", "connection", "up", "uuid", "aaaa-1111")
@@ -152,7 +152,7 @@ def test_wifi_keeps_existing_password_for_same_ssid(helper, paths):
helper.network_confirm()
helper.network_apply({"interface": "wlan0", "method": "static", "address": "10.0.0.9/24", "gateway": "10.0.0.1", "dns": "10.0.0.1",
"wifi": {"ssid": "Kantoor", "psk": ""}})
assert "psk=geheim-wachtwoord" in (paths.nm_connections_dir / "voxip-wlan0.nmconnection").read_text()
assert "psk=geheim-wachtwoord" in (paths.nm_connections_dir / "daynivo-wlan0.nmconnection").read_text()
helper.network_confirm()
with pytest.raises(h.HelperError, match="wachtwoord"):
helper.network_apply({"interface": "wlan0", "method": "dhcp", "wifi": {"ssid": "Ander", "psk": ""}})
@@ -165,22 +165,22 @@ def test_boot_guard_rolls_back_and_honours_reset(helper, paths, boot):
helper.run.commands.clear()
result = helper.network_boot_guard()
assert result == {"rolled_back": True}
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
assert not any(c[0] == "nmcli" for c in helper.run.commands), "NetworkManager is not running yet at boot"
(paths.nm_connections_dir / "voxip-wlan0.nmconnection").write_text("x")
(paths.nm_connections_dir / "daynivo-wlan0.nmconnection").write_text("x")
(boot / "daynivo-network-reset").write_text("")
assert helper.network_boot_guard() == {"reset": True}
assert not (paths.nm_connections_dir / "voxip-wlan0.nmconnection").exists()
assert not (paths.nm_connections_dir / "daynivo-wlan0.nmconnection").exists()
assert not (boot / "daynivo-network-reset").exists()
assert old.exists()
def test_boot_guard_still_honours_the_old_reset_name(helper, paths, boot):
(paths.nm_connections_dir / "voxip-eth0.nmconnection").write_text("x")
(paths.nm_connections_dir / "daynivo-eth0.nmconnection").write_text("x")
(boot / "voxip-network-reset").write_text("")
assert helper.network_boot_guard() == {"reset": True}
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
assert not (boot / "voxip-network-reset").exists()
@@ -230,7 +230,7 @@ def test_update_verbs_are_public_and_install_runs_in_its_own_unit(helper):
def test_update_install_reports_a_running_update(helper):
def busy(args, timeout=30, check=True, input=None):
return subprocess.CompletedProcess(args, 1, stdout="", stderr="Unit voxip-kiosk-update-now.service already exists.")
return subprocess.CompletedProcess(args, 1, stdout="", stderr="Unit daynivo-kiosk-update-now.service already exists.")
helper.run = busy
with pytest.raises(h.HelperError, match="al een update"):