github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/e2e/checkpoint_test.go (about) 1 package integration 2 3 import ( 4 "net" 5 "os" 6 "os/exec" 7 8 "github.com/containers/podman/v2/pkg/criu" 9 . "github.com/containers/podman/v2/test/utils" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 ) 13 14 func getRunString(input []string) []string { 15 // CRIU does not work with seccomp correctly on RHEL7 : seccomp=unconfined 16 runString := []string{"run", "-it", "--security-opt", "seccomp=unconfined", "-d", "--ip", GetRandomIPAddress()} 17 return append(runString, input...) 18 } 19 20 var _ = Describe("Podman checkpoint", func() { 21 var ( 22 tempdir string 23 err error 24 podmanTest *PodmanTestIntegration 25 ) 26 27 BeforeEach(func() { 28 SkipIfRemote("checkpoint not supported in remote mode") 29 SkipIfRootless("checkpoint not supported in rootless mode") 30 tempdir, err = CreateTempDirInTempDir() 31 if err != nil { 32 os.Exit(1) 33 } 34 podmanTest = PodmanTestCreate(tempdir) 35 podmanTest.Setup() 36 podmanTest.SeedImages() 37 // Check if the runtime implements checkpointing. Currently only 38 // runc's checkpoint/restore implementation is supported. 39 cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help") 40 if err := cmd.Start(); err != nil { 41 Skip("OCI runtime does not support checkpoint/restore") 42 } 43 if err := cmd.Wait(); err != nil { 44 Skip("OCI runtime does not support checkpoint/restore") 45 } 46 47 if !criu.CheckForCriu() { 48 Skip("CRIU is missing or too old.") 49 } 50 // Only Fedora 29 and newer has a new enough selinux-policy and 51 // container-selinux package to support CRIU in correctly 52 // restoring threaded processes 53 hostInfo := podmanTest.Host 54 if hostInfo.Distribution == "fedora" && hostInfo.Version < "29" { 55 Skip("Checkpoint/Restore with SELinux only works on Fedora >= 29") 56 } 57 }) 58 59 AfterEach(func() { 60 podmanTest.Cleanup() 61 f := CurrentGinkgoTestDescription() 62 processTestResult(f) 63 64 }) 65 66 It("podman checkpoint bogus container", func() { 67 session := podmanTest.Podman([]string{"container", "checkpoint", "foobar"}) 68 session.WaitWithDefaultTimeout() 69 Expect(session).To(ExitWithError()) 70 }) 71 72 It("podman restore bogus container", func() { 73 session := podmanTest.Podman([]string{"container", "restore", "foobar"}) 74 session.WaitWithDefaultTimeout() 75 Expect(session).To(ExitWithError()) 76 }) 77 78 It("podman checkpoint a running container by id", func() { 79 localRunString := getRunString([]string{ALPINE, "top"}) 80 session := podmanTest.Podman(localRunString) 81 session.WaitWithDefaultTimeout() 82 Expect(session.ExitCode()).To(Equal(0)) 83 cid := session.OutputToString() 84 85 result := podmanTest.Podman([]string{"container", "checkpoint", cid}) 86 result.WaitWithDefaultTimeout() 87 88 Expect(result.ExitCode()).To(Equal(0)) 89 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 90 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 91 92 result = podmanTest.Podman([]string{"container", "restore", cid}) 93 result.WaitWithDefaultTimeout() 94 95 Expect(result.ExitCode()).To(Equal(0)) 96 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 97 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 98 }) 99 100 It("podman checkpoint a running container by name", func() { 101 localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"}) 102 session := podmanTest.Podman(localRunString) 103 session.WaitWithDefaultTimeout() 104 Expect(session.ExitCode()).To(Equal(0)) 105 106 result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"}) 107 result.WaitWithDefaultTimeout() 108 109 Expect(result.ExitCode()).To(Equal(0)) 110 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 111 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 112 113 result = podmanTest.Podman([]string{"container", "restore", "test_name"}) 114 result.WaitWithDefaultTimeout() 115 116 Expect(result.ExitCode()).To(Equal(0)) 117 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 118 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 119 }) 120 121 It("podman pause a checkpointed container by id", func() { 122 localRunString := getRunString([]string{ALPINE, "top"}) 123 session := podmanTest.Podman(localRunString) 124 session.WaitWithDefaultTimeout() 125 Expect(session.ExitCode()).To(Equal(0)) 126 cid := session.OutputToString() 127 128 result := podmanTest.Podman([]string{"container", "checkpoint", cid}) 129 result.WaitWithDefaultTimeout() 130 131 Expect(result.ExitCode()).To(Equal(0)) 132 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 133 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 134 135 result = podmanTest.Podman([]string{"pause", cid}) 136 result.WaitWithDefaultTimeout() 137 138 Expect(result.ExitCode()).To(Equal(125)) 139 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 140 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 141 142 result = podmanTest.Podman([]string{"container", "restore", cid}) 143 result.WaitWithDefaultTimeout() 144 Expect(result.ExitCode()).To(Equal(0)) 145 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 146 147 result = podmanTest.Podman([]string{"rm", cid}) 148 result.WaitWithDefaultTimeout() 149 Expect(result.ExitCode()).To(Equal(2)) 150 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 151 152 result = podmanTest.Podman([]string{"rm", "-f", cid}) 153 result.WaitWithDefaultTimeout() 154 Expect(result.ExitCode()).To(Equal(0)) 155 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 156 157 }) 158 159 It("podman checkpoint latest running container", func() { 160 localRunString := getRunString([]string{"--name", "first", ALPINE, "top"}) 161 session1 := podmanTest.Podman(localRunString) 162 session1.WaitWithDefaultTimeout() 163 Expect(session1.ExitCode()).To(Equal(0)) 164 165 localRunString = getRunString([]string{"--name", "second", ALPINE, "top"}) 166 session2 := podmanTest.Podman(localRunString) 167 session2.WaitWithDefaultTimeout() 168 Expect(session2.ExitCode()).To(Equal(0)) 169 170 result := podmanTest.Podman([]string{"container", "checkpoint", "-l"}) 171 result.WaitWithDefaultTimeout() 172 173 Expect(result.ExitCode()).To(Equal(0)) 174 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 175 176 ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) 177 ps.WaitWithDefaultTimeout() 178 Expect(ps.ExitCode()).To(Equal(0)) 179 Expect(ps.LineInOutputContains(session1.OutputToString())).To(BeTrue()) 180 Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse()) 181 182 result = podmanTest.Podman([]string{"container", "restore", "-l"}) 183 result.WaitWithDefaultTimeout() 184 185 Expect(result.ExitCode()).To(Equal(0)) 186 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) 187 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 188 Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited"))) 189 190 result = podmanTest.Podman([]string{"rm", "-fa"}) 191 result.WaitWithDefaultTimeout() 192 Expect(result.ExitCode()).To(Equal(0)) 193 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 194 }) 195 196 It("podman checkpoint all running container", func() { 197 localRunString := getRunString([]string{"--name", "first", ALPINE, "top"}) 198 session1 := podmanTest.Podman(localRunString) 199 session1.WaitWithDefaultTimeout() 200 Expect(session1.ExitCode()).To(Equal(0)) 201 202 localRunString = getRunString([]string{"--name", "second", ALPINE, "top"}) 203 session2 := podmanTest.Podman(localRunString) 204 session2.WaitWithDefaultTimeout() 205 Expect(session2.ExitCode()).To(Equal(0)) 206 207 result := podmanTest.Podman([]string{"container", "checkpoint", "-a"}) 208 result.WaitWithDefaultTimeout() 209 210 Expect(result.ExitCode()).To(Equal(0)) 211 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 212 213 ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) 214 ps.WaitWithDefaultTimeout() 215 Expect(ps.ExitCode()).To(Equal(0)) 216 Expect(ps.LineInOutputContains(session1.OutputToString())).To(BeFalse()) 217 Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse()) 218 219 result = podmanTest.Podman([]string{"container", "restore", "-a"}) 220 result.WaitWithDefaultTimeout() 221 222 Expect(result.ExitCode()).To(Equal(0)) 223 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) 224 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 225 Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited"))) 226 227 result = podmanTest.Podman([]string{"rm", "-fa"}) 228 result.WaitWithDefaultTimeout() 229 Expect(result.ExitCode()).To(Equal(0)) 230 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 231 }) 232 233 It("podman checkpoint container with established tcp connections", func() { 234 // Broken on Ubuntu. 235 SkipIfNotFedora() 236 localRunString := getRunString([]string{redis}) 237 session := podmanTest.Podman(localRunString) 238 session.WaitWithDefaultTimeout() 239 Expect(session.ExitCode()).To(Equal(0)) 240 241 IP := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"}) 242 IP.WaitWithDefaultTimeout() 243 Expect(IP.ExitCode()).To(Equal(0)) 244 245 // Open a network connection to the redis server 246 conn, err := net.Dial("tcp", IP.OutputToString()+":6379") 247 if err != nil { 248 os.Exit(1) 249 } 250 // This should fail as the container has established TCP connections 251 result := podmanTest.Podman([]string{"container", "checkpoint", "-l"}) 252 result.WaitWithDefaultTimeout() 253 254 Expect(result.ExitCode()).To(Equal(125)) 255 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 256 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 257 258 // Now it should work thanks to "--tcp-established" 259 result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "--tcp-established"}) 260 result.WaitWithDefaultTimeout() 261 262 Expect(result.ExitCode()).To(Equal(0)) 263 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 264 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 265 266 // Restore should fail as the checkpoint image contains established TCP connections 267 result = podmanTest.Podman([]string{"container", "restore", "-l"}) 268 result.WaitWithDefaultTimeout() 269 270 Expect(result.ExitCode()).To(Equal(125)) 271 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 272 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 273 274 // Now it should work thanks to "--tcp-established" 275 result = podmanTest.Podman([]string{"container", "restore", "-l", "--tcp-established"}) 276 result.WaitWithDefaultTimeout() 277 278 Expect(result.ExitCode()).To(Equal(0)) 279 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 280 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 281 282 result = podmanTest.Podman([]string{"rm", "-fa"}) 283 result.WaitWithDefaultTimeout() 284 Expect(result.ExitCode()).To(Equal(0)) 285 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 286 287 conn.Close() 288 }) 289 290 It("podman checkpoint with --leave-running", func() { 291 localRunString := getRunString([]string{ALPINE, "top"}) 292 session := podmanTest.Podman(localRunString) 293 session.WaitWithDefaultTimeout() 294 Expect(session.ExitCode()).To(Equal(0)) 295 cid := session.OutputToString() 296 297 // Checkpoint container, but leave it running 298 result := podmanTest.Podman([]string{"container", "checkpoint", "--leave-running", cid}) 299 result.WaitWithDefaultTimeout() 300 301 Expect(result.ExitCode()).To(Equal(0)) 302 // Make sure it is still running 303 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 304 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 305 306 // Stop the container 307 result = podmanTest.Podman([]string{"container", "stop", cid}) 308 result.WaitWithDefaultTimeout() 309 310 Expect(result.ExitCode()).To(Equal(0)) 311 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 312 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 313 314 // Restore the stopped container from the previous checkpoint 315 result = podmanTest.Podman([]string{"container", "restore", cid}) 316 result.WaitWithDefaultTimeout() 317 318 Expect(result.ExitCode()).To(Equal(0)) 319 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 320 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 321 322 result = podmanTest.Podman([]string{"rm", "-fa"}) 323 result.WaitWithDefaultTimeout() 324 Expect(result.ExitCode()).To(Equal(0)) 325 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 326 }) 327 328 It("podman checkpoint and restore container with same IP", func() { 329 localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"}) 330 session := podmanTest.Podman(localRunString) 331 session.WaitWithDefaultTimeout() 332 Expect(session.ExitCode()).To(Equal(0)) 333 334 IPBefore := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"}) 335 IPBefore.WaitWithDefaultTimeout() 336 Expect(IPBefore.ExitCode()).To(Equal(0)) 337 338 MACBefore := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.MacAddress}}"}) 339 MACBefore.WaitWithDefaultTimeout() 340 Expect(MACBefore.ExitCode()).To(Equal(0)) 341 342 result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"}) 343 result.WaitWithDefaultTimeout() 344 345 Expect(result.ExitCode()).To(Equal(0)) 346 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 347 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) 348 349 result = podmanTest.Podman([]string{"container", "restore", "test_name"}) 350 result.WaitWithDefaultTimeout() 351 352 IPAfter := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"}) 353 IPAfter.WaitWithDefaultTimeout() 354 Expect(IPAfter.ExitCode()).To(Equal(0)) 355 356 MACAfter := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.MacAddress}}"}) 357 MACAfter.WaitWithDefaultTimeout() 358 Expect(MACAfter.ExitCode()).To(Equal(0)) 359 360 // Check that IP address did not change between checkpointing and restoring 361 Expect(IPBefore.OutputToString()).To(Equal(IPAfter.OutputToString())) 362 363 // Check that MAC address did not change between checkpointing and restoring 364 Expect(MACBefore.OutputToString()).To(Equal(MACAfter.OutputToString())) 365 366 Expect(result.ExitCode()).To(Equal(0)) 367 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 368 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 369 370 result = podmanTest.Podman([]string{"rm", "-fa"}) 371 result.WaitWithDefaultTimeout() 372 Expect(result.ExitCode()).To(Equal(0)) 373 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 374 }) 375 376 // This test does the same steps which are necessary for migrating 377 // a container from one host to another 378 It("podman checkpoint container with export (migration)", func() { 379 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 380 session := podmanTest.Podman(localRunString) 381 session.WaitWithDefaultTimeout() 382 Expect(session.ExitCode()).To(Equal(0)) 383 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 384 cid := session.OutputToString() 385 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 386 387 result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) 388 result.WaitWithDefaultTimeout() 389 390 // As the container has been started with '--rm' it will be completely 391 // cleaned up after checkpointing. 392 Expect(result.ExitCode()).To(Equal(0)) 393 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 394 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 395 396 // Restore container the first time with different name. 397 // Using '--ignore-static-ip' as for parallel test runs 398 // each containers gets a random IP address via '--ip'. 399 // '--ignore-static-ip' tells the restore to use the next 400 // available IP address. 401 // First restore the container with a new name/ID to make 402 // sure nothing in the restored container depends on the 403 // original container. 404 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName, "-n", "restore_again", "--ignore-static-ip"}) 405 result.WaitWithDefaultTimeout() 406 407 Expect(result.ExitCode()).To(Equal(0)) 408 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 409 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 410 411 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) 412 result.WaitWithDefaultTimeout() 413 414 Expect(result.ExitCode()).To(Equal(0)) 415 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) 416 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 417 418 result = podmanTest.Podman([]string{"rm", "-fa"}) 419 result.WaitWithDefaultTimeout() 420 Expect(result.ExitCode()).To(Equal(0)) 421 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 422 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 423 424 // Remove exported checkpoint 425 os.Remove(fileName) 426 }) 427 428 It("podman checkpoint and restore container with root file-system changes", func() { 429 // Start the container 430 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 431 session := podmanTest.Podman(localRunString) 432 session.WaitWithDefaultTimeout() 433 Expect(session.ExitCode()).To(Equal(0)) 434 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 435 cid := session.OutputToString() 436 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 437 438 // Change the container's root file-system 439 result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"}) 440 result.WaitWithDefaultTimeout() 441 Expect(result.ExitCode()).To(Equal(0)) 442 443 result = podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "rm /etc/motd"}) 444 result.WaitWithDefaultTimeout() 445 Expect(result.ExitCode()).To(Equal(0)) 446 447 result = podmanTest.Podman([]string{"diff", "-l"}) 448 result.WaitWithDefaultTimeout() 449 Expect(result.ExitCode()).To(Equal(0)) 450 Expect(result.OutputToString()).To(ContainSubstring("C /etc")) 451 Expect(result.OutputToString()).To(ContainSubstring("A /test.output")) 452 Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd")) 453 Expect(len(result.OutputToStringArray())).To(Equal(3)) 454 455 // Checkpoint the container 456 result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) 457 result.WaitWithDefaultTimeout() 458 459 Expect(result.ExitCode()).To(Equal(0)) 460 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 461 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 462 463 // Restore the container 464 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) 465 result.WaitWithDefaultTimeout() 466 467 Expect(result.ExitCode()).To(Equal(0)) 468 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 469 Expect(podmanTest.NumberOfContainers()).To(Equal(1)) 470 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 471 472 // Verify the changes to the container's root file-system 473 result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"}) 474 result.WaitWithDefaultTimeout() 475 Expect(result.ExitCode()).To(Equal(0)) 476 Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test")) 477 478 result = podmanTest.Podman([]string{"diff", "-l"}) 479 result.WaitWithDefaultTimeout() 480 Expect(result.ExitCode()).To(Equal(0)) 481 Expect(result.OutputToString()).To(ContainSubstring("C /etc")) 482 Expect(result.OutputToString()).To(ContainSubstring("A /test.output")) 483 Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd")) 484 Expect(len(result.OutputToStringArray())).To(Equal(3)) 485 486 // Remove exported checkpoint 487 os.Remove(fileName) 488 }) 489 It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during restore", func() { 490 // Start the container 491 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 492 session := podmanTest.Podman(localRunString) 493 session.WaitWithDefaultTimeout() 494 Expect(session.ExitCode()).To(Equal(0)) 495 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 496 cid := session.OutputToString() 497 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 498 499 // Change the container's root file-system 500 result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"}) 501 result.WaitWithDefaultTimeout() 502 Expect(result.ExitCode()).To(Equal(0)) 503 504 // Checkpoint the container 505 result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) 506 result.WaitWithDefaultTimeout() 507 508 Expect(result.ExitCode()).To(Equal(0)) 509 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 510 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 511 512 // Restore the container 513 result = podmanTest.Podman([]string{"container", "restore", "--ignore-rootfs", "-i", fileName}) 514 result.WaitWithDefaultTimeout() 515 516 Expect(result.ExitCode()).To(Equal(0)) 517 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 518 Expect(podmanTest.NumberOfContainers()).To(Equal(1)) 519 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 520 521 // Verify the changes to the container's root file-system 522 result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"}) 523 result.WaitWithDefaultTimeout() 524 Expect(result.ExitCode()).To(Equal(1)) 525 Expect(result.ErrorToString()).To(ContainSubstring("cat: can't open '/test.output': No such file or directory")) 526 527 // Remove exported checkpoint 528 os.Remove(fileName) 529 }) 530 It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during checkpoint", func() { 531 // Start the container 532 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 533 session := podmanTest.Podman(localRunString) 534 session.WaitWithDefaultTimeout() 535 Expect(session.ExitCode()).To(Equal(0)) 536 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 537 cid := session.OutputToString() 538 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 539 540 // Change the container's root file-system 541 result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"}) 542 result.WaitWithDefaultTimeout() 543 Expect(result.ExitCode()).To(Equal(0)) 544 545 // Checkpoint the container 546 result = podmanTest.Podman([]string{"container", "checkpoint", "--ignore-rootfs", "-l", "-e", fileName}) 547 result.WaitWithDefaultTimeout() 548 549 Expect(result.ExitCode()).To(Equal(0)) 550 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 551 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 552 553 // Restore the container 554 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) 555 result.WaitWithDefaultTimeout() 556 557 Expect(result.ExitCode()).To(Equal(0)) 558 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 559 Expect(podmanTest.NumberOfContainers()).To(Equal(1)) 560 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 561 562 // Verify the changes to the container's root file-system 563 result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"}) 564 result.WaitWithDefaultTimeout() 565 Expect(result.ExitCode()).To(Equal(1)) 566 Expect(result.ErrorToString()).To(ContainSubstring("cat: can't open '/test.output': No such file or directory")) 567 568 // Remove exported checkpoint 569 os.Remove(fileName) 570 }) 571 572 It("podman checkpoint and run exec in restored container", func() { 573 // Start the container 574 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 575 session := podmanTest.Podman(localRunString) 576 session.WaitWithDefaultTimeout() 577 Expect(session.ExitCode()).To(Equal(0)) 578 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 579 cid := session.OutputToString() 580 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 581 582 // Checkpoint the container 583 result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) 584 result.WaitWithDefaultTimeout() 585 586 Expect(result.ExitCode()).To(Equal(0)) 587 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 588 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 589 590 // Restore the container 591 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) 592 result.WaitWithDefaultTimeout() 593 594 Expect(result.ExitCode()).To(Equal(0)) 595 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 596 Expect(podmanTest.NumberOfContainers()).To(Equal(1)) 597 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 598 599 // Exec in the container 600 result = podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /test.output"}) 601 result.WaitWithDefaultTimeout() 602 Expect(result.ExitCode()).To(Equal(0)) 603 604 result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"}) 605 result.WaitWithDefaultTimeout() 606 Expect(result.ExitCode()).To(Equal(0)) 607 Expect(result.OutputToString()).To(ContainSubstring(cid)) 608 609 // Remove exported checkpoint 610 os.Remove(fileName) 611 }) 612 613 It("podman checkpoint a container started with --rm", func() { 614 // Start the container 615 localRunString := getRunString([]string{"--rm", ALPINE, "top"}) 616 session := podmanTest.Podman(localRunString) 617 session.WaitWithDefaultTimeout() 618 cid := session.OutputToString() 619 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 620 621 // Checkpoint the container - this should fail as it was started with --rm 622 result := podmanTest.Podman([]string{"container", "checkpoint", "-l"}) 623 result.WaitWithDefaultTimeout() 624 Expect(result).To(ExitWithError()) 625 Expect(result.ErrorToString()).To(ContainSubstring("Cannot checkpoint containers that have been started with '--rm'")) 626 627 // Checkpointing with --export should still work 628 fileName := "/tmp/checkpoint-" + cid + ".tar.gz" 629 630 result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) 631 result.WaitWithDefaultTimeout() 632 633 // As the container has been started with '--rm' it will be completely 634 // cleaned up after checkpointing. 635 Expect(result.ExitCode()).To(Equal(0)) 636 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 637 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 638 639 result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) 640 result.WaitWithDefaultTimeout() 641 642 Expect(result.ExitCode()).To(Equal(0)) 643 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) 644 Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) 645 646 result = podmanTest.Podman([]string{"rm", "-fa"}) 647 result.WaitWithDefaultTimeout() 648 Expect(result.ExitCode()).To(Equal(0)) 649 Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) 650 Expect(podmanTest.NumberOfContainers()).To(Equal(0)) 651 652 // Remove exported checkpoint 653 os.Remove(fileName) 654 }) 655 })