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()