Skip to content

Commit fde4760

Browse files
roypatCompuIves
andcommitted
test: Add a test for taking diff snapshots on top of full snapshots
The test first crates a full snapshot, and then takes a diff snapshot with the same memory file, to merge it. We take both snapshots as "diff" snapshots, as taking a full snapshot does not clear the dirty pages tracked (and in this test, we want to exercise the path where the second diff snapshot only writes a few pages). Signed-off-by: Patrick Roy <[email protected]> Co-authored-by: Ives van Hoorne <[email protected]>
1 parent f00eab8 commit fde4760

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

tests/integration_tests/functional/test_snapshot_basic.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import logging
77
import os
88
import re
9+
import shutil
910
from pathlib import Path
1011

1112
import pytest
@@ -411,3 +412,49 @@ def test_create_large_diff_snapshot(test_microvm_with_api):
411412

412413
# If the regression was not fixed, this would have failed. The Firecracker
413414
# process would have been taken down.
415+
416+
417+
def test_diff_snapshot_overlay(guest_kernel, rootfs, microvm_factory):
418+
"""
419+
Tests that if we take a diff snapshot and direct firecracker to write it on
420+
top of an existing snapshot file, it will successfully merge them.
421+
"""
422+
basevm = microvm_factory.build(guest_kernel, rootfs)
423+
basevm.spawn()
424+
basevm.basic_config(track_dirty_pages=True)
425+
basevm.add_net_iface()
426+
basevm.start()
427+
428+
# Wait for microvm to be booted
429+
rc, _, stderr = basevm.ssh.run("true")
430+
assert rc == 0, stderr
431+
432+
# The first snapshot taken will always contain all memory (even if its specified as "diff").
433+
# We use a diff snapshot here, as taking a full snapshot does not clear the dirty page tracking,
434+
# meaning the `snapshot_diff()` call below would again dump the entire guest memory instead of
435+
# only dirty regions.
436+
full_snapshot = basevm.snapshot_diff()
437+
basevm.resume()
438+
439+
# Run some command to dirty some pages
440+
rc, _, stderr = basevm.ssh.run("true")
441+
assert rc == 0, stderr
442+
443+
# First copy the base snapshot somewhere else, so we can make sure
444+
# it will actually get updated
445+
first_snapshot_backup = Path(basevm.chroot()) / "mem.old"
446+
shutil.copyfile(full_snapshot.mem, first_snapshot_backup)
447+
448+
# One Microvm object will always write its snapshot files to the same location
449+
merged_snapshot = basevm.snapshot_diff()
450+
assert full_snapshot.mem == merged_snapshot.mem
451+
452+
assert not filecmp.cmp(merged_snapshot.mem, first_snapshot_backup, shallow=False)
453+
454+
new_vm = microvm_factory.build()
455+
new_vm.spawn()
456+
new_vm.restore_from_snapshot(merged_snapshot, resume=True)
457+
458+
# Run some command to check that the restored VM works
459+
rc, _, stderr = new_vm.ssh.run("true")
460+
assert rc == 0, stderr

0 commit comments

Comments
 (0)