Skip to content

Commit 3321f0a

Browse files
committed
test: verify the guest of a VM created from a backup, not just that it boots
The chain test checked an Instance created from a backup only for reaching Running. That proves the image boots; it says nothing about whether the diff chain was replayed into the new volume correctly, so a create-from-backup that produced a stale or empty image would still have passed. Check the guest the same way an in-place restore is checked: the markers taken up to that backup must be present, and markers written after it must be absent. The absent half matters as much as the present half -- without it, a VM that somehow came up with the source Instance's current disk would pass. Access uses the pattern already proven by test_incremental_after_vm_restart: the backup carries the source Instance's authorized_keys, so the new VM accepts the same keypair and the stock cloud-image "ubuntu" user.
1 parent a4a8c27 commit 3321f0a

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

‎test/integration/smoke/test_backup_recovery_nas.py‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,14 @@ def _restore_in_place_and_check(self, backup, expected_markers, absent_markers,
899899
"%s: marker %s was written AFTER this backup, so the restore should have "
900900
"rolled it back" % (context, marker))
901901

902-
def _create_vm_from_backup_and_check(self, backup, context):
903-
"""Build a VM from a backup and confirm it reaches Running, then clean it up."""
902+
def _create_vm_from_backup_and_check(self, backup, expected_markers, absent_markers, context):
903+
"""Build a VM from a backup and verify the guest it comes up with.
904+
905+
Reaching Running only proves the image boots. The markers are what prove the
906+
diff chain was replayed into the new volume correctly, so the guest is checked
907+
the same way an in-place restore is -- markers taken up to this backup present,
908+
markers written after it absent.
909+
"""
904910
name = "chain-%s-%d" % (context, int(time.time()))
905911
new_vm = Backup.createVMFromBackup(
906912
self.apiclient,
@@ -920,6 +926,20 @@ def _create_vm_from_backup_and_check(self, backup, context):
920926
self.assertTrue(vms and str(vms[0].state).lower() == "running",
921927
"%s: VM created from the backup is not Running (state=%s)"
922928
% (context, vms[0].state if vms else "<not listed>"))
929+
930+
# The backup carries the source Instance's authorized_keys, so the new VM
931+
# accepts the same keypair and the stock cloud-image "ubuntu" user.
932+
new_vm.username = "ubuntu"
933+
ssh_new = new_vm.get_ssh_client(reconnect=True, keyPairFileLocation=self.ssh_key_file)
934+
listing = "".join(ssh_new.execute(self._sudo("ls /root")))
935+
for marker in expected_markers:
936+
self.assertIn(marker, listing,
937+
"%s: marker %s written before this backup is missing from the VM created "
938+
"from it" % (context, marker))
939+
for marker in absent_markers:
940+
self.assertNotIn(marker, listing,
941+
"%s: marker %s was written AFTER this backup, so a VM created from it "
942+
"should not have it" % (context, marker))
923943
finally:
924944
# Destroyed as we go rather than via cls._cleanup: this test builds seven
925945
# of these, and keeping them all alive to the end risks exhausting the
@@ -969,7 +989,8 @@ def test_full_chain_restore_and_create_vm_survive_mid_chain_delete(self):
969989
self._restore_in_place_and_check(
970990
backup, markers[:idx + 1], markers[idx + 1:], "complete chain, backup %d" % idx)
971991
for idx, backup in enumerate(backups):
972-
self._create_vm_from_backup_and_check(backup, "full%d" % idx)
992+
self._create_vm_from_backup_and_check(
993+
backup, markers[:idx + 1], markers[idx + 1:], "full%d" % idx)
973994

974995
# --- delete the 2nd incremental --------------------------------------
975996
# Its diff stays on the repository while INC3 still needs it to replay;
@@ -999,7 +1020,8 @@ def test_full_chain_restore_and_create_vm_survive_mid_chain_delete(self):
9991020
self._restore_in_place_and_check(
10001021
backup, expected[idx], absent[idx], "after delete, backup %d" % idx)
10011022
for idx, backup in enumerate(survivors):
1002-
self._create_vm_from_backup_and_check(backup, "post%d" % idx)
1023+
self._create_vm_from_backup_and_check(
1024+
backup, expected[idx], absent[idx], "post%d" % idx)
10031025

10041026
# --- the chain must leave nothing behind ------------------------------
10051027
for backup in reversed(survivors):

0 commit comments

Comments
 (0)