Files
podman/test/e2e/checkpoint_image_test.go
Paul Holzinger 666d839157 golangci-lint: make windows linting happy
It qemu cannot be compiled anyway so make sure we do not try to compile
parts where the typechecker complains about on windows.
Also all the e2e test files are only used on linux as well.
pkg/machine/wsl also reports some error but to many for me to fix them
now. One minor problem was fixed in pkg/machine/machine_windows.go.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2024-08-19 11:41:29 +02:00

325 lines
13 KiB
Go

//go:build linux || freebsd
package integration
import (
"fmt"
"os/exec"
"strconv"
"strings"
"github.com/containers/podman/v5/pkg/criu"
. "github.com/containers/podman/v5/test/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("Podman checkpoint", func() {
BeforeEach(func() {
SkipIfRootless("checkpoint not supported in rootless mode")
// Check if the runtime implements checkpointing. Currently only
// runc's checkpoint/restore implementation is supported.
cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help")
if err := cmd.Start(); err != nil {
Skip("OCI runtime does not support checkpoint/restore")
}
if err := cmd.Wait(); err != nil {
Skip("OCI runtime does not support checkpoint/restore")
}
if err := criu.CheckForCriu(criu.MinCriuVersion); err != nil {
Skip(fmt.Sprintf("check CRIU version error: %v", err))
}
})
It("podman checkpoint --create-image with bogus container", func() {
checkpointImage := "foobar-checkpoint"
session := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "foobar"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError(125, `no container with name or ID "foobar" found: no such container`))
})
It("podman checkpoint --create-image with running container", func() {
// Container image must be lowercase
checkpointImage := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
containerName := "alpine-container-" + RandomString(6)
localRunString := []string{
"run",
"-d",
"--ip", GetSafeIPAddress(),
"--name", containerName,
ALPINE,
"top",
}
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
containerID := session.OutputToString()
// Checkpoint image should not exist
session = podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeFalse())
// Check if none of the checkpoint/restore specific information is displayed
// for newly started containers.
inspect := podmanTest.Podman([]string{"inspect", containerID})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(ExitCleanly())
inspectOut := inspect.InspectContainerToJSON()
Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
Expect(inspectOut[0].State).To(HaveField("CheckpointPath", ""))
Expect(inspectOut[0].State).To(HaveField("CheckpointLog", ""))
Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
inspect = podmanTest.Podman([]string{"inspect", containerID})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(ExitCleanly())
inspectOut = inspect.InspectContainerToJSON()
Expect(inspectOut[0].State.Checkpointed).To(BeTrue(), ".State.Checkpointed")
Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
// Check if checkpoint image has been created
session = podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeTrue())
// Check if the checkpoint image contains annotations
inspect = podmanTest.Podman([]string{"inspect", checkpointImage})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(ExitCleanly())
inspectImageOut := inspect.InspectImageJSON()
Expect(inspectImageOut[0].Annotations["io.podman.annotations.checkpoint.name"]).To(
BeEquivalentTo(containerName),
"io.podman.annotations.checkpoint.name",
)
ociRuntimeName := ""
if strings.Contains(podmanTest.OCIRuntime, "runc") {
ociRuntimeName = "runc"
} else if strings.Contains(podmanTest.OCIRuntime, "crun") {
ociRuntimeName = "crun"
}
if ociRuntimeName != "" {
Expect(inspectImageOut[0].Annotations["io.podman.annotations.checkpoint.runtime.name"]).To(
BeEquivalentTo(ociRuntimeName),
"io.podman.annotations.checkpoint.runtime.name",
)
}
// Remove existing container
result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerID})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
// Restore container from checkpoint image
result = podmanTest.Podman([]string{"container", "restore", checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Clean-up
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
result = podmanTest.Podman([]string{"rmi", checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman restore multiple containers from single checkpoint image", func() {
// Container image must be lowercase
checkpointImage := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
containerName := "alpine-container-" + RandomString(6)
localRunString := []string{"run", "-d", "--name", containerName, ALPINE, "top"}
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
containerID := session.OutputToString()
// Checkpoint image should not exist
session = podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeFalse())
result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
// Check if checkpoint image has been created
session = podmanTest.Podman([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeTrue())
// Remove existing container
result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerID})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
for i := 1; i < 5; i++ {
// Restore container from checkpoint image
name := containerName + strconv.Itoa(i)
result = podmanTest.Podman([]string{"container", "restore", "--name", name, checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(i))
// Check that the container is running
status := podmanTest.Podman([]string{"inspect", name, "--format={{.State.Status}}"})
status.WaitWithDefaultTimeout()
Expect(status).Should(ExitCleanly())
Expect(status.OutputToString()).To(Equal("running"))
}
// Clean-up
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
result = podmanTest.Podman([]string{"rmi", checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman restore multiple containers from multiple checkpoint images", func() {
// Container image must be lowercase
checkpointImage1 := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
checkpointImage2 := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
containerName1 := "alpine-container-" + RandomString(6)
containerName2 := "alpine-container-" + RandomString(6)
// Create first container
localRunString := []string{"run", "-d", "--name", containerName1, ALPINE, "top"}
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
containerID1 := session.OutputToString()
// Create second container
localRunString = []string{"run", "-d", "--name", containerName2, ALPINE, "top"}
session = podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
containerID2 := session.OutputToString()
// Checkpoint first container
result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage1, "--keep", containerID1})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
// Checkpoint second container
result = podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage2, "--keep", containerID2})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
// Remove existing containers
result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerName1, containerName2})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
// Restore both containers from images
result = podmanTest.Podman([]string{"container", "restore", checkpointImage1, checkpointImage2})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
// Check if first container is running
status := podmanTest.Podman([]string{"inspect", containerName1, "--format={{.State.Status}}"})
status.WaitWithDefaultTimeout()
Expect(status).Should(ExitCleanly())
Expect(status.OutputToString()).To(Equal("running"))
// Check if second container is running
status = podmanTest.Podman([]string{"inspect", containerName2, "--format={{.State.Status}}"})
status.WaitWithDefaultTimeout()
Expect(status).Should(ExitCleanly())
Expect(status.OutputToString()).To(Equal("running"))
// Clean-up
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
result = podmanTest.Podman([]string{"rmi", checkpointImage1, checkpointImage2})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman run with checkpoint image", func() {
// Container image must be lowercase
checkpointImage := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
containerName := "alpine-container-" + RandomString(6)
// Create container
localRunString := []string{"run", "-d", "--name", containerName, ALPINE, "top"}
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
containerID1 := session.OutputToString()
// Checkpoint container, create checkpoint image
result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID1})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
// Remove existing container
result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerName})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
// Restore containers from image using `podman run`
result = podmanTest.Podman([]string{"run", checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
// Check if the container is running
status := podmanTest.Podman([]string{"inspect", containerName, "--format={{.State.Status}}"})
status.WaitWithDefaultTimeout()
Expect(status).Should(ExitCleanly())
Expect(status.OutputToString()).To(Equal("running"))
// Clean-up
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
result = podmanTest.Podman([]string{"rmi", checkpointImage})
result.WaitWithDefaultTimeout()
Expect(result).Should(ExitCleanly())
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
})