diff --git a/webapp/services/blancco_update.py b/webapp/services/blancco_update.py index 69dd13a..f61d376 100644 --- a/webapp/services/blancco_update.py +++ b/webapp/services/blancco_update.py @@ -991,9 +991,13 @@ def apply_prefs(version): def refresh_live_prefs(): """Re-render the served preferences.xml (site settings, share login) and write the same preferences into the live config.img, which the - BIOS (native) boot path reads instead. Returns True if a file changed. - release.json keeps describing the release when it did before.""" + BIOS (native) boot path reads instead. Returns (changed, warning): + warning is set when config.img could not take them (a release older + than our preferences, see check_prefs); the served file, which the + UEFI path uses, is written regardless. release.json keeps describing + the release when it did before.""" from services import blancco_prefs + warning = None with _lock: root = blancco_root() meta_path = os.path.join(root, "release.json") @@ -1005,13 +1009,18 @@ def refresh_live_prefs(): if cfg is not None: with open(blancco_prefs.served_prefs_path(), "rb") as f: ours = f.read() - new = patch_config_img(cfg, ours) + try: + new = patch_config_img(cfg, ours) + except (StageBlocked, ValueError) as e: + warning = (f"the live config.img (BIOS boot) was not updated: {e} " + "Stage a current release on Updates > Blancco releases.") + new = cfg if new != cfg: _atomic_write(cfg_path, new) changed = True if changed and meta_ok: _write_live_meta(meta) - return changed + return changed, warning def save_merged_prefs(version, data): diff --git a/webapp/services/share_accounts.py b/webapp/services/share_accounts.py index 77ef4bf..c29c823 100644 --- a/webapp/services/share_accounts.py +++ b/webapp/services/share_accounts.py @@ -177,7 +177,9 @@ def _apply_menu(password): def _apply_blancco(): from services import blancco_update as bu - return "Blancco preferences: " + ("updated" if bu.refresh_live_prefs() else "unchanged") + changed, warning = bu.refresh_live_prefs() + out = "Blancco preferences: " + ("updated" if changed else "unchanged") + return out + (f" (WARNING: {warning})" if warning else "") def apply(only=None, values=None): diff --git a/webapp/tests/test_share_accounts.py b/webapp/tests/test_share_accounts.py index 00c6007..53560c2 100644 --- a/webapp/tests/test_share_accounts.py +++ b/webapp/tests/test_share_accounts.py @@ -179,6 +179,23 @@ class ShareAccounts(Fixture): with open(BP.repo_prefs_path(), "rb") as f: self.assertEqual(self.prefs_share_pw(BP.apply(f.read())), PW) + def test_older_live_release_warns_instead_of_failing(self): + # A config.img from an older Blancco than our preferences (the repo + # payload can lag): the version guard refuses it. The served + # preferences (UEFI path) still change; the change is not refused. + old = cpio_file(self.cfg, "preferences.xml").replace( + b"20", b"15", 1) + self.assertIn(b"15", old) + cfg = newc({"report.key": b"KEY", "preferences.xml": old, "config.xml": b""}) + with open(os.path.join(BU.blancco_root(), "config.img"), "wb") as f: + f.write(cfg) + done = SA.set_password("blancco", PW) + self.assertTrue(any("WARNING" in d and "config.img" in d for d in done), done) + with open(BP.served_prefs_path(), "rb") as f: + self.assertEqual(self.prefs_share_pw(f.read()), PW) + with open(os.path.join(BU.blancco_root(), "config.img"), "rb") as f: + self.assertEqual(f.read(), cfg) # left as it was + def test_apply_is_idempotent(self): SA.set_password("pxe-upload", PW) SA.set_password("clonezilla", PW + "x") diff --git a/webapp/views/blancco_update.py b/webapp/views/blancco_update.py index 668e934..5d444e1 100644 --- a/webapp/views/blancco_update.py +++ b/webapp/views/blancco_update.py @@ -53,8 +53,8 @@ def site_settings(): request.form.get("wifi_ssid", ""), request.form.get("wifi_password", "")) # Served preferences.xml and the live config.img (BIOS path). - changed = bu.refresh_live_prefs() - except (OSError, ValueError, bu.StageBlocked) as e: + changed, warning = bu.refresh_live_prefs() + except (OSError, ValueError) as e: flash(f"Blancco site settings not saved: {e}", "danger") return _back() s = blancco_prefs.public() @@ -62,6 +62,8 @@ def site_settings(): f"password={'set' if s['wifi_password_set'] else 'empty'}") flash("Blancco site settings saved" + (" and preferences.xml updated." if changed else " (no change)."), "success") + if warning: + flash(f"Blancco: {warning}", "warning") return _back()