13
"github.com/checkpoint-restore/go-criu/v7/stats"
14
"github.com/containers/podman/v5/pkg/checkpoint/crutils"
15
"github.com/containers/podman/v5/pkg/criu"
16
"github.com/containers/podman/v5/pkg/domain/entities"
17
. "github.com/containers/podman/v5/test/utils"
18
"github.com/containers/podman/v5/utils"
19
. "github.com/onsi/ginkgo/v2"
20
. "github.com/onsi/gomega"
21
. "github.com/onsi/gomega/gexec"
26
func getRunString(input []string) []string {
27
runString := []string{"run", "-d", "--network", netname}
28
return append(runString, input...)
31
var _ = Describe("Podman checkpoint", func() {
34
SkipIfRootless("checkpoint not supported in rootless mode")
36
// Check if the runtime implements checkpointing. Currently only
37
// runc's checkpoint/restore implementation is supported.
38
cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help")
39
if err := cmd.Start(); err != nil {
40
Skip("OCI runtime does not support checkpoint/restore")
42
if err := cmd.Wait(); err != nil {
43
Skip("OCI runtime does not support checkpoint/restore")
46
if err := criu.CheckForCriu(criu.MinCriuVersion); err != nil {
47
Skip(fmt.Sprintf("check CRIU version error: %v", err))
50
session := podmanTest.Podman([]string{"network", "create"})
51
session.WaitWithDefaultTimeout()
52
Expect(session).Should(ExitCleanly())
53
netname = session.OutputToString()
58
session := podmanTest.Podman([]string{"network", "rm", "-f", netname})
59
session.WaitWithDefaultTimeout()
60
Expect(session).Should(ExitCleanly())
64
It("podman checkpoint bogus container", func() {
65
session := podmanTest.Podman([]string{"container", "checkpoint", "foobar"})
66
session.WaitWithDefaultTimeout()
67
Expect(session).Should(ExitWithError(125, "no such container"))
70
It("podman restore bogus container", func() {
71
session := podmanTest.Podman([]string{"container", "restore", "foobar"})
72
session.WaitWithDefaultTimeout()
73
Expect(session).Should(ExitWithError(125, "no such container or image"))
76
It("podman checkpoint a running container by id", func() {
77
localRunString := getRunString([]string{ALPINE, "top"})
78
session := podmanTest.Podman(localRunString)
79
session.WaitWithDefaultTimeout()
80
Expect(session).Should(ExitCleanly())
81
cid := session.OutputToString()
83
// Check if none of the checkpoint/restore specific information is displayed
84
// for newly started containers.
85
inspect := podmanTest.Podman([]string{"inspect", cid})
86
inspect.WaitWithDefaultTimeout()
87
Expect(inspect).Should(ExitCleanly())
88
inspectOut := inspect.InspectContainerToJSON()
89
Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
90
Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
91
Expect(inspectOut[0].State).To(HaveField("CheckpointPath", ""))
92
Expect(inspectOut[0].State).To(HaveField("CheckpointLog", ""))
93
Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
95
result := podmanTest.Podman([]string{
101
result.WaitWithDefaultTimeout()
103
Expect(result).Should(ExitCleanly())
104
Expect(result.OutputToString()).To(Equal(cid))
105
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
106
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
108
// For a checkpointed container we expect the checkpoint related information
110
inspect = podmanTest.Podman([]string{"inspect", cid})
111
inspect.WaitWithDefaultTimeout()
112
Expect(inspect).Should(ExitCleanly())
113
inspectOut = inspect.InspectContainerToJSON()
114
Expect(inspectOut[0].State.Checkpointed).To(BeTrue(), ".State.Checkpointed")
115
Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
116
Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
117
Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
118
Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
120
result = podmanTest.Podman([]string{
126
result.WaitWithDefaultTimeout()
128
Expect(result).Should(ExitCleanly())
129
Expect(result.OutputToString()).To(Equal(cid))
130
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
131
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
133
inspect = podmanTest.Podman([]string{"inspect", cid})
134
inspect.WaitWithDefaultTimeout()
135
Expect(inspect).Should(ExitCleanly())
136
inspectOut = inspect.InspectContainerToJSON()
137
Expect(inspectOut[0].State.Restored).To(BeTrue(), ".State.Restored")
138
Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
139
Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
140
Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
141
Expect(inspectOut[0].State.RestoreLog).To(ContainSubstring("userdata/restore.log"))
143
podmanTest.StopContainer(cid)
144
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
146
result = podmanTest.Podman([]string{
151
result.WaitWithDefaultTimeout()
153
Expect(result).Should(ExitCleanly())
154
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
156
// Stopping and starting the container should remove all checkpoint
157
// related information from inspect again.
158
inspect = podmanTest.Podman([]string{"inspect", cid})
159
inspect.WaitWithDefaultTimeout()
160
Expect(inspect).Should(ExitCleanly())
161
inspectOut = inspect.InspectContainerToJSON()
162
Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
163
Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
164
Expect(inspectOut[0].State).To(HaveField("CheckpointPath", ""))
165
Expect(inspectOut[0].State).To(HaveField("CheckpointLog", ""))
166
Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
169
It("podman checkpoint a running container by name", func() {
170
localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"})
171
session := podmanTest.Podman(localRunString)
172
session.WaitWithDefaultTimeout()
173
Expect(session).Should(ExitCleanly())
175
result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
176
result.WaitWithDefaultTimeout()
178
Expect(result).Should(ExitCleanly())
179
Expect(result.OutputToString()).To(Equal("test_name"))
180
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
181
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
183
result = podmanTest.Podman([]string{"container", "restore", "test_name"})
184
result.WaitWithDefaultTimeout()
186
Expect(result).Should(ExitCleanly())
187
Expect(result.OutputToString()).To(Equal("test_name"))
188
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
189
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
191
// Restore a container which name is equal to an image name (#15055)
192
localRunString = getRunString([]string{"--name", "alpine", "quay.io/libpod/alpine:latest", "top"})
193
session = podmanTest.Podman(localRunString)
194
session.WaitWithDefaultTimeout()
195
Expect(session).Should(ExitCleanly())
197
result = podmanTest.Podman([]string{"container", "checkpoint", "alpine"})
198
result.WaitWithDefaultTimeout()
200
Expect(result).Should(ExitCleanly())
201
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
202
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
204
result = podmanTest.Podman([]string{"container", "restore", "alpine"})
205
result.WaitWithDefaultTimeout()
207
Expect(result).Should(ExitCleanly())
208
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
209
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
212
It("podman pause a checkpointed container by id", func() {
213
localRunString := getRunString([]string{ALPINE, "top"})
214
session := podmanTest.Podman(localRunString)
215
session.WaitWithDefaultTimeout()
216
Expect(session).Should(ExitCleanly())
217
cid := session.OutputToString()
219
result := podmanTest.Podman([]string{"container", "checkpoint", cid})
220
result.WaitWithDefaultTimeout()
222
Expect(result).Should(ExitCleanly())
223
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
224
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
226
result = podmanTest.Podman([]string{"pause", cid})
227
result.WaitWithDefaultTimeout()
229
Expect(result).Should(ExitWithError(125, `"exited" is not running, can't pause: container state improper`))
230
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
231
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
233
result = podmanTest.Podman([]string{"container", "restore", cid})
234
result.WaitWithDefaultTimeout()
235
Expect(result).Should(ExitCleanly())
236
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
238
result = podmanTest.Podman([]string{"rm", cid})
239
result.WaitWithDefaultTimeout()
240
Expect(result).Should(ExitWithError(2, " as it is running - running or paused containers cannot be removed without force: container state improper"))
241
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
243
result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", cid})
244
result.WaitWithDefaultTimeout()
245
Expect(result).Should(ExitCleanly())
246
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
250
It("podman checkpoint latest running container", func() {
251
localRunString := getRunString([]string{"--name", "first", ALPINE, "top"})
252
session1 := podmanTest.Podman(localRunString)
253
session1.WaitWithDefaultTimeout()
254
Expect(session1).Should(ExitCleanly())
256
localRunString = getRunString([]string{"--name", "second", ALPINE, "top"})
257
session2 := podmanTest.Podman(localRunString)
258
session2.WaitWithDefaultTimeout()
259
Expect(session2).Should(ExitCleanly())
261
result := podmanTest.Podman([]string{"container", "checkpoint", "second"})
262
result.WaitWithDefaultTimeout()
264
Expect(result).Should(ExitCleanly())
265
Expect(result.OutputToString()).To(Equal("second"))
266
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
268
ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
269
ps.WaitWithDefaultTimeout()
270
Expect(ps).Should(ExitCleanly())
271
Expect(ps.OutputToString()).To(ContainSubstring(session1.OutputToString()))
272
Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
274
result = podmanTest.Podman([]string{"container", "restore", "second"})
275
result.WaitWithDefaultTimeout()
277
Expect(result).Should(ExitCleanly())
278
Expect(result.OutputToString()).To(Equal("second"))
279
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
280
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
281
Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
283
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
284
result.WaitWithDefaultTimeout()
285
Expect(result).Should(ExitCleanly())
286
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
289
It("podman checkpoint all running container", func() {
290
localRunString := getRunString([]string{"--name", "first", ALPINE, "top"})
291
session1 := podmanTest.Podman(localRunString)
292
session1.WaitWithDefaultTimeout()
293
Expect(session1).Should(ExitCleanly())
294
cid1 := session1.OutputToString()
296
localRunString = getRunString([]string{"--name", "second", ALPINE, "top"})
297
session2 := podmanTest.Podman(localRunString)
298
session2.WaitWithDefaultTimeout()
299
Expect(session2).Should(ExitCleanly())
300
cid2 := session2.OutputToString()
302
result := podmanTest.Podman([]string{"container", "checkpoint", "-a"})
303
result.WaitWithDefaultTimeout()
305
Expect(result).Should(ExitCleanly())
306
Expect(result.OutputToString()).To(ContainSubstring(cid1))
307
Expect(result.OutputToString()).To(ContainSubstring(cid2))
308
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
310
ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
311
ps.WaitWithDefaultTimeout()
312
Expect(ps).Should(ExitCleanly())
313
Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
314
Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
316
result = podmanTest.Podman([]string{"container", "restore", "-a"})
317
result.WaitWithDefaultTimeout()
319
Expect(result).Should(ExitCleanly())
320
Expect(result.OutputToString()).To(ContainSubstring(cid1))
321
Expect(result.OutputToString()).To(ContainSubstring(cid2))
322
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
323
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
324
Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
326
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
327
result.WaitWithDefaultTimeout()
328
Expect(result).Should(ExitCleanly())
329
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
332
It("podman checkpoint container with established tcp connections", func() {
333
localRunString := getRunString([]string{REDIS_IMAGE})
334
session := podmanTest.Podman(localRunString)
335
session.WaitWithDefaultTimeout()
336
Expect(session).Should(ExitCleanly())
337
cid := session.OutputToString()
338
if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
339
Fail("Container failed to get ready")
342
// clunky format needed because CNI uses dashes in net names
343
IP := podmanTest.Podman([]string{"inspect", cid, fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
344
IP.WaitWithDefaultTimeout()
345
Expect(IP).Should(ExitCleanly())
347
// Open a network connection to the redis server
348
conn, err := net.DialTimeout("tcp4", IP.OutputToString()+":6379", time.Duration(3)*time.Second)
349
Expect(err).ToNot(HaveOccurred())
351
// This should fail as the container has established TCP connections
352
result := podmanTest.Podman([]string{"container", "checkpoint", cid})
353
result.WaitWithDefaultTimeout()
355
// FIXME: criu emits an error message, but podman never sees it:
356
// "CRIU checkpointing failed -52. Please check CRIU logfile /...."
357
Expect(result).Should(ExitWithError(125, "failed: exit status 1"))
358
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
359
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
361
// Now it should work thanks to "--tcp-established"
362
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "--tcp-established"})
363
result.WaitWithDefaultTimeout()
365
Expect(result).Should(ExitCleanly())
366
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
367
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
369
// Restore should fail as the checkpoint image contains established TCP connections
370
result = podmanTest.Podman([]string{"container", "restore", cid})
371
result.WaitWithDefaultTimeout()
373
// FIXME: CRIU failure message not seen by podman (same as above)
374
Expect(result).Should(ExitWithError(125))
375
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
376
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
378
// Now it should work thanks to "--tcp-established"
379
result = podmanTest.Podman([]string{"container", "restore", cid, "--tcp-established"})
380
result.WaitWithDefaultTimeout()
382
Expect(result).Should(ExitCleanly())
383
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
384
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
386
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
387
result.WaitWithDefaultTimeout()
388
Expect(result).Should(ExitCleanly())
389
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
394
It("podman checkpoint with --leave-running", func() {
395
localRunString := getRunString([]string{ALPINE, "top"})
396
session := podmanTest.Podman(localRunString)
397
session.WaitWithDefaultTimeout()
398
Expect(session).Should(ExitCleanly())
399
cid := session.OutputToString()
401
// Checkpoint container, but leave it running
402
result := podmanTest.Podman([]string{"container", "checkpoint", "--leave-running", cid})
403
result.WaitWithDefaultTimeout()
405
Expect(result).Should(ExitCleanly())
406
// Make sure it is still running
407
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
408
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
410
// Stop the container
411
podmanTest.StopContainer(cid)
412
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
413
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
415
// Restore the stopped container from the previous checkpoint
416
result = podmanTest.Podman([]string{"container", "restore", cid})
417
result.WaitWithDefaultTimeout()
419
Expect(result).Should(ExitCleanly())
420
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
421
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
423
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
424
result.WaitWithDefaultTimeout()
425
Expect(result).Should(ExitCleanly())
426
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
429
It("podman checkpoint and restore container with same IP", func() {
430
localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"})
431
session := podmanTest.Podman(localRunString)
432
session.WaitWithDefaultTimeout()
433
Expect(session).Should(ExitCleanly())
435
// clunky format needed because CNI uses dashes in net names
436
IPBefore := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
437
IPBefore.WaitWithDefaultTimeout()
438
Expect(IPBefore).Should(ExitCleanly())
439
Expect(IPBefore.OutputToString()).To(MatchRegexp("^[0-9]+(\\.[0-9]+){3}$"))
441
MACBefore := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").MacAddress}}", netname)})
442
MACBefore.WaitWithDefaultTimeout()
443
Expect(MACBefore).Should(ExitCleanly())
444
Expect(MACBefore.OutputToString()).To(MatchRegexp("^[0-9a-f]{2}(:[0-9a-f]{2}){5}$"))
446
result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
447
result.WaitWithDefaultTimeout()
449
Expect(result).Should(ExitCleanly())
450
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
451
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
453
result = podmanTest.Podman([]string{"container", "restore", "test_name"})
454
result.WaitWithDefaultTimeout()
456
IPAfter := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
457
IPAfter.WaitWithDefaultTimeout()
458
Expect(IPAfter).Should(ExitCleanly())
460
MACAfter := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").MacAddress}}", netname)})
461
MACAfter.WaitWithDefaultTimeout()
462
Expect(MACAfter).Should(ExitCleanly())
464
// Check that IP address did not change between checkpointing and restoring
465
Expect(IPAfter.OutputToString()).To(Equal(IPBefore.OutputToString()))
467
// Check that MAC address did not change between checkpointing and restoring
468
Expect(MACAfter.OutputToString()).To(Equal(MACBefore.OutputToString()))
470
Expect(result).Should(ExitCleanly())
471
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
472
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
474
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
475
result.WaitWithDefaultTimeout()
476
Expect(result).Should(ExitCleanly())
477
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
480
// This test does the same steps which are necessary for migrating
481
// a container from one host to another
482
It("podman checkpoint container with export (migration)", func() {
483
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
484
session := podmanTest.Podman(localRunString)
485
session.WaitWithDefaultTimeout()
486
Expect(session).Should(ExitCleanly())
487
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
488
cid := session.OutputToString()
489
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
491
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
492
result.WaitWithDefaultTimeout()
494
// As the container has been started with '--rm' it will be completely
495
// cleaned up after checkpointing.
496
Expect(result).Should(ExitCleanly())
497
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
498
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
500
// Restore container the first time with different name.
501
// Using '--ignore-static-ip' as for parallel test runs
502
// each containers gets a random IP address via '--ip'.
503
// '--ignore-static-ip' tells the restore to use the next
504
// available IP address.
505
// First restore the container with a new name/ID to make
506
// sure nothing in the restored container depends on the
507
// original container.
508
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName, "-n", "restore_again", "--ignore-static-ip"})
509
result.WaitWithDefaultTimeout()
511
Expect(result).Should(ExitCleanly())
512
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
513
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
515
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
516
result.WaitWithDefaultTimeout()
518
Expect(result).Should(ExitCleanly())
519
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
520
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
522
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
523
result.WaitWithDefaultTimeout()
524
Expect(result).Should(ExitCleanly())
525
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
526
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
528
// Remove exported checkpoint
531
// This test does the same steps which are necessary for migrating
532
// a container from one host to another
533
It("podman checkpoint container with export and different compression algorithms", func() {
534
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
535
session := podmanTest.Podman(localRunString)
536
session.WaitWithDefaultTimeout()
537
Expect(session).Should(ExitCleanly())
538
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
539
cid := session.OutputToString()
540
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
542
// Checkpoint with the default algorithm
543
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
544
result.WaitWithDefaultTimeout()
546
// As the container has been started with '--rm' it will be completely
547
// cleaned up after checkpointing.
548
Expect(result).Should(ExitCleanly())
549
Expect(result.OutputToString()).To(ContainSubstring(cid))
550
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
551
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
554
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
555
result.WaitWithDefaultTimeout()
557
Expect(result).Should(ExitCleanly())
558
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
559
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
561
// Checkpoint with the zstd algorithm
562
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "--compress", "zstd"})
563
result.WaitWithDefaultTimeout()
565
// As the container has been started with '--rm' it will be completely
566
// cleaned up after checkpointing.
567
Expect(result).Should(ExitCleanly())
568
Expect(result.OutputToString()).To(ContainSubstring(cid))
569
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
570
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
573
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
574
result.WaitWithDefaultTimeout()
576
Expect(result).Should(ExitCleanly())
577
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
578
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
580
// Checkpoint with the none algorithm
581
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "none"})
582
result.WaitWithDefaultTimeout()
584
// As the container has been started with '--rm' it will be completely
585
// cleaned up after checkpointing.
586
Expect(result).Should(ExitCleanly())
587
Expect(result.OutputToString()).To(ContainSubstring(cid))
588
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
589
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
592
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
593
result.WaitWithDefaultTimeout()
595
Expect(result).Should(ExitCleanly())
596
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
597
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
599
// Checkpoint with the gzip algorithm
600
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "gzip"})
601
result.WaitWithDefaultTimeout()
603
// As the container has been started with '--rm' it will be completely
604
// cleaned up after checkpointing.
605
Expect(result).Should(ExitCleanly())
606
Expect(result.OutputToString()).To(ContainSubstring(cid))
607
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
608
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
611
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
612
result.WaitWithDefaultTimeout()
614
Expect(result).Should(ExitCleanly())
615
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
616
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
618
// Checkpoint with the non-existing algorithm
619
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "non-existing"})
620
result.WaitWithDefaultTimeout()
622
Expect(result).Should(ExitWithError(125, `selected compression algorithm ("non-existing") not supported. Please select one from`))
623
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
624
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
626
result = podmanTest.Podman([]string{"rm", "--time", "0", "-fa"})
627
result.WaitWithDefaultTimeout()
628
Expect(result).Should(ExitCleanly())
629
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
630
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
632
// Remove exported checkpoint
636
It("podman checkpoint and restore container with root file-system changes", func() {
637
// Start the container
638
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
639
session := podmanTest.Podman(localRunString)
640
session.WaitWithDefaultTimeout()
641
Expect(session).Should(ExitCleanly())
642
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
643
cid := session.OutputToString()
644
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
646
// Change the container's root file-system
647
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
648
result.WaitWithDefaultTimeout()
649
Expect(result).Should(ExitCleanly())
651
result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "rm /etc/motd"})
652
result.WaitWithDefaultTimeout()
653
Expect(result).Should(ExitCleanly())
655
result = podmanTest.Podman([]string{"diff", cid})
656
result.WaitWithDefaultTimeout()
657
Expect(result).Should(ExitCleanly())
658
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
659
Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
660
Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
661
Expect(result.OutputToStringArray()).To(HaveLen(3))
663
// Checkpoint the container
664
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
665
result.WaitWithDefaultTimeout()
667
Expect(result).Should(ExitCleanly())
668
Expect(result.OutputToString()).To(ContainSubstring(cid))
669
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
670
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
672
// Restore the container
673
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
674
result.WaitWithDefaultTimeout()
676
Expect(result).Should(ExitCleanly())
677
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
678
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
679
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
681
// Verify the changes to the container's root file-system
682
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
683
result.WaitWithDefaultTimeout()
684
Expect(result).Should(ExitCleanly())
685
Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
687
result = podmanTest.Podman([]string{"diff", cid})
688
result.WaitWithDefaultTimeout()
689
Expect(result).Should(ExitCleanly())
690
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
691
Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
692
Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
693
Expect(result.OutputToStringArray()).To(HaveLen(3))
695
// Remove exported checkpoint
698
It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during restore", func() {
699
// Start the container
700
// test that restore works without network namespace (https://github.com/containers/podman/issues/14389)
701
session := podmanTest.Podman([]string{"run", "--network=none", "-d", "--rm", ALPINE, "top"})
702
session.WaitWithDefaultTimeout()
703
Expect(session).Should(ExitCleanly())
704
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
705
cid := session.OutputToString()
706
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
708
// Change the container's root file-system
709
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
710
result.WaitWithDefaultTimeout()
711
Expect(result).Should(ExitCleanly())
713
// Checkpoint the container
714
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
715
result.WaitWithDefaultTimeout()
717
Expect(result).Should(ExitCleanly())
718
Expect(result.OutputToString()).To(ContainSubstring(cid))
719
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
720
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
722
// Restore the container
723
result = podmanTest.Podman([]string{"container", "restore", "--ignore-rootfs", "-i", fileName})
724
result.WaitWithDefaultTimeout()
726
Expect(result).Should(ExitCleanly())
727
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
728
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
729
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
731
// Verify the changes to the container's root file-system
732
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
733
result.WaitWithDefaultTimeout()
734
Expect(result).Should(ExitWithError(1, "cat: can't open '/test.output': No such file or directory"))
736
// Remove exported checkpoint
739
It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during checkpoint", func() {
740
// Start the container
741
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
742
session := podmanTest.Podman(localRunString)
743
session.WaitWithDefaultTimeout()
744
Expect(session).Should(ExitCleanly())
745
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
746
cid := session.OutputToString()
747
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
749
// Change the container's root file-system
750
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
751
result.WaitWithDefaultTimeout()
752
Expect(result).Should(ExitCleanly())
754
// Checkpoint the container
755
result = podmanTest.Podman([]string{"container", "checkpoint", "--ignore-rootfs", cid, "-e", fileName})
756
result.WaitWithDefaultTimeout()
758
Expect(result).Should(ExitCleanly())
759
Expect(result.OutputToString()).To(ContainSubstring(cid))
760
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
761
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
763
// Restore the container
764
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
765
result.WaitWithDefaultTimeout()
767
Expect(result).Should(ExitCleanly())
768
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
769
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
770
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
772
// Verify the changes to the container's root file-system
773
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
774
result.WaitWithDefaultTimeout()
775
Expect(result).Should(ExitWithError(1, "cat: can't open '/test.output': No such file or directory"))
777
// Remove exported checkpoint
781
It("podman checkpoint and run exec in restored container", func() {
782
// Start the container
783
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
784
session := podmanTest.Podman(localRunString)
785
session.WaitWithDefaultTimeout()
786
Expect(session).Should(ExitCleanly())
787
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
788
cid := session.OutputToString()
789
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
791
// Checkpoint the container
792
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
793
result.WaitWithDefaultTimeout()
795
Expect(result).Should(ExitCleanly())
796
Expect(result.OutputToString()).To(ContainSubstring(cid))
797
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
798
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
800
// Restore the container
801
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
802
result.WaitWithDefaultTimeout()
804
Expect(result).Should(ExitCleanly())
805
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
806
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
807
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
809
// Exec in the container
810
result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /test.output"})
811
result.WaitWithDefaultTimeout()
812
Expect(result).Should(ExitCleanly())
814
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
815
result.WaitWithDefaultTimeout()
816
Expect(result).Should(ExitCleanly())
817
Expect(result.OutputToString()).To(ContainSubstring(cid))
819
// Remove exported checkpoint
823
It("podman checkpoint a container started with --rm", func() {
824
// Start the container
825
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
826
session := podmanTest.Podman(localRunString)
827
session.WaitWithDefaultTimeout()
828
cid := session.OutputToString()
829
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
831
// Checkpoint the container - this should fail as it was started with --rm
832
result := podmanTest.Podman([]string{"container", "checkpoint", cid})
833
result.WaitWithDefaultTimeout()
834
Expect(result).To(ExitWithError(125, "cannot checkpoint containers that have been started with '--rm'"))
836
// Checkpointing with --export should still work
837
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
839
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
840
result.WaitWithDefaultTimeout()
842
// As the container has been started with '--rm' it will be completely
843
// cleaned up after checkpointing.
844
Expect(result).Should(ExitCleanly())
845
Expect(result.OutputToString()).To(ContainSubstring(cid))
846
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
847
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
849
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
850
result.WaitWithDefaultTimeout()
852
Expect(result).Should(ExitCleanly())
853
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
854
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
856
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
857
result.WaitWithDefaultTimeout()
858
Expect(result).Should(ExitCleanly())
859
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
860
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
862
// Remove exported checkpoint
866
It("podman checkpoint a container with volumes", func() {
867
session := podmanTest.Podman([]string{
868
"build", "-f", "build/basicalpine/Containerfile.volume", "-t", "test-cr-volume",
870
session.WaitWithDefaultTimeout()
871
Expect(session).Should(ExitCleanly())
873
// Start the container
874
localRunString := getRunString([]string{
877
"-v", "my-test-vol:/volume2",
881
session = podmanTest.Podman(localRunString)
882
session.WaitWithDefaultTimeout()
883
Expect(session).Should(ExitCleanly())
884
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
886
cid := session.OutputToString()
888
// Add file in volume0
889
result := podmanTest.Podman([]string{
890
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume0/test.output",
892
result.WaitWithDefaultTimeout()
893
Expect(result).Should(ExitCleanly())
895
// Add file in volume1
896
result = podmanTest.Podman([]string{
897
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume1/test.output",
899
result.WaitWithDefaultTimeout()
900
Expect(result).Should(ExitCleanly())
902
// Add file in volume2
903
result = podmanTest.Podman([]string{
904
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume2/test.output",
906
result.WaitWithDefaultTimeout()
907
Expect(result).Should(ExitCleanly())
909
checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
911
// Checkpoint the container
912
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
913
result.WaitWithDefaultTimeout()
914
Expect(result).Should(ExitCleanly())
915
Expect(result.OutputToString()).To(ContainSubstring(cid))
916
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
917
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
919
// Restore container should fail because named volume still exists
920
result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
921
result.WaitWithDefaultTimeout()
922
Expect(result).To(ExitWithError(125, "volume with name my-test-vol already exists. Use --ignore-volumes to not restore content of volumes"))
924
// Remove named volume
925
session = podmanTest.Podman([]string{"volume", "rm", "my-test-vol"})
926
session.WaitWithDefaultTimeout()
927
Expect(session).Should(ExitCleanly())
929
// Restoring container
930
result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
931
result.WaitWithDefaultTimeout()
932
Expect(result).Should(ExitCleanly())
933
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
934
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
935
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
937
// Validate volume0 content
938
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume0/test.output"})
939
result.WaitWithDefaultTimeout()
940
Expect(result).Should(ExitCleanly())
941
Expect(result.OutputToString()).To(ContainSubstring(cid))
943
// Validate volume1 content
944
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume1/test.output"})
945
result.WaitWithDefaultTimeout()
946
Expect(result).Should(ExitCleanly())
947
Expect(result.OutputToString()).To(ContainSubstring(cid))
949
// Validate volume2 content
950
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume2/test.output"})
951
result.WaitWithDefaultTimeout()
952
Expect(result).Should(ExitCleanly())
953
Expect(result.OutputToString()).To(ContainSubstring(cid))
955
// Remove exported checkpoint
956
os.Remove(checkpointFileName)
959
It("podman checkpoint container with --pre-checkpoint", func() {
960
if !criu.MemTrack() {
961
Skip("system (architecture/kernel/CRIU) does not support memory tracking")
963
localRunString := getRunString([]string{ALPINE, "top"})
964
session := podmanTest.Podman(localRunString)
965
session.WaitWithDefaultTimeout()
966
Expect(session).Should(ExitCleanly())
967
cid := session.OutputToString()
969
result := podmanTest.Podman([]string{"container", "checkpoint", "-P", cid})
970
result.WaitWithDefaultTimeout()
972
Expect(result).Should(ExitCleanly())
973
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
974
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
976
result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", cid})
977
result.WaitWithDefaultTimeout()
979
Expect(result).Should(ExitCleanly())
980
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
981
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
983
result = podmanTest.Podman([]string{"container", "restore", cid})
984
result.WaitWithDefaultTimeout()
986
Expect(result).Should(ExitCleanly())
987
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
988
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
991
It("podman checkpoint container with --pre-checkpoint and export (migration)", func() {
992
SkipIfRemote("--import-previous is not yet supported on the remote client")
993
if !criu.MemTrack() {
994
Skip("system (architecture/kernel/CRIU) does not support memory tracking")
996
localRunString := getRunString([]string{ALPINE, "top"})
997
session := podmanTest.Podman(localRunString)
998
session.WaitWithDefaultTimeout()
999
Expect(session).Should(ExitCleanly())
1000
cid := session.OutputToString()
1001
preCheckpointFileName := filepath.Join(podmanTest.TempDir, "/pre-checkpoint-"+cid+".tar.gz")
1002
checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1004
result := podmanTest.Podman([]string{"container", "checkpoint", "-P", "-e", preCheckpointFileName, cid})
1005
result.WaitWithDefaultTimeout()
1007
Expect(result).Should(ExitCleanly())
1008
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1009
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1011
result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", "-e", checkpointFileName, cid})
1012
result.WaitWithDefaultTimeout()
1014
Expect(result).Should(ExitCleanly())
1015
Expect(result.OutputToString()).To(ContainSubstring(cid))
1016
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1017
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
1019
result = podmanTest.Podman([]string{"rm", "-t", "0", "-f", cid})
1020
result.WaitWithDefaultTimeout()
1021
Expect(result).Should(ExitCleanly())
1022
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1024
result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName, "--import-previous", preCheckpointFileName})
1025
result.WaitWithDefaultTimeout()
1027
Expect(result).Should(ExitCleanly())
1028
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1029
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1031
os.Remove(checkpointFileName)
1032
os.Remove(preCheckpointFileName)
1035
It("podman checkpoint and restore container with different port mappings", func() {
1036
randomPort, err := utils.GetRandomPort()
1037
Expect(err).ShouldNot(HaveOccurred())
1038
localRunString := getRunString([]string{"-p", fmt.Sprintf("%d:6379", randomPort), "--rm", REDIS_IMAGE})
1039
session := podmanTest.Podman(localRunString)
1040
session.WaitWithDefaultTimeout()
1041
Expect(session).Should(ExitCleanly())
1042
cid := session.OutputToString()
1043
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1045
if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
1046
Fail("Container failed to get ready")
1049
GinkgoWriter.Printf("Trying to connect to redis server at localhost:%d\n", randomPort)
1050
// Open a network connection to the redis server via initial port mapping
1051
conn, err := net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
1052
Expect(err).ShouldNot(HaveOccurred())
1055
// Checkpoint the container
1056
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
1057
result.WaitWithDefaultTimeout()
1059
// As the container has been started with '--rm' it will be completely
1060
// cleaned up after checkpointing.
1061
Expect(result).Should(ExitCleanly())
1062
Expect(result.OutputToString()).To(ContainSubstring(cid))
1063
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1064
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1066
// Restore container with different port mapping
1067
newRandomPort, err := utils.GetRandomPort()
1068
Expect(err).ShouldNot(HaveOccurred())
1069
result = podmanTest.Podman([]string{"container", "restore", "-p", fmt.Sprintf("%d:6379", newRandomPort), "-i", fileName})
1070
result.WaitWithDefaultTimeout()
1072
Expect(result).Should(ExitCleanly())
1073
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1074
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1076
// Open a network connection to the redis server via initial port mapping
1078
_, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
1079
Expect(err).To(HaveOccurred())
1080
Expect(err.Error()).To(ContainSubstring("connection refused"))
1081
// Open a network connection to the redis server via new port mapping
1082
GinkgoWriter.Printf("Trying to reconnect to redis server at localhost:%d\n", newRandomPort)
1083
conn, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", newRandomPort), time.Duration(3)*time.Second)
1084
Expect(err).ShouldNot(HaveOccurred())
1087
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
1088
result.WaitWithDefaultTimeout()
1089
Expect(result).Should(ExitCleanly())
1090
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1091
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1093
// Remove exported checkpoint
1097
namespaceCombination := []string{
1105
for _, share := range namespaceCombination {
1106
testName := fmt.Sprintf(
1107
"podman checkpoint and restore container out of and into pod (%s)",
1111
share := share // copy into local scope, for use inside function
1113
It(testName, func() {
1114
if err := criu.CheckForCriu(criu.PodCriuVersion); err != nil {
1115
Skip(fmt.Sprintf("check CRIU pod version error: %v", err))
1117
if !crutils.CRRuntimeSupportsPodCheckpointRestore(podmanTest.OCIRuntime) {
1118
Skip("runtime does not support pod restore: " + podmanTest.OCIRuntime)
1121
session := podmanTest.Podman([]string{
1127
session.WaitWithDefaultTimeout()
1128
Expect(session).To(ExitCleanly())
1129
podID := session.OutputToString()
1131
session = podmanTest.Podman([]string{
1140
session.WaitWithDefaultTimeout()
1141
Expect(session).To(ExitCleanly())
1142
cid := session.OutputToString()
1144
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1146
// Checkpoint the container
1147
result := podmanTest.Podman([]string{
1154
result.WaitWithDefaultTimeout()
1156
// As the container has been started with '--rm' it will be completely
1157
// cleaned up after checkpointing.
1158
// #11784 (closed wontfix): runc warns "lstat /sys/.../machine.slice/...: ENOENT"
1159
// so we can't use ExitCleanly()
1160
if podmanTest.OCIRuntime == "runc" {
1161
Expect(result).To(Exit(0))
1163
Expect(result).To(ExitCleanly())
1165
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1166
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
1168
// Remove the pod and create a new pod
1169
result = podmanTest.Podman([]string{
1174
result.WaitWithDefaultTimeout()
1175
Expect(result).To(ExitCleanly())
1177
// First create a pod with different shared namespaces.
1178
// Restore should fail
1180
wrongShare := share[:strings.LastIndex(share, ",")]
1182
session = podmanTest.Podman([]string{
1188
session.WaitWithDefaultTimeout()
1189
Expect(session).To(ExitCleanly())
1190
podID = session.OutputToString()
1192
// Restore container with different port mapping
1193
result = podmanTest.Podman([]string{
1201
result.WaitWithDefaultTimeout()
1202
Expect(result).To(ExitWithError(125, "does not share the "))
1204
// Remove the pod and create a new pod
1205
result = podmanTest.Podman([]string{
1210
result.WaitWithDefaultTimeout()
1211
Expect(result).To(ExitCleanly())
1213
session = podmanTest.Podman([]string{
1219
session.WaitWithDefaultTimeout()
1220
Expect(session).To(ExitCleanly())
1221
podID = session.OutputToString()
1223
// Restore container with different port mapping
1224
result = podmanTest.Podman([]string{
1232
result.WaitWithDefaultTimeout()
1234
Expect(result).To(ExitCleanly())
1235
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
1236
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1238
result = podmanTest.Podman([]string{
1241
result.OutputToString(),
1243
result.WaitWithDefaultTimeout()
1244
// #11784 (closed wontfix): runc warns "lstat /sys/.../machine.slice/...: ENOENT"
1245
// so we can't use ExitCleanly()
1246
if podmanTest.OCIRuntime == "runc" {
1247
Expect(result).To(Exit(0))
1249
Expect(result).To(ExitCleanly())
1251
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1252
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
1254
result = podmanTest.Podman([]string{
1259
result.WaitWithDefaultTimeout()
1260
Expect(result).To(ExitCleanly())
1262
// Remove exported checkpoint
1267
It("podman checkpoint container with export (migration) and --ipc host", func() {
1268
localRunString := getRunString([]string{"--rm", "--ipc", "host", ALPINE, "top"})
1269
session := podmanTest.Podman(localRunString)
1270
session.WaitWithDefaultTimeout()
1271
Expect(session).Should(ExitCleanly())
1272
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1273
cid := session.OutputToString()
1274
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1276
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
1277
result.WaitWithDefaultTimeout()
1279
// As the container has been started with '--rm' it will be completely
1280
// cleaned up after checkpointing.
1281
// Cannot use ExitCleanly() because "skipping [ssh-agent-path] since it is a socket"
1282
Expect(result).Should(Exit(0))
1283
Expect(result.OutputToString()).To(ContainSubstring(cid))
1284
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1285
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1287
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
1288
result.WaitWithDefaultTimeout()
1290
Expect(result).Should(ExitCleanly())
1291
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1292
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1294
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
1295
result.WaitWithDefaultTimeout()
1296
Expect(result).Should(ExitCleanly())
1297
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1298
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1300
// Remove exported checkpoint
1304
It("podman checkpoint container with export and statistics", func() {
1305
localRunString := getRunString([]string{
1310
session := podmanTest.Podman(localRunString)
1311
session.WaitWithDefaultTimeout()
1312
Expect(session).Should(ExitCleanly())
1313
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1314
cid := session.OutputToString()
1315
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1316
defer os.Remove(fileName)
1318
result := podmanTest.Podman([]string{
1324
result.WaitWithDefaultTimeout()
1326
// As the container has been started with '--rm' it will be completely
1327
// cleaned up after checkpointing.
1328
Expect(result).Should(ExitCleanly())
1329
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1330
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1332
// Extract checkpoint archive
1333
destinationDirectory := filepath.Join(podmanTest.TempDir, "dest")
1334
err = os.MkdirAll(destinationDirectory, os.ModePerm)
1335
Expect(err).ToNot(HaveOccurred())
1337
tarsession := SystemExec(
1343
destinationDirectory,
1346
Expect(tarsession).Should(ExitCleanly())
1348
_, err = os.Stat(filepath.Join(destinationDirectory, stats.StatsDump))
1349
Expect(err).ShouldNot(HaveOccurred())
1352
It("podman checkpoint and restore containers with --print-stats", func() {
1353
session1 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE}))
1354
session1.WaitWithDefaultTimeout()
1355
Expect(session1).Should(ExitCleanly())
1357
session2 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE, "top"}))
1358
session2.WaitWithDefaultTimeout()
1359
Expect(session2).Should(ExitCleanly())
1361
result := podmanTest.Podman([]string{
1367
result.WaitWithDefaultTimeout()
1369
Expect(result).Should(ExitCleanly())
1370
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1372
type checkpointStatistics struct {
1373
PodmanDuration int64 `json:"podman_checkpoint_duration"`
1374
ContainerStatistics []*entities.CheckpointReport `json:"container_statistics"`
1377
cS := new(checkpointStatistics)
1378
err := json.Unmarshal([]byte(result.OutputToString()), cS)
1379
Expect(err).ShouldNot(HaveOccurred())
1381
Expect(cS.ContainerStatistics).To(HaveLen(2))
1382
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
1383
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
1384
Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
1385
BeNumerically(">", cS.ContainerStatistics[0].CRIUStatistics.FrozenTime),
1387
Expect(cS.ContainerStatistics[1].RuntimeDuration).To(
1388
BeNumerically(">", cS.ContainerStatistics[1].CRIUStatistics.FrozenTime),
1391
ps := podmanTest.Podman([]string{
1396
ps.WaitWithDefaultTimeout()
1397
Expect(ps).Should(ExitCleanly())
1398
Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
1399
Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
1401
result = podmanTest.Podman([]string{
1407
result.WaitWithDefaultTimeout()
1409
Expect(result).Should(ExitCleanly())
1410
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
1411
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1412
Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
1414
type restoreStatistics struct {
1415
PodmanDuration int64 `json:"podman_restore_duration"`
1416
ContainerStatistics []*entities.RestoreReport `json:"container_statistics"`
1419
rS := new(restoreStatistics)
1420
err = json.Unmarshal([]byte(result.OutputToString()), rS)
1421
Expect(err).ShouldNot(HaveOccurred())
1423
Expect(cS.ContainerStatistics).To(HaveLen(2))
1424
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
1425
Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
1426
Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
1427
BeNumerically(">", cS.ContainerStatistics[0].CRIUStatistics.RestoreTime),
1429
Expect(cS.ContainerStatistics[1].RuntimeDuration).To(
1430
BeNumerically(">", cS.ContainerStatistics[1].CRIUStatistics.RestoreTime),
1433
result = podmanTest.Podman([]string{
1439
result.WaitWithDefaultTimeout()
1440
Expect(result).Should(ExitCleanly())
1441
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1444
It("podman checkpoint and restore container with --file-locks", func() {
1445
localRunString := getRunString([]string{"--name", "test_name", ALPINE, "flock", "test.lock", "sh", "-c", "echo READY;sleep 100"})
1446
session := podmanTest.Podman(localRunString)
1447
session.WaitWithDefaultTimeout()
1448
Expect(session).Should(ExitCleanly())
1449
Expect(WaitContainerReady(podmanTest, "test_name", "READY", 5, 1)).To(BeTrue(), "Timed out waiting for READY")
1451
// Checkpoint is expected to fail without --file-locks
1452
result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
1453
result.WaitWithDefaultTimeout()
1454
Expect(result).Should(ExitWithError(125, "failed: exit status 1"))
1455
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1457
// Checkpoint is expected to succeed with --file-locks
1458
result = podmanTest.Podman([]string{"container", "checkpoint", "--file-locks", "test_name"})
1459
result.WaitWithDefaultTimeout()
1460
Expect(result).Should(ExitCleanly())
1461
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1462
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
1464
result = podmanTest.Podman([]string{"container", "restore", "--file-locks", "test_name"})
1465
result.WaitWithDefaultTimeout()
1467
Expect(result).Should(ExitCleanly())
1468
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1469
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1471
result = podmanTest.Podman([]string{"rm", "-t", "0", "-f", "test_name"})
1472
result.WaitWithDefaultTimeout()
1473
Expect(result).Should(ExitCleanly())
1474
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1477
It("podman checkpoint container with export and verify runtime", func() {
1478
SkipIfRemote("podman-remote does not support --runtime flag")
1479
localRunString := getRunString([]string{
1484
session := podmanTest.Podman(localRunString)
1485
session.WaitWithDefaultTimeout()
1486
Expect(session).Should(ExitCleanly())
1487
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1488
cid := session.OutputToString()
1490
session = podmanTest.Podman([]string{
1496
session.WaitWithDefaultTimeout()
1497
Expect(session).Should(ExitCleanly())
1498
runtime := session.OutputToString()
1500
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1502
result := podmanTest.Podman([]string{
1508
result.WaitWithDefaultTimeout()
1510
// As the container has been started with '--rm' it will be completely
1511
// cleaned up after checkpointing.
1512
Expect(result).Should(ExitCleanly())
1513
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1514
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1516
result = podmanTest.Podman([]string{
1522
result.WaitWithDefaultTimeout()
1523
Expect(result).Should(ExitCleanly())
1524
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1525
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1527
// The restored container should have the same runtime as the original container
1528
result = podmanTest.Podman([]string{
1534
result.WaitWithDefaultTimeout()
1535
Expect(result).Should(ExitCleanly())
1536
Expect(session.OutputToString()).To(Equal(runtime))
1538
// Remove exported checkpoint
1542
It("podman checkpoint container with export and verify non-default runtime", func() {
1543
SkipIfRemote("podman-remote does not support --runtime flag")
1544
// This test triggers the edge case where:
1545
// 1. Default runtime is crun
1546
// 2. Container is created with runc
1547
// 3. Checkpoint without setting --runtime into archive
1548
// 4. Restore without setting --runtime from archive
1549
// It should be expected that podman identifies runtime
1550
// from the checkpoint archive.
1552
// Prevent --runtime arg from being set to force using default
1553
// runtime unless explicitly set through passed args.
1554
preservedMakeOptions := podmanTest.PodmanMakeOptions
1555
podmanTest.PodmanMakeOptions = func(args []string, noEvents, noCache bool) []string {
1556
defaultArgs := preservedMakeOptions(args, noEvents, noCache)
1557
for i := range args {
1558
// Runtime is set explicitly, so we should keep --runtime arg.
1559
if args[i] == "--runtime" {
1563
updatedArgs := make([]string, 0)
1564
for i := 0; i < len(defaultArgs); i++ {
1565
// Remove --runtime arg, letting podman fall back to its default
1566
if defaultArgs[i] == "--runtime" {
1569
updatedArgs = append(updatedArgs, defaultArgs[i])
1575
for _, runtime := range []string{"runc", "crun"} {
1576
if err := exec.Command(runtime, "--help").Run(); err != nil {
1577
Skip(fmt.Sprintf("%s not found in PATH; this test requires both runc and crun", runtime))
1581
// Detect default runtime
1582
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.OCIRuntime.Name}}"})
1583
session.WaitWithDefaultTimeout()
1584
Expect(session).Should(ExitCleanly())
1585
if defaultRuntime := session.OutputToString(); defaultRuntime != "crun" {
1586
Skip(fmt.Sprintf("Default runtime is %q; this test requires crun to be default", defaultRuntime))
1589
// Force non-default runtime "runc"
1590
localRunString := getRunString([]string{"--runtime", "runc", "--rm", ALPINE, "top"})
1591
session = podmanTest.Podman(localRunString)
1592
session.WaitWithDefaultTimeout()
1593
Expect(session).Should(ExitCleanly())
1594
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1595
cid := session.OutputToString()
1597
session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
1598
session.WaitWithDefaultTimeout()
1599
Expect(session).Should(ExitCleanly())
1600
Expect(session.OutputToString()).To(Equal("runc"))
1602
checkpointExportPath := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1604
session = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointExportPath})
1605
session.WaitWithDefaultTimeout()
1606
// As the container has been started with '--rm' it will be completely
1607
// cleaned up after checkpointing.
1608
Expect(session).Should(ExitCleanly())
1609
Expect(session.OutputToString()).To(ContainSubstring(cid))
1610
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1611
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1613
session = podmanTest.Podman([]string{"container", "restore", "-i", checkpointExportPath})
1614
session.WaitWithDefaultTimeout()
1615
Expect(session).Should(ExitCleanly())
1616
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1617
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1619
// The restored container should have the same runtime as the original container
1620
session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
1621
session.WaitWithDefaultTimeout()
1622
Expect(session).Should(ExitCleanly())
1623
Expect(session.OutputToString()).To(Equal("runc"))
1625
// Remove exported checkpoint
1626
os.Remove(checkpointExportPath)
1629
It("podman checkpoint container with export and try to change the runtime", func() {
1630
SkipIfRemote("podman-remote does not support --runtime flag")
1631
// This test will only run if runc and crun both exist
1632
if !strings.Contains(podmanTest.OCIRuntime, "crun") {
1633
Skip("Test requires crun and runc")
1635
cmd := exec.Command("runc")
1636
if err := cmd.Start(); err != nil {
1637
Skip("Test requires crun and runc")
1639
if err := cmd.Wait(); err != nil {
1640
Skip("Test requires crun and runc")
1642
localRunString := getRunString([]string{
1647
// Let's start a container with runc and try to restore it with crun (expected to fail)
1648
localRunString = append(
1655
session := podmanTest.Podman(localRunString)
1656
session.WaitWithDefaultTimeout()
1657
Expect(session).Should(ExitCleanly())
1658
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1659
cid := session.OutputToString()
1661
session = podmanTest.Podman([]string{
1667
session.WaitWithDefaultTimeout()
1668
Expect(session).Should(ExitCleanly())
1669
runtime := session.OutputToString()
1671
fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1673
result := podmanTest.Podman([]string{
1679
result.WaitWithDefaultTimeout()
1681
// As the container has been started with '--rm' it will be completely
1682
// cleaned up after checkpointing.
1683
Expect(result).Should(ExitCleanly())
1684
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1685
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1687
// This should fail as the container was checkpointed with runc
1688
result = podmanTest.Podman([]string{
1696
result.WaitWithDefaultTimeout()
1698
Expect(result).Should(ExitWithError(125, "and cannot be restored with runtime"))
1700
result = podmanTest.Podman([]string{
1708
result.WaitWithDefaultTimeout()
1709
Expect(result).Should(ExitCleanly())
1711
result = podmanTest.Podman([]string{
1717
result.WaitWithDefaultTimeout()
1718
Expect(result).Should(ExitCleanly())
1719
Expect(result.OutputToString()).To(Equal(runtime))
1721
result = podmanTest.Podman([]string{
1727
result.WaitWithDefaultTimeout()
1728
Expect(result).Should(ExitCleanly())
1729
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1730
// Remove exported checkpoint
1734
It("podman checkpoint and restore dev/shm content with --export and --import", func() {
1735
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
1736
session := podmanTest.Podman(localRunString)
1737
session.WaitWithDefaultTimeout()
1738
Expect(session).Should(ExitCleanly())
1739
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1740
cid := session.OutputToString()
1742
// Add test file in dev/shm
1743
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /dev/shm/test.output"})
1744
result.WaitWithDefaultTimeout()
1745
Expect(result).Should(ExitCleanly())
1747
session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
1748
session.WaitWithDefaultTimeout()
1749
Expect(session).Should(ExitCleanly())
1750
runtime := session.OutputToString()
1752
checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
1753
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
1754
result.WaitWithDefaultTimeout()
1756
// As the container has been started with '--rm' it will be completely
1757
// cleaned up after checkpointing.
1758
Expect(result).Should(ExitCleanly())
1759
Expect(result.OutputToString()).To(ContainSubstring(cid))
1760
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1761
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
1763
result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
1764
result.WaitWithDefaultTimeout()
1765
Expect(result).Should(ExitCleanly())
1766
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1767
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1769
// The restored container should have the same runtime as the original container
1770
result = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
1771
result.WaitWithDefaultTimeout()
1772
Expect(result).Should(ExitCleanly())
1773
Expect(session.OutputToString()).To(Equal(runtime))
1775
// Verify the test file content in dev/shm
1776
result = podmanTest.Podman([]string{"exec", cid, "cat", "/dev/shm/test.output"})
1777
result.WaitWithDefaultTimeout()
1778
Expect(result).Should(ExitCleanly())
1779
Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
1781
// Remove exported checkpoint
1782
os.Remove(checkpointFileName)
1785
It("podman checkpoint and restore dev/shm content", func() {
1786
localRunString := getRunString([]string{ALPINE, "top"})
1787
session := podmanTest.Podman(localRunString)
1788
session.WaitWithDefaultTimeout()
1789
Expect(session).Should(ExitCleanly())
1790
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1791
cid := session.OutputToString()
1793
// Add test file in dev/shm
1794
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /dev/shm/test.output"})
1795
result.WaitWithDefaultTimeout()
1796
Expect(result).Should(ExitCleanly())
1798
result = podmanTest.Podman([]string{"container", "checkpoint", cid})
1799
result.WaitWithDefaultTimeout()
1800
Expect(result).Should(ExitCleanly())
1801
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1802
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
1804
result = podmanTest.Podman([]string{"container", "restore", cid})
1805
result.WaitWithDefaultTimeout()
1806
Expect(result).Should(ExitCleanly())
1807
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
1808
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
1810
// Verify the test file content in dev/shm
1811
result = podmanTest.Podman([]string{"exec", cid, "cat", "/dev/shm/test.output"})
1812
result.WaitWithDefaultTimeout()
1813
Expect(result).Should(ExitCleanly())
1814
Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
1816
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
1817
result.WaitWithDefaultTimeout()
1818
Expect(result).Should(ExitCleanly())
1819
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))