Continue guest-update rollback after individual restore failures
This commit is contained in:
+23
-10
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user