mirror of
https://github.com/containers/podman.git
synced 2025-05-20 00:27:03 +08:00
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:
@ -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 != "" {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ type RestoreOptions struct {
|
||||
Name string
|
||||
TCPEstablished bool
|
||||
ImportPrevious string
|
||||
PublishPorts []nettypes.PortMapping
|
||||
PublishPorts []string
|
||||
Pod string
|
||||
PrintStats bool
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user