Protect dedicated staging disk and document verified migration

This commit is contained in:
admin committed 2026-10-27 19:38:37 +01:00
1 parent 5ab3d078fb
commit 46644e5041
7 files changed
+158 -4

No files matched your search

+34
View File
@@ -70,6 +70,39 @@ class BackupTests(unittest.TestCase):
with self.assertRaisesRegex(m.BackupError, 'unowned'):
self.runner.staging_preflight(self.manifest())
def test_dedicated_stage_mount_missing_or_wrong_uuid_does_not_create_directory(self):
disk = self.root/'disk'
self.runner.stage = disk/'private/staging'
for actual in ({'target': '/', 'uuid': 'system-disk', 'fstype': 'btrfs'},
{'target': str(disk), 'uuid': 'wrong-disk', 'fstype': 'btrfs'}):
with self.subTest(actual=actual), patch.dict(os.environ, {
'EXPECTED_STAGE_MOUNT': str(disk), 'EXPECTED_STAGE_UUID': 'archive-disk'}), \
patch.object(self.runner, 'run', return_value=json.dumps({'filesystems': [actual]})):
with self.assertRaisesRegex(m.BackupError, 'missing or has the wrong identity'):
self.runner.staging_preflight(self.manifest())
self.assertFalse(disk.exists())
def test_dedicated_stage_mount_verified_before_owned_stage_creation(self):
disk = self.root/'disk'
disk.mkdir()
self.runner.stage = disk/'staging'
with patch.dict(os.environ, {'EXPECTED_STAGE_MOUNT': str(disk), 'EXPECTED_STAGE_UUID': 'archive-disk'}), \
patch.object(self.runner, 'run', side_effect=[json.dumps({'filesystems': [
{'target': str(disk), 'uuid': 'archive-disk', 'fstype': 'btrfs'}]}),
json.dumps({'filesystems': [{'fstype': 'btrfs'}]})]):
self.runner.staging_preflight(self.manifest())
self.assertEqual(m.read_json(disk/'staging.owner.json'),
{'remote': self.runner.remote, 'stage': str(self.runner.stage)})
def test_dedicated_stage_mount_configuration_must_be_paired_and_contain_stage(self):
for values in ({'EXPECTED_STAGE_MOUNT': str(self.root), 'EXPECTED_STAGE_UUID': ''},
{'EXPECTED_STAGE_MOUNT': '', 'EXPECTED_STAGE_UUID': 'archive-disk'},
{'EXPECTED_STAGE_MOUNT': str(self.root/'other-disk'), 'EXPECTED_STAGE_UUID': 'archive-disk'}):
with self.subTest(values=values), patch.dict(os.environ, values):
with self.assertRaises(m.BackupError):
self.runner.staging_preflight(self.manifest())
self.assertFalse(self.runner.stage.exists())
def test_subprocess_failure_never_becomes_success(self):
with patch.object(self.runner, 'perform', side_effect=m.BackupError('network failure')), \
patch.object(self.runner, 'notify') as notify:
@@ -221,6 +254,7 @@ class BackupTests(unittest.TestCase):
self.runner.backup()
success = m.read_json(self.runner.success_file)
self.assertEqual(success['files'], 2)
self.assertEqual(success['stage'], str(self.runner.stage))
dest = self.root/'restore'
dest.mkdir()
subprocess.run(['borg', 'extract', f'{self.runner.repo}::{success["archive"]}'],