|
1 | 1 | package instances |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "context" |
5 | 4 | "os" |
6 | 5 | "path/filepath" |
7 | 6 | "syscall" |
8 | 7 | "testing" |
9 | 8 |
|
10 | | - "github.com/kernel/hypeman/lib/hypervisor" |
11 | 9 | "github.com/stretchr/testify/assert" |
12 | 10 | "github.com/stretchr/testify/require" |
13 | 11 | ) |
@@ -61,76 +59,6 @@ func TestInstallForkSharedMemFile_ErrorsWhenSourceMissing(t *testing.T) { |
61 | 59 | require.Error(t, err) |
62 | 60 | } |
63 | 61 |
|
64 | | -// TestForkFirecrackerSharesMemFile_FromTemplate verifies the end-to-end fork |
65 | | -// path: when the source is a Firecracker Template instance, the fork's |
66 | | -// mem-file is a hardlink to the source's mem-file instead of a copy. This |
67 | | -// preserves the firecracker MAP_PRIVATE COW semantics that let multiple forks |
68 | | -// share the heavy backing file. |
69 | | -func TestForkFirecrackerSharesMemFile_FromTemplate(t *testing.T) { |
70 | | - t.Parallel() |
71 | | - |
72 | | - mgr, _ := setupTestManager(t) |
73 | | - ctx := context.Background() |
74 | | - |
75 | | - sourceID := "shared-memfile-fc-src" |
76 | | - createStandbySnapshotSourceFixture(t, mgr, sourceID, "shared-memfile-fc-src", hypervisor.TypeFirecracker) |
77 | | - promoteFixtureToTemplate(t, mgr, sourceID) |
78 | | - |
79 | | - srcSnapshotDir := mgr.paths.InstanceSnapshotLatest(sourceID) |
80 | | - srcMem := filepath.Join(srcSnapshotDir, templateSharedMemFileName) |
81 | | - require.NoError(t, os.WriteFile(srcMem, []byte("firecracker mem-file contents"), 0o644)) |
82 | | - snapshotConfigPath := mgr.paths.InstanceSnapshotConfig(sourceID) |
83 | | - require.NoError(t, os.MkdirAll(filepath.Dir(snapshotConfigPath), 0o755)) |
84 | | - require.NoError(t, os.WriteFile(snapshotConfigPath, []byte(`{}`), 0o644)) |
85 | | - |
86 | | - forked, err := mgr.forkInstanceFromStoppedOrStandby(ctx, sourceID, ForkInstanceRequest{ |
87 | | - Name: "shared-memfile-fc-fork", |
88 | | - TargetState: StateStopped, |
89 | | - }, true) |
90 | | - require.NoError(t, err) |
91 | | - require.NotNil(t, forked) |
92 | | - |
93 | | - forkMem := filepath.Join(mgr.paths.InstanceSnapshotLatest(forked.Id), templateSharedMemFileName) |
94 | | - info, err := os.Lstat(forkMem) |
95 | | - require.NoError(t, err) |
96 | | - assert.True(t, info.Mode().IsRegular(), "fork mem-file must be a regular file (hardlink) for firecracker fan-out") |
97 | | - assert.True(t, sameInode(t, srcMem, forkMem), "fork mem-file must share the source's inode") |
98 | | -} |
99 | | - |
100 | | -// TestForkFirecrackerStandbySourceDoesNotShareMemFile guards the |
101 | | -// non-Template carve-out: forking a plain Standby source must copy the |
102 | | -// mem-file outright. Sharing would let a later RestoreInstance on the source |
103 | | -// mutate the file out from under live forks. |
104 | | -func TestForkFirecrackerStandbySourceDoesNotShareMemFile(t *testing.T) { |
105 | | - t.Parallel() |
106 | | - |
107 | | - mgr, _ := setupTestManager(t) |
108 | | - ctx := context.Background() |
109 | | - |
110 | | - sourceID := "standby-fork-fc-src" |
111 | | - createStandbySnapshotSourceFixture(t, mgr, sourceID, "standby-fork-fc-src", hypervisor.TypeFirecracker) |
112 | | - |
113 | | - srcSnapshotDir := mgr.paths.InstanceSnapshotLatest(sourceID) |
114 | | - srcMem := filepath.Join(srcSnapshotDir, templateSharedMemFileName) |
115 | | - require.NoError(t, os.WriteFile(srcMem, []byte("firecracker mem-file contents"), 0o644)) |
116 | | - snapshotConfigPath := mgr.paths.InstanceSnapshotConfig(sourceID) |
117 | | - require.NoError(t, os.MkdirAll(filepath.Dir(snapshotConfigPath), 0o755)) |
118 | | - require.NoError(t, os.WriteFile(snapshotConfigPath, []byte(`{}`), 0o644)) |
119 | | - |
120 | | - forked, err := mgr.forkInstanceFromStoppedOrStandby(ctx, sourceID, ForkInstanceRequest{ |
121 | | - Name: "standby-fork-fc-fork", |
122 | | - TargetState: StateStopped, |
123 | | - }, true) |
124 | | - require.NoError(t, err) |
125 | | - require.NotNil(t, forked) |
126 | | - |
127 | | - forkMem := filepath.Join(mgr.paths.InstanceSnapshotLatest(forked.Id), templateSharedMemFileName) |
128 | | - info, err := os.Lstat(forkMem) |
129 | | - require.NoError(t, err) |
130 | | - require.True(t, info.Mode().IsRegular(), "standby-source fork mem-file must be a regular file copy") |
131 | | - assert.False(t, sameInode(t, srcMem, forkMem), "standby-source fork mem-file must be a copy, not a hardlink to source") |
132 | | -} |
133 | | - |
134 | 62 | // promoteFixtureToTemplate marks the source's stored metadata as a Template |
135 | 63 | // without invoking the full PromoteToTemplate lifecycle (which would require |
136 | 64 | // a live VM). Test-only shortcut. |
|
0 commit comments