|
7 | 7 | "path/filepath" |
8 | 8 | "sync" |
9 | 9 | "testing" |
| 10 | + "time" |
10 | 11 |
|
11 | 12 | "github.com/kernel/hypeman/lib/devices" |
12 | 13 | "github.com/kernel/hypeman/lib/paths" |
@@ -180,13 +181,68 @@ func TestStartRollbackRetainsVGPUAssignmentAfterFailedDestroy(t *testing.T) { |
180 | 181 | }) |
181 | 182 |
|
182 | 183 | t.Setenv("TMPDIR", filepath.Join(t.TempDir(), "missing")) |
183 | | - _, err := m.startInstance(context.Background(), id, StartInstanceRequest{}) |
| 184 | + _, err := m.startInstance(context.Background(), id, StartInstanceRequest{Entrypoint: []string{"new-entrypoint"}}) |
184 | 185 | require.Error(t, err) |
185 | 186 |
|
186 | 187 | stored, err := m.loadMetadata(id) |
187 | 188 | require.NoError(t, err) |
188 | 189 | assert.Equal(t, devices.VGPUFrameworkVendorVFIO, stored.GPUFramework) |
189 | 190 | assert.Equal(t, "/sys/bus/pci/devices/0000:82:00.4", stored.GPUDevicePath) |
| 191 | + assert.NotNil(t, stored.GPUAssignedAt) |
| 192 | + assert.Empty(t, stored.Entrypoint) |
| 193 | +} |
| 194 | + |
| 195 | +func TestCleanupStartVGPURestoresMetadataAfterBootFailure(t *testing.T) { |
| 196 | + m := &manager{ |
| 197 | + paths: paths.New(t.TempDir()), |
| 198 | + destroyVGPU: func(context.Context, devices.VGPUAssignment) error { |
| 199 | + return nil |
| 200 | + }, |
| 201 | + } |
| 202 | + const id = "failed-start" |
| 203 | + require.NoError(t, m.ensureDirectories(id)) |
| 204 | + |
| 205 | + previousStart := time.Now().Add(-time.Hour).UTC() |
| 206 | + previousProgramStart := previousStart.Add(time.Second) |
| 207 | + exitCode := 1 |
| 208 | + rollbackMeta := metadata{StoredMetadata: StoredMetadata{ |
| 209 | + Id: id, |
| 210 | + GPUProfile: "NVIDIA L40S-2Q", |
| 211 | + Entrypoint: []string{"old-entrypoint"}, |
| 212 | + Cmd: []string{"old-command"}, |
| 213 | + StartedAt: &previousStart, |
| 214 | + ProgramStartedAt: &previousProgramStart, |
| 215 | + ExitCode: &exitCode, |
| 216 | + ExitMessage: "previous exit", |
| 217 | + }} |
| 218 | + |
| 219 | + partial := rollbackMeta |
| 220 | + partial.Entrypoint = []string{"new-entrypoint"} |
| 221 | + partial.Cmd = []string{"new-command"} |
| 222 | + partial.StartedAt = ptr(time.Now().UTC()) |
| 223 | + partial.ProgramStartedAt = nil |
| 224 | + partial.ExitCode = nil |
| 225 | + partial.ExitMessage = "" |
| 226 | + assignedAt := time.Now().UTC() |
| 227 | + device := &devices.VGPUDevice{ |
| 228 | + Framework: devices.VGPUFrameworkVendorVFIO, |
| 229 | + SysfsPath: "/sys/bus/pci/devices/0000:82:00.4", |
| 230 | + } |
| 231 | + setStoredVGPUDevice(&partial.StoredMetadata, device, assignedAt) |
| 232 | + require.NoError(t, m.saveMetadata(&partial)) |
| 233 | + |
| 234 | + m.cleanupStartVGPU(context.Background(), id, device, assignedAt, rollbackMeta) |
| 235 | + |
| 236 | + stored, err := m.loadMetadata(id) |
| 237 | + require.NoError(t, err) |
| 238 | + assert.Equal(t, rollbackMeta.Entrypoint, stored.Entrypoint) |
| 239 | + assert.Equal(t, rollbackMeta.Cmd, stored.Cmd) |
| 240 | + assert.Equal(t, rollbackMeta.StartedAt, stored.StartedAt) |
| 241 | + assert.Equal(t, rollbackMeta.ProgramStartedAt, stored.ProgramStartedAt) |
| 242 | + assert.Equal(t, rollbackMeta.ExitCode, stored.ExitCode) |
| 243 | + assert.Equal(t, rollbackMeta.ExitMessage, stored.ExitMessage) |
| 244 | + assert.Empty(t, stored.GPUDevicePath) |
| 245 | + assert.Nil(t, stored.GPUAssignedAt) |
190 | 246 | } |
191 | 247 |
|
192 | 248 | func TestVGPUAssignmentClaimedByLiveInstanceFailsOnInvalidMetadata(t *testing.T) { |
@@ -333,16 +389,19 @@ func TestReleaseStoredVGPURetainsMetadataOnFailure(t *testing.T) { |
333 | 389 | func TestSetAndClearStoredVGPUDevice(t *testing.T) { |
334 | 390 | t.Parallel() |
335 | 391 |
|
| 392 | + assignedAt := time.Now().UTC() |
336 | 393 | stored := &StoredMetadata{} |
337 | 394 | setStoredVGPUDevice(stored, &devices.VGPUDevice{ |
338 | 395 | Framework: devices.VGPUFrameworkVendorVFIO, |
339 | 396 | SysfsPath: "/sys/bus/pci/devices/0000:82:00.4", |
340 | | - }) |
| 397 | + }, assignedAt) |
341 | 398 | assert.Equal(t, devices.VGPUFrameworkVendorVFIO, stored.GPUFramework) |
342 | 399 | assert.Equal(t, "/sys/bus/pci/devices/0000:82:00.4", stored.GPUDevicePath) |
| 400 | + assert.Equal(t, assignedAt, *stored.GPUAssignedAt) |
343 | 401 |
|
344 | 402 | clearStoredVGPUDevice(stored) |
345 | 403 | assert.Empty(t, stored.GPUFramework) |
346 | 404 | assert.Empty(t, stored.GPUDevicePath) |
347 | 405 | assert.Empty(t, stored.GPUMdevUUID) |
| 406 | + assert.Nil(t, stored.GPUAssignedAt) |
348 | 407 | } |
0 commit comments