Continue guest-update rollback after individual restore failures

This commit is contained in:
Codex
2026-10-13 15:29:28 +03:00
parent dcf1fbae40
commit 61a5628f9e
3 changed files with 111 additions and 16 deletions
+23 -10
View File
@@ -179,17 +179,30 @@ def apply_bundle(bundle, root=Path('/'), *, execute=False):
for name, (data, mode) in payload.items():
atomic_write(checked_path(root, name), data, mode)
changed.append(name)
except BaseException:
except BaseException as apply_error:
rollback_errors = {}
for name in reversed(changed):
dest = checked_path(root, name)
original = records[name]
if 'symlink' in original:
dest.unlink()
dest.symlink_to(original['symlink'])
elif original['existed']:
atomic_write(dest, (backup / name).read_bytes(), original['mode'])
else:
dest.unlink()
try:
dest = checked_path(root, name)
original = records[name]
if 'symlink' in original:
dest.unlink()
dest.symlink_to(original['symlink'])
elif original['existed']:
atomic_write(dest, (backup / name).read_bytes(), original['mode'])
else:
dest.unlink(missing_ok=True)
except BaseException as restore_error:
# A full/unavailable filesystem may prevent one restoration
# while unlinking independently created files still succeeds.
rollback_errors[name] = f'{type(restore_error).__name__}: {restore_error}'
if rollback_errors:
report = ('Hydra OS update: rollback incomplete; the runtime may contain mixed versions.\n'
f'Retained backup: {backup}\n'
'Manual recovery records: ' + str(backup / 'backup.json') + '\n' +
'\n'.join(f' {name}: {error}' for name, error in rollback_errors.items()))
apply_error.add_note(report)
print(report, file=sys.stderr)
raise
result.update(applied=True, backup=str(backup))
return result