fix remote checkpoint/restore

Nothing was working before, and it's too much to summarize.  To make
sure we're not regressing in the future again, enable the remote e2e
tests.

Fixes: #12007
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2021-10-20 15:18:25 +02:00
parent be681ab518
commit 33ec8c6698
10 changed files with 268 additions and 133 deletions

View File

@ -12,7 +12,6 @@ import (
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/specgenutil"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -120,12 +119,7 @@ func restore(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
if len(inputPorts) > 0 {
restoreOptions.PublishPorts, err = specgenutil.CreatePortBindings(inputPorts)
if err != nil {
return err
}
}
restoreOptions.PublishPorts = inputPorts
argLen := len(args)
if restoreOptions.Import != "" {

View File

@ -1,9 +1,11 @@
package libpod
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
@ -206,7 +208,9 @@ func ShowMountedContainers(w http.ResponseWriter, r *http.Request) {
}
func Checkpoint(w http.ResponseWriter, r *http.Request) {
var targetFile string
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
containerEngine := abi.ContainerEngine{Libpod: runtime}
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Keep bool `schema:"keep"`
@ -224,66 +228,68 @@ func Checkpoint(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
name := utils.GetName(r)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ctr, err := runtime.LookupContainer(name)
if err != nil {
if _, err := runtime.LookupContainer(name); err != nil {
utils.ContainerNotFound(w, name, err)
return
}
if query.Export {
tmpFile, err := ioutil.TempFile("", "checkpoint")
if err != nil {
utils.InternalServerError(w, err)
return
}
defer os.Remove(tmpFile.Name())
if err := tmpFile.Close(); err != nil {
utils.InternalServerError(w, err)
return
}
targetFile = tmpFile.Name()
}
options := libpod.ContainerCheckpointOptions{
names := []string{name}
options := entities.CheckpointOptions{
Keep: query.Keep,
KeepRunning: query.LeaveRunning,
LeaveRunning: query.LeaveRunning,
TCPEstablished: query.TCPEstablished,
IgnoreRootfs: query.IgnoreRootFS,
IgnoreRootFS: query.IgnoreRootFS,
PrintStats: query.PrintStats,
}
if query.Export {
options.TargetFile = targetFile
}
criuStatistics, runtimeCheckpointDuration, err := ctr.Checkpoint(r.Context(), options)
f, err := ioutil.TempFile("", "checkpoint")
if err != nil {
utils.InternalServerError(w, err)
return
}
if query.Export {
f, err := os.Open(targetFile)
defer os.Remove(f.Name())
if err := f.Close(); err != nil {
utils.InternalServerError(w, err)
return
}
options.Export = f.Name()
}
reports, err := containerEngine.ContainerCheckpoint(r.Context(), names, options)
if err != nil {
utils.InternalServerError(w, err)
return
}
if !query.Export {
if len(reports) != 1 {
utils.InternalServerError(w, fmt.Errorf("expected 1 restore report but got %d", len(reports)))
return
}
if reports[0].Err != nil {
utils.InternalServerError(w, reports[0].Err)
return
}
utils.WriteResponse(w, http.StatusOK, reports[0])
return
}
f, err := os.Open(options.Export)
if err != nil {
utils.InternalServerError(w, err)
return
}
defer f.Close()
utils.WriteResponse(w, http.StatusOK, f)
return
}
utils.WriteResponse(
w,
http.StatusOK,
entities.CheckpointReport{
Id: ctr.ID(),
RuntimeDuration: runtimeCheckpointDuration,
CRIUStatistics: criuStatistics,
},
)
}
func Restore(w http.ResponseWriter, r *http.Request) {
var (
targetFile string
)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
containerEngine := abi.ContainerEngine{Libpod: runtime}
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
Keep bool `schema:"keep"`
@ -295,6 +301,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
IgnoreStaticIP bool `schema:"ignoreStaticIP"`
IgnoreStaticMAC bool `schema:"ignoreStaticMAC"`
PrintStats bool `schema:"printStats"`
PublishPorts string `schema:"publishPorts"`
}{
// override any golang type defaults
}
@ -303,53 +310,55 @@ func Restore(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
name := utils.GetName(r)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ctr, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
return
options := entities.RestoreOptions{
Name: query.Name,
Keep: query.Keep,
TCPEstablished: query.TCPEstablished,
IgnoreRootFS: query.IgnoreRootFS,
IgnoreVolumes: query.IgnoreVolumes,
IgnoreStaticIP: query.IgnoreStaticIP,
IgnoreStaticMAC: query.IgnoreStaticMAC,
PrintStats: query.PrintStats,
PublishPorts: strings.Fields(query.PublishPorts),
}
var names []string
if query.Import {
t, err := ioutil.TempFile("", "restore")
if err != nil {
utils.InternalServerError(w, err)
return
}
defer t.Close()
defer os.Remove(t.Name())
if err := compat.SaveFromBody(t, r); err != nil {
utils.InternalServerError(w, err)
return
}
targetFile = t.Name()
options.Import = t.Name()
} else {
name := utils.GetName(r)
if _, err := runtime.LookupContainer(name); err != nil {
utils.ContainerNotFound(w, name, err)
return
}
names = []string{name}
}
options := libpod.ContainerCheckpointOptions{
Keep: query.Keep,
TCPEstablished: query.TCPEstablished,
IgnoreRootfs: query.IgnoreRootFS,
IgnoreStaticIP: query.IgnoreStaticIP,
IgnoreStaticMAC: query.IgnoreStaticMAC,
PrintStats: query.PrintStats,
}
if query.Import {
options.TargetFile = targetFile
options.Name = query.Name
}
criuStatistics, runtimeRestoreDuration, err := ctr.Restore(r.Context(), options)
reports, err := containerEngine.ContainerRestore(r.Context(), names, options)
if err != nil {
utils.InternalServerError(w, err)
return
}
utils.WriteResponse(
w,
http.StatusOK,
entities.RestoreReport{
Id: ctr.ID(),
RuntimeDuration: runtimeRestoreDuration,
CRIUStatistics: criuStatistics,
},
)
if len(reports) != 1 {
utils.InternalServerError(w, fmt.Errorf("expected 1 restore report but got %d", len(reports)))
return
}
if reports[0].Err != nil {
utils.InternalServerError(w, reports[0].Err)
return
}
utils.WriteResponse(w, http.StatusOK, reports[0])
}
func InitContainer(w http.ResponseWriter, r *http.Request) {

View File

@ -2,7 +2,9 @@ package containers
import (
"context"
"io"
"net/http"
"os"
"github.com/containers/podman/v3/pkg/bindings"
"github.com/containers/podman/v3/pkg/domain/entities"
@ -23,15 +25,36 @@ func Checkpoint(ctx context.Context, nameOrID string, options *CheckpointOptions
if err != nil {
return nil, err
}
// "export" is a bool for the server so override it in the parameters
// if set.
export := false
if options.Export != nil && *options.Export != "" {
export = true
params.Set("export", "true")
}
response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/containers/%s/checkpoint", params, nil, nameOrID)
if err != nil {
return nil, err
}
defer response.Body.Close()
if !export {
return &report, response.Process(&report)
}
f, err := os.OpenFile(*options.Export, os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
return nil, err
}
defer f.Close()
if _, err := io.Copy(f, response.Body); err != nil {
return nil, err
}
return &entities.CheckpointReport{}, nil
}
// Restore restores a checkpointed container to running. The container is identified by the nameOrID option. All
// additional options are optional and allow finer control of the restore process.
func Restore(ctx context.Context, nameOrID string, options *RestoreOptions) (*entities.RestoreReport, error) {
@ -47,12 +70,26 @@ func Restore(ctx context.Context, nameOrID string, options *RestoreOptions) (*en
if err != nil {
return nil, err
}
// The import key is a reserved golang term
params.Del("ImportArchive")
if i := options.GetImportAchive(); options.Changed("ImportArchive") {
params.Set("import", i)
for _, p := range options.PublishPorts {
params.Add("publishPorts", p)
}
response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/containers/%s/restore", params, nil, nameOrID)
params.Del("ImportArchive") // The import key is a reserved golang term
// Open the to-be-imported archive if needed.
var r io.Reader
if i := options.GetImportAchive(); i != "" {
params.Set("import", "true")
r, err = os.Open(i)
if err != nil {
return nil, err
}
// Hard-code the name since it will be ignored in any case.
nameOrID = "import"
}
response, err := conn.DoRequest(ctx, r, http.MethodPost, "/containers/%s/restore", params, nil, nameOrID)
if err != nil {
return nil, err
}

View File

@ -50,12 +50,14 @@ type CheckpointOptions struct {
Keep *bool
LeaveRunning *bool
TCPEstablished *bool
PrintStats *bool
}
//go:generate go run ../generator/generator.go RestoreOptions
// RestoreOptions are optional options for restoring containers
type RestoreOptions struct {
IgnoreRootfs *bool
IgnoreVolumes *bool
IgnoreStaticIP *bool
IgnoreStaticMAC *bool
ImportAchive *string
@ -63,6 +65,8 @@ type RestoreOptions struct {
Name *string
TCPEstablished *bool
Pod *string
PrintStats *bool
PublishPorts []string
}
//go:generate go run ../generator/generator.go CreateOptions
@ -86,7 +90,8 @@ type ExecInspectOptions struct{}
//go:generate go run ../generator/generator.go ExecStartOptions
// ExecStartOptions are optional options for starting
// exec sessions
type ExecStartOptions struct{}
type ExecStartOptions struct {
}
//go:generate go run ../generator/generator.go HealthCheckOptions
// HealthCheckOptions are optional options for checking

View File

@ -91,3 +91,18 @@ func (o *CheckpointOptions) GetTCPEstablished() bool {
}
return *o.TCPEstablished
}
// WithPrintStats set field PrintStats to given value
func (o *CheckpointOptions) WithPrintStats(value bool) *CheckpointOptions {
o.PrintStats = &value
return o
}
// GetPrintStats returns value of field PrintStats
func (o *CheckpointOptions) GetPrintStats() bool {
if o.PrintStats == nil {
var z bool
return z
}
return *o.PrintStats
}

View File

@ -32,6 +32,21 @@ func (o *RestoreOptions) GetIgnoreRootfs() bool {
return *o.IgnoreRootfs
}
// WithIgnoreVolumes set field IgnoreVolumes to given value
func (o *RestoreOptions) WithIgnoreVolumes(value bool) *RestoreOptions {
o.IgnoreVolumes = &value
return o
}
// GetIgnoreVolumes returns value of field IgnoreVolumes
func (o *RestoreOptions) GetIgnoreVolumes() bool {
if o.IgnoreVolumes == nil {
var z bool
return z
}
return *o.IgnoreVolumes
}
// WithIgnoreStaticIP set field IgnoreStaticIP to given value
func (o *RestoreOptions) WithIgnoreStaticIP(value bool) *RestoreOptions {
o.IgnoreStaticIP = &value
@ -136,3 +151,33 @@ func (o *RestoreOptions) GetPod() string {
}
return *o.Pod
}
// WithPrintStats set field PrintStats to given value
func (o *RestoreOptions) WithPrintStats(value bool) *RestoreOptions {
o.PrintStats = &value
return o
}
// GetPrintStats returns value of field PrintStats
func (o *RestoreOptions) GetPrintStats() bool {
if o.PrintStats == nil {
var z bool
return z
}
return *o.PrintStats
}
// WithPublishPorts set field PublishPorts to given value
func (o *RestoreOptions) WithPublishPorts(value []string) *RestoreOptions {
o.PublishPorts = value
return o
}
// GetPublishPorts returns value of field PublishPorts
func (o *RestoreOptions) GetPublishPorts() []string {
if o.PublishPorts == nil {
var z []string
return z
}
return o.PublishPorts
}

View File

@ -16,6 +16,7 @@ import (
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/errorhandling"
"github.com/containers/podman/v3/pkg/specgen/generate"
"github.com/containers/podman/v3/pkg/specgenutil"
"github.com/containers/storage/pkg/archive"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@ -195,7 +196,12 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
}
if len(restoreOptions.PublishPorts) > 0 {
ports, err := generate.ParsePortMapping(restoreOptions.PublishPorts, nil)
pubPorts, err := specgenutil.CreatePortBindings(restoreOptions.PublishPorts)
if err != nil {
return nil, err
}
ports, err := generate.ParsePortMapping(pubPorts, nil)
if err != nil {
return nil, err
}

View File

@ -212,7 +212,7 @@ type RestoreOptions struct {
Name string
TCPEstablished bool
ImportPrevious string
PublishPorts []nettypes.PortMapping
PublishPorts []string
Pod string
PrintStats bool
}

View File

@ -302,6 +302,14 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string,
}
func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, opts entities.CheckpointOptions) ([]*entities.CheckpointReport, error) {
options := new(containers.CheckpointOptions)
options.WithIgnoreRootfs(opts.IgnoreRootFS)
options.WithKeep(opts.Keep)
options.WithExport(opts.Export)
options.WithTCPEstablished(opts.TCPEstablished)
options.WithPrintStats(opts.PrintStats)
options.WithLeaveRunning(opts.LeaveRunning)
var (
err error
ctrs = []entities.ListContainer{}
@ -325,19 +333,36 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
}
}
reports := make([]*entities.CheckpointReport, 0, len(ctrs))
options := new(containers.CheckpointOptions).WithExport(opts.Export).WithIgnoreRootfs(opts.IgnoreRootFS).WithKeep(opts.Keep)
options.WithLeaveRunning(opts.LeaveRunning).WithTCPEstablished(opts.TCPEstablished)
for _, c := range ctrs {
report, err := containers.Checkpoint(ic.ClientCtx, c.ID, options)
if err != nil {
reports = append(reports, &entities.CheckpointReport{Id: c.ID, Err: err})
}
} else {
reports = append(reports, report)
}
}
return reports, nil
}
func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []string, opts entities.RestoreOptions) ([]*entities.RestoreReport, error) {
options := new(containers.RestoreOptions)
options.WithIgnoreRootfs(opts.IgnoreRootFS)
options.WithIgnoreVolumes(opts.IgnoreVolumes)
options.WithIgnoreStaticIP(opts.IgnoreStaticIP)
options.WithIgnoreStaticMAC(opts.IgnoreStaticMAC)
options.WithKeep(opts.Keep)
options.WithName(opts.Name)
options.WithTCPEstablished(opts.TCPEstablished)
options.WithPod(opts.Pod)
options.WithPrintStats(opts.PrintStats)
options.WithPublishPorts(opts.PublishPorts)
if opts.Import != "" {
options.WithImportAchive(opts.Import)
report, err := containers.Restore(ic.ClientCtx, "", options)
return []*entities.RestoreReport{report}, err
}
var (
err error
ctrs = []entities.ListContainer{}
@ -360,7 +385,6 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
}
}
reports := make([]*entities.RestoreReport, 0, len(ctrs))
options := new(containers.RestoreOptions)
for _, c := range ctrs {
report, err := containers.Restore(ic.ClientCtx, c.ID, options)
if err != nil {

View File

@ -35,7 +35,6 @@ var _ = Describe("Podman checkpoint", func() {
)
BeforeEach(func() {
SkipIfRemote("checkpoint not supported in remote mode")
SkipIfRootless("checkpoint not supported in rootless mode")
tempdir, err = CreateTempDirInTempDir()
if err != nil {
@ -183,7 +182,7 @@ var _ = Describe("Podman checkpoint", func() {
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result := podmanTest.Podman([]string{"container", "checkpoint", "second"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -195,7 +194,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(ps.LineInOutputContains(session1.OutputToString())).To(BeTrue())
Expect(ps.LineInOutputContains(session2.OutputToString())).To(BeFalse())
result = podmanTest.Podman([]string{"container", "restore", "-l"})
result = podmanTest.Podman([]string{"container", "restore", "second"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -258,7 +257,7 @@ var _ = Describe("Podman checkpoint", func() {
Fail("Container failed to get ready")
}
IP := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
IP := podmanTest.Podman([]string{"inspect", cid, "--format={{.NetworkSettings.IPAddress}}"})
IP.WaitWithDefaultTimeout()
Expect(IP).Should(Exit(0))
@ -267,7 +266,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(err).To(BeNil())
// This should fail as the container has established TCP connections
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result := podmanTest.Podman([]string{"container", "checkpoint", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
@ -275,7 +274,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Now it should work thanks to "--tcp-established"
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "--tcp-established"})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "--tcp-established"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -283,7 +282,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
// Restore should fail as the checkpoint image contains established TCP connections
result = podmanTest.Podman([]string{"container", "restore", "-l"})
result = podmanTest.Podman([]string{"container", "restore", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
@ -291,7 +290,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
// Now it should work thanks to "--tcp-established"
result = podmanTest.Podman([]string{"container", "restore", "-l", "--tcp-established"})
result = podmanTest.Podman([]string{"container", "restore", cid, "--tcp-established"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -350,11 +349,11 @@ var _ = Describe("Podman checkpoint", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
IPBefore := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
IPBefore := podmanTest.Podman([]string{"inspect", "test_name", "--format={{.NetworkSettings.IPAddress}}"})
IPBefore.WaitWithDefaultTimeout()
Expect(IPBefore).Should(Exit(0))
MACBefore := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.MacAddress}}"})
MACBefore := podmanTest.Podman([]string{"inspect", "test_name", "--format={{.NetworkSettings.MacAddress}}"})
MACBefore.WaitWithDefaultTimeout()
Expect(MACBefore).Should(Exit(0))
@ -368,11 +367,11 @@ var _ = Describe("Podman checkpoint", func() {
result = podmanTest.Podman([]string{"container", "restore", "test_name"})
result.WaitWithDefaultTimeout()
IPAfter := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
IPAfter := podmanTest.Podman([]string{"inspect", "test_name", "--format={{.NetworkSettings.IPAddress}}"})
IPAfter.WaitWithDefaultTimeout()
Expect(IPAfter).Should(Exit(0))
MACAfter := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.MacAddress}}"})
MACAfter := podmanTest.Podman([]string{"inspect", "test_name", "--format={{.NetworkSettings.MacAddress}}"})
MACAfter.WaitWithDefaultTimeout()
Expect(MACAfter).Should(Exit(0))
@ -403,7 +402,7 @@ var _ = Describe("Podman checkpoint", func() {
cid := session.OutputToString()
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -455,7 +454,7 @@ var _ = Describe("Podman checkpoint", func() {
fileName := "/tmp/checkpoint-" + cid + ".tar"
// Checkpoint with the default algorithm
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -473,7 +472,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the zstd algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "--compress", "zstd"})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "--compress", "zstd"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -491,7 +490,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the none algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "none"})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "none"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -509,7 +508,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the gzip algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "gzip"})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "gzip"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -527,7 +526,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the non-existing algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "non-existing"})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "non-existing"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
@ -555,15 +554,15 @@ var _ = Describe("Podman checkpoint", func() {
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
// Change the container's root file-system
result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
result = podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "rm /etc/motd"})
result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "rm /etc/motd"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
result = podmanTest.Podman([]string{"diff", "-l"})
result = podmanTest.Podman([]string{"diff", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
@ -572,7 +571,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(len(result.OutputToStringArray())).To(Equal(3))
// Checkpoint the container
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -589,12 +588,12 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Verify the changes to the container's root file-system
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
result = podmanTest.Podman([]string{"diff", "-l"})
result = podmanTest.Podman([]string{"diff", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
@ -616,12 +615,12 @@ var _ = Describe("Podman checkpoint", func() {
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
// Change the container's root file-system
result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// Checkpoint the container
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -638,7 +637,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Verify the changes to the container's root file-system
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(1))
Expect(result.ErrorToString()).To(ContainSubstring("cat: can't open '/test.output': No such file or directory"))
@ -657,12 +656,12 @@ var _ = Describe("Podman checkpoint", func() {
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
// Change the container's root file-system
result := podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// Checkpoint the container
result = podmanTest.Podman([]string{"container", "checkpoint", "--ignore-rootfs", "-l", "-e", fileName})
result = podmanTest.Podman([]string{"container", "checkpoint", "--ignore-rootfs", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -679,7 +678,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Verify the changes to the container's root file-system
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(1))
Expect(result.ErrorToString()).To(ContainSubstring("cat: can't open '/test.output': No such file or directory"))
@ -699,7 +698,7 @@ var _ = Describe("Podman checkpoint", func() {
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
// Checkpoint the container
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -716,11 +715,11 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Exec in the container
result = podmanTest.Podman([]string{"exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /test.output"})
result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring(cid))
@ -738,7 +737,7 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
// Checkpoint the container - this should fail as it was started with --rm
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result := podmanTest.Podman([]string{"container", "checkpoint", cid})
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
Expect(result.ErrorToString()).To(ContainSubstring("cannot checkpoint containers that have been started with '--rm'"))
@ -746,7 +745,7 @@ var _ = Describe("Podman checkpoint", func() {
// Checkpointing with --export should still work
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -796,21 +795,21 @@ var _ = Describe("Podman checkpoint", func() {
// Add file in volume0
result := podmanTest.Podman([]string{
"exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume0/test.output",
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume0/test.output",
})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// Add file in volume1
result = podmanTest.Podman([]string{
"exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume1/test.output",
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume1/test.output",
})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// Add file in volume2
result = podmanTest.Podman([]string{
"exec", "-l", "/bin/sh", "-c", "echo " + cid + " > /volume2/test.output",
"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume2/test.output",
})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@ -818,7 +817,7 @@ var _ = Describe("Podman checkpoint", func() {
checkpointFileName := "/tmp/checkpoint-" + cid + ".tar.gz"
// Checkpoint the container
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", checkpointFileName})
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
@ -846,19 +845,19 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Validate volume0 content
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume0/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume0/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring(cid))
// Validate volume1 content
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume1/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume1/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring(cid))
// Validate volume2 content
result = podmanTest.Podman([]string{"exec", "-l", "cat", "/volume2/test.output"})
result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume2/test.output"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(result.OutputToString()).To(ContainSubstring(cid))
@ -962,7 +961,7 @@ var _ = Describe("Podman checkpoint", func() {
conn.Close()
// Checkpoint the container
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -984,6 +983,7 @@ var _ = Describe("Podman checkpoint", func() {
// Open a network connection to the redis server via initial port mapping
// This should fail
conn, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(ContainSubstring("connection refused"))
// Open a network connection to the redis server via new port mapping
fmt.Fprintf(os.Stderr, "Trying to reconnect to redis server at localhost:%d", newRandomPort)
@ -1023,7 +1023,7 @@ var _ = Describe("Podman checkpoint", func() {
Skip("CRIU is missing or too old.")
}
if !crutils.CRRuntimeSupportsPodCheckpointRestore(podmanTest.OCIRuntime) {
Skip("runtime does not support pod restore")
Skip("runtime does not support pod restore: " + podmanTest.OCIRuntime)
}
// Create a pod
session := podmanTest.Podman([]string{
@ -1170,7 +1170,7 @@ var _ = Describe("Podman checkpoint", func() {
cid := session.OutputToString()
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
@ -1212,7 +1212,7 @@ var _ = Describe("Podman checkpoint", func() {
result := podmanTest.Podman([]string{
"container",
"checkpoint",
"-l", "-e",
cid, "-e",
fileName,
})
result.WaitWithDefaultTimeout()