github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/checkpoint_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/checkpoint-restore/go-criu/v7/stats"
    14  	"github.com/containers/podman/v5/pkg/checkpoint/crutils"
    15  	"github.com/containers/podman/v5/pkg/criu"
    16  	"github.com/containers/podman/v5/pkg/domain/entities"
    17  	. "github.com/containers/podman/v5/test/utils"
    18  	"github.com/containers/podman/v5/utils"
    19  	. "github.com/onsi/ginkgo/v2"
    20  	. "github.com/onsi/gomega"
    21  	. "github.com/onsi/gomega/gexec"
    22  )
    23  
    24  var netname string
    25  
    26  func getRunString(input []string) []string {
    27  	runString := []string{"run", "-d", "--network", netname}
    28  	return append(runString, input...)
    29  }
    30  
    31  var _ = Describe("Podman checkpoint", func() {
    32  
    33  	BeforeEach(func() {
    34  		SkipIfRootless("checkpoint not supported in rootless mode")
    35  
    36  		// Check if the runtime implements checkpointing. Currently only
    37  		// runc's checkpoint/restore implementation is supported.
    38  		cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help")
    39  		if err := cmd.Start(); err != nil {
    40  			Skip("OCI runtime does not support checkpoint/restore")
    41  		}
    42  		if err := cmd.Wait(); err != nil {
    43  			Skip("OCI runtime does not support checkpoint/restore")
    44  		}
    45  
    46  		if err := criu.CheckForCriu(criu.MinCriuVersion); err != nil {
    47  			Skip(fmt.Sprintf("check CRIU version error: %v", err))
    48  		}
    49  
    50  		session := podmanTest.Podman([]string{"network", "create"})
    51  		session.WaitWithDefaultTimeout()
    52  		Expect(session).Should(ExitCleanly())
    53  		netname = session.OutputToString()
    54  	})
    55  
    56  	AfterEach(func() {
    57  		if netname != "" {
    58  			session := podmanTest.Podman([]string{"network", "rm", "-f", netname})
    59  			session.WaitWithDefaultTimeout()
    60  			Expect(session).Should(ExitCleanly())
    61  		}
    62  	})
    63  
    64  	It("podman checkpoint bogus container", func() {
    65  		session := podmanTest.Podman([]string{"container", "checkpoint", "foobar"})
    66  		session.WaitWithDefaultTimeout()
    67  		Expect(session).Should(ExitWithError(125, "no such container"))
    68  	})
    69  
    70  	It("podman restore bogus container", func() {
    71  		session := podmanTest.Podman([]string{"container", "restore", "foobar"})
    72  		session.WaitWithDefaultTimeout()
    73  		Expect(session).Should(ExitWithError(125, "no such container or image"))
    74  	})
    75  
    76  	It("podman checkpoint a running container by id", func() {
    77  		localRunString := getRunString([]string{ALPINE, "top"})
    78  		session := podmanTest.Podman(localRunString)
    79  		session.WaitWithDefaultTimeout()
    80  		Expect(session).Should(ExitCleanly())
    81  		cid := session.OutputToString()
    82  
    83  		// Check if none of the checkpoint/restore specific information is displayed
    84  		// for newly started containers.
    85  		inspect := podmanTest.Podman([]string{"inspect", cid})
    86  		inspect.WaitWithDefaultTimeout()
    87  		Expect(inspect).Should(ExitCleanly())
    88  		inspectOut := inspect.InspectContainerToJSON()
    89  		Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
    90  		Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
    91  		Expect(inspectOut[0].State).To(HaveField("CheckpointPath", ""))
    92  		Expect(inspectOut[0].State).To(HaveField("CheckpointLog", ""))
    93  		Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
    94  
    95  		result := podmanTest.Podman([]string{
    96  			"container",
    97  			"checkpoint",
    98  			"--keep",
    99  			cid,
   100  		})
   101  		result.WaitWithDefaultTimeout()
   102  
   103  		Expect(result).Should(ExitCleanly())
   104  		Expect(result.OutputToString()).To(Equal(cid))
   105  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   106  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   107  
   108  		// For a checkpointed container we expect the checkpoint related information
   109  		// to be populated.
   110  		inspect = podmanTest.Podman([]string{"inspect", cid})
   111  		inspect.WaitWithDefaultTimeout()
   112  		Expect(inspect).Should(ExitCleanly())
   113  		inspectOut = inspect.InspectContainerToJSON()
   114  		Expect(inspectOut[0].State.Checkpointed).To(BeTrue(), ".State.Checkpointed")
   115  		Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
   116  		Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
   117  		Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
   118  		Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
   119  
   120  		result = podmanTest.Podman([]string{
   121  			"container",
   122  			"restore",
   123  			"--keep",
   124  			cid,
   125  		})
   126  		result.WaitWithDefaultTimeout()
   127  
   128  		Expect(result).Should(ExitCleanly())
   129  		Expect(result.OutputToString()).To(Equal(cid))
   130  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   131  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   132  
   133  		inspect = podmanTest.Podman([]string{"inspect", cid})
   134  		inspect.WaitWithDefaultTimeout()
   135  		Expect(inspect).Should(ExitCleanly())
   136  		inspectOut = inspect.InspectContainerToJSON()
   137  		Expect(inspectOut[0].State.Restored).To(BeTrue(), ".State.Restored")
   138  		Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
   139  		Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
   140  		Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
   141  		Expect(inspectOut[0].State.RestoreLog).To(ContainSubstring("userdata/restore.log"))
   142  
   143  		podmanTest.StopContainer(cid)
   144  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   145  
   146  		result = podmanTest.Podman([]string{
   147  			"container",
   148  			"start",
   149  			cid,
   150  		})
   151  		result.WaitWithDefaultTimeout()
   152  
   153  		Expect(result).Should(ExitCleanly())
   154  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   155  
   156  		// Stopping and starting the container should remove all checkpoint
   157  		// related information from inspect again.
   158  		inspect = podmanTest.Podman([]string{"inspect", cid})
   159  		inspect.WaitWithDefaultTimeout()
   160  		Expect(inspect).Should(ExitCleanly())
   161  		inspectOut = inspect.InspectContainerToJSON()
   162  		Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
   163  		Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
   164  		Expect(inspectOut[0].State).To(HaveField("CheckpointPath", ""))
   165  		Expect(inspectOut[0].State).To(HaveField("CheckpointLog", ""))
   166  		Expect(inspectOut[0].State).To(HaveField("RestoreLog", ""))
   167  	})
   168  
   169  	It("podman checkpoint a running container by name", func() {
   170  		localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"})
   171  		session := podmanTest.Podman(localRunString)
   172  		session.WaitWithDefaultTimeout()
   173  		Expect(session).Should(ExitCleanly())
   174  
   175  		result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
   176  		result.WaitWithDefaultTimeout()
   177  
   178  		Expect(result).Should(ExitCleanly())
   179  		Expect(result.OutputToString()).To(Equal("test_name"))
   180  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   181  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   182  
   183  		result = podmanTest.Podman([]string{"container", "restore", "test_name"})
   184  		result.WaitWithDefaultTimeout()
   185  
   186  		Expect(result).Should(ExitCleanly())
   187  		Expect(result.OutputToString()).To(Equal("test_name"))
   188  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   189  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   190  
   191  		// Restore a container which name is equal to an image name (#15055)
   192  		localRunString = getRunString([]string{"--name", "alpine", "quay.io/libpod/alpine:latest", "top"})
   193  		session = podmanTest.Podman(localRunString)
   194  		session.WaitWithDefaultTimeout()
   195  		Expect(session).Should(ExitCleanly())
   196  
   197  		result = podmanTest.Podman([]string{"container", "checkpoint", "alpine"})
   198  		result.WaitWithDefaultTimeout()
   199  
   200  		Expect(result).Should(ExitCleanly())
   201  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   202  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   203  
   204  		result = podmanTest.Podman([]string{"container", "restore", "alpine"})
   205  		result.WaitWithDefaultTimeout()
   206  
   207  		Expect(result).Should(ExitCleanly())
   208  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
   209  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   210  	})
   211  
   212  	It("podman pause a checkpointed container by id", func() {
   213  		localRunString := getRunString([]string{ALPINE, "top"})
   214  		session := podmanTest.Podman(localRunString)
   215  		session.WaitWithDefaultTimeout()
   216  		Expect(session).Should(ExitCleanly())
   217  		cid := session.OutputToString()
   218  
   219  		result := podmanTest.Podman([]string{"container", "checkpoint", cid})
   220  		result.WaitWithDefaultTimeout()
   221  
   222  		Expect(result).Should(ExitCleanly())
   223  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   224  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   225  
   226  		result = podmanTest.Podman([]string{"pause", cid})
   227  		result.WaitWithDefaultTimeout()
   228  
   229  		Expect(result).Should(ExitWithError(125, `"exited" is not running, can't pause: container state improper`))
   230  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   231  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   232  
   233  		result = podmanTest.Podman([]string{"container", "restore", cid})
   234  		result.WaitWithDefaultTimeout()
   235  		Expect(result).Should(ExitCleanly())
   236  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   237  
   238  		result = podmanTest.Podman([]string{"rm", cid})
   239  		result.WaitWithDefaultTimeout()
   240  		Expect(result).Should(ExitWithError(2, " as it is running - running or paused containers cannot be removed without force: container state improper"))
   241  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   242  
   243  		result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", cid})
   244  		result.WaitWithDefaultTimeout()
   245  		Expect(result).Should(ExitCleanly())
   246  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   247  
   248  	})
   249  
   250  	It("podman checkpoint latest running container", func() {
   251  		localRunString := getRunString([]string{"--name", "first", ALPINE, "top"})
   252  		session1 := podmanTest.Podman(localRunString)
   253  		session1.WaitWithDefaultTimeout()
   254  		Expect(session1).Should(ExitCleanly())
   255  
   256  		localRunString = getRunString([]string{"--name", "second", ALPINE, "top"})
   257  		session2 := podmanTest.Podman(localRunString)
   258  		session2.WaitWithDefaultTimeout()
   259  		Expect(session2).Should(ExitCleanly())
   260  
   261  		result := podmanTest.Podman([]string{"container", "checkpoint", "second"})
   262  		result.WaitWithDefaultTimeout()
   263  
   264  		Expect(result).Should(ExitCleanly())
   265  		Expect(result.OutputToString()).To(Equal("second"))
   266  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   267  
   268  		ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
   269  		ps.WaitWithDefaultTimeout()
   270  		Expect(ps).Should(ExitCleanly())
   271  		Expect(ps.OutputToString()).To(ContainSubstring(session1.OutputToString()))
   272  		Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
   273  
   274  		result = podmanTest.Podman([]string{"container", "restore", "second"})
   275  		result.WaitWithDefaultTimeout()
   276  
   277  		Expect(result).Should(ExitCleanly())
   278  		Expect(result.OutputToString()).To(Equal("second"))
   279  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
   280  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   281  		Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
   282  
   283  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   284  		result.WaitWithDefaultTimeout()
   285  		Expect(result).Should(ExitCleanly())
   286  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   287  	})
   288  
   289  	It("podman checkpoint all running container", func() {
   290  		localRunString := getRunString([]string{"--name", "first", ALPINE, "top"})
   291  		session1 := podmanTest.Podman(localRunString)
   292  		session1.WaitWithDefaultTimeout()
   293  		Expect(session1).Should(ExitCleanly())
   294  		cid1 := session1.OutputToString()
   295  
   296  		localRunString = getRunString([]string{"--name", "second", ALPINE, "top"})
   297  		session2 := podmanTest.Podman(localRunString)
   298  		session2.WaitWithDefaultTimeout()
   299  		Expect(session2).Should(ExitCleanly())
   300  		cid2 := session2.OutputToString()
   301  
   302  		result := podmanTest.Podman([]string{"container", "checkpoint", "-a"})
   303  		result.WaitWithDefaultTimeout()
   304  
   305  		Expect(result).Should(ExitCleanly())
   306  		Expect(result.OutputToString()).To(ContainSubstring(cid1))
   307  		Expect(result.OutputToString()).To(ContainSubstring(cid2))
   308  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   309  
   310  		ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
   311  		ps.WaitWithDefaultTimeout()
   312  		Expect(ps).Should(ExitCleanly())
   313  		Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
   314  		Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
   315  
   316  		result = podmanTest.Podman([]string{"container", "restore", "-a"})
   317  		result.WaitWithDefaultTimeout()
   318  
   319  		Expect(result).Should(ExitCleanly())
   320  		Expect(result.OutputToString()).To(ContainSubstring(cid1))
   321  		Expect(result.OutputToString()).To(ContainSubstring(cid2))
   322  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
   323  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   324  		Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
   325  
   326  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   327  		result.WaitWithDefaultTimeout()
   328  		Expect(result).Should(ExitCleanly())
   329  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   330  	})
   331  
   332  	It("podman checkpoint container with established tcp connections", func() {
   333  		localRunString := getRunString([]string{REDIS_IMAGE})
   334  		session := podmanTest.Podman(localRunString)
   335  		session.WaitWithDefaultTimeout()
   336  		Expect(session).Should(ExitCleanly())
   337  		cid := session.OutputToString()
   338  		if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
   339  			Fail("Container failed to get ready")
   340  		}
   341  
   342  		// clunky format needed because CNI uses dashes in net names
   343  		IP := podmanTest.Podman([]string{"inspect", cid, fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
   344  		IP.WaitWithDefaultTimeout()
   345  		Expect(IP).Should(ExitCleanly())
   346  
   347  		// Open a network connection to the redis server
   348  		conn, err := net.DialTimeout("tcp4", IP.OutputToString()+":6379", time.Duration(3)*time.Second)
   349  		Expect(err).ToNot(HaveOccurred())
   350  
   351  		// This should fail as the container has established TCP connections
   352  		result := podmanTest.Podman([]string{"container", "checkpoint", cid})
   353  		result.WaitWithDefaultTimeout()
   354  
   355  		// FIXME: criu emits an error message, but podman never sees it:
   356  		//   "CRIU checkpointing failed -52.  Please check CRIU logfile /...."
   357  		Expect(result).Should(ExitWithError(125, "failed: exit status 1"))
   358  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   359  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   360  
   361  		// Now it should work thanks to "--tcp-established"
   362  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "--tcp-established"})
   363  		result.WaitWithDefaultTimeout()
   364  
   365  		Expect(result).Should(ExitCleanly())
   366  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   367  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   368  
   369  		// Restore should fail as the checkpoint image contains established TCP connections
   370  		result = podmanTest.Podman([]string{"container", "restore", cid})
   371  		result.WaitWithDefaultTimeout()
   372  
   373  		// default message when using crun
   374  		expectStderr := "crun: CRIU restoring failed -52. Please check CRIU logfile"
   375  		if podmanTest.OCIRuntime == "runc" {
   376  			expectStderr = "runc: criu failed: type NOTIFY errno 0"
   377  		}
   378  		if !IsRemote() {
   379  			// This part is only seen with podman local, never remote
   380  			expectStderr = "OCI runtime error: " + expectStderr
   381  		}
   382  		Expect(result).Should(ExitWithError(125, expectStderr))
   383  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   384  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   385  
   386  		// Now it should work thanks to "--tcp-established"
   387  		result = podmanTest.Podman([]string{"container", "restore", cid, "--tcp-established"})
   388  		result.WaitWithDefaultTimeout()
   389  
   390  		Expect(result).Should(ExitCleanly())
   391  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   392  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   393  
   394  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   395  		result.WaitWithDefaultTimeout()
   396  		Expect(result).Should(ExitCleanly())
   397  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   398  
   399  		conn.Close()
   400  	})
   401  
   402  	It("podman checkpoint with --leave-running", func() {
   403  		localRunString := getRunString([]string{ALPINE, "top"})
   404  		session := podmanTest.Podman(localRunString)
   405  		session.WaitWithDefaultTimeout()
   406  		Expect(session).Should(ExitCleanly())
   407  		cid := session.OutputToString()
   408  
   409  		// Checkpoint container, but leave it running
   410  		result := podmanTest.Podman([]string{"container", "checkpoint", "--leave-running", cid})
   411  		result.WaitWithDefaultTimeout()
   412  
   413  		Expect(result).Should(ExitCleanly())
   414  		// Make sure it is still running
   415  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   416  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   417  
   418  		// Stop the container
   419  		podmanTest.StopContainer(cid)
   420  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   421  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   422  
   423  		// Restore the stopped container from the previous checkpoint
   424  		result = podmanTest.Podman([]string{"container", "restore", cid})
   425  		result.WaitWithDefaultTimeout()
   426  
   427  		Expect(result).Should(ExitCleanly())
   428  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   429  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   430  
   431  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   432  		result.WaitWithDefaultTimeout()
   433  		Expect(result).Should(ExitCleanly())
   434  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   435  	})
   436  
   437  	It("podman checkpoint and restore container with same IP", func() {
   438  		localRunString := getRunString([]string{"--name", "test_name", ALPINE, "top"})
   439  		session := podmanTest.Podman(localRunString)
   440  		session.WaitWithDefaultTimeout()
   441  		Expect(session).Should(ExitCleanly())
   442  
   443  		// clunky format needed because CNI uses dashes in net names
   444  		IPBefore := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
   445  		IPBefore.WaitWithDefaultTimeout()
   446  		Expect(IPBefore).Should(ExitCleanly())
   447  		Expect(IPBefore.OutputToString()).To(MatchRegexp("^[0-9]+(\\.[0-9]+){3}$"))
   448  
   449  		MACBefore := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").MacAddress}}", netname)})
   450  		MACBefore.WaitWithDefaultTimeout()
   451  		Expect(MACBefore).Should(ExitCleanly())
   452  		Expect(MACBefore.OutputToString()).To(MatchRegexp("^[0-9a-f]{2}(:[0-9a-f]{2}){5}$"))
   453  
   454  		result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
   455  		result.WaitWithDefaultTimeout()
   456  
   457  		Expect(result).Should(ExitCleanly())
   458  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   459  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   460  
   461  		result = podmanTest.Podman([]string{"container", "restore", "test_name"})
   462  		result.WaitWithDefaultTimeout()
   463  
   464  		IPAfter := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").IPAddress}}", netname)})
   465  		IPAfter.WaitWithDefaultTimeout()
   466  		Expect(IPAfter).Should(ExitCleanly())
   467  
   468  		MACAfter := podmanTest.Podman([]string{"inspect", "test_name", fmt.Sprintf("--format={{(index .NetworkSettings.Networks \"%s\").MacAddress}}", netname)})
   469  		MACAfter.WaitWithDefaultTimeout()
   470  		Expect(MACAfter).Should(ExitCleanly())
   471  
   472  		// Check that IP address did not change between checkpointing and restoring
   473  		Expect(IPAfter.OutputToString()).To(Equal(IPBefore.OutputToString()))
   474  
   475  		// Check that MAC address did not change between checkpointing and restoring
   476  		Expect(MACAfter.OutputToString()).To(Equal(MACBefore.OutputToString()))
   477  
   478  		Expect(result).Should(ExitCleanly())
   479  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   480  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   481  
   482  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   483  		result.WaitWithDefaultTimeout()
   484  		Expect(result).Should(ExitCleanly())
   485  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   486  	})
   487  
   488  	// This test does the same steps which are necessary for migrating
   489  	// a container from one host to another
   490  	It("podman checkpoint container with export (migration)", func() {
   491  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   492  		session := podmanTest.Podman(localRunString)
   493  		session.WaitWithDefaultTimeout()
   494  		Expect(session).Should(ExitCleanly())
   495  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   496  		cid := session.OutputToString()
   497  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   498  
   499  		result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   500  		result.WaitWithDefaultTimeout()
   501  
   502  		// As the container has been started with '--rm' it will be completely
   503  		// cleaned up after checkpointing.
   504  		Expect(result).Should(ExitCleanly())
   505  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   506  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   507  
   508  		// Restore container the first time with different name.
   509  		// Using '--ignore-static-ip' as for parallel test runs
   510  		// each containers gets a random IP address via '--ip'.
   511  		// '--ignore-static-ip' tells the restore to use the next
   512  		// available IP address.
   513  		// First restore the container with a new name/ID to make
   514  		// sure nothing in the restored container depends on the
   515  		// original container.
   516  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName, "-n", "restore_again", "--ignore-static-ip"})
   517  		result.WaitWithDefaultTimeout()
   518  
   519  		Expect(result).Should(ExitCleanly())
   520  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   521  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   522  
   523  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   524  		result.WaitWithDefaultTimeout()
   525  
   526  		Expect(result).Should(ExitCleanly())
   527  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
   528  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   529  
   530  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   531  		result.WaitWithDefaultTimeout()
   532  		Expect(result).Should(ExitCleanly())
   533  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   534  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   535  
   536  		// Remove exported checkpoint
   537  		os.Remove(fileName)
   538  	})
   539  	// This test does the same steps which are necessary for migrating
   540  	// a container from one host to another
   541  	It("podman checkpoint container with export and different compression algorithms", func() {
   542  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   543  		session := podmanTest.Podman(localRunString)
   544  		session.WaitWithDefaultTimeout()
   545  		Expect(session).Should(ExitCleanly())
   546  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   547  		cid := session.OutputToString()
   548  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   549  
   550  		// Checkpoint with the default algorithm
   551  		result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   552  		result.WaitWithDefaultTimeout()
   553  
   554  		// As the container has been started with '--rm' it will be completely
   555  		// cleaned up after checkpointing.
   556  		Expect(result).Should(ExitCleanly())
   557  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   558  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   559  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   560  
   561  		// Restore container
   562  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   563  		result.WaitWithDefaultTimeout()
   564  
   565  		Expect(result).Should(ExitCleanly())
   566  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   567  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   568  
   569  		// Checkpoint with the zstd algorithm
   570  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "--compress", "zstd"})
   571  		result.WaitWithDefaultTimeout()
   572  
   573  		// As the container has been started with '--rm' it will be completely
   574  		// cleaned up after checkpointing.
   575  		Expect(result).Should(ExitCleanly())
   576  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   577  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   578  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   579  
   580  		// Restore container
   581  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   582  		result.WaitWithDefaultTimeout()
   583  
   584  		Expect(result).Should(ExitCleanly())
   585  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   586  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   587  
   588  		// Checkpoint with the none algorithm
   589  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "none"})
   590  		result.WaitWithDefaultTimeout()
   591  
   592  		// As the container has been started with '--rm' it will be completely
   593  		// cleaned up after checkpointing.
   594  		Expect(result).Should(ExitCleanly())
   595  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   596  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   597  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   598  
   599  		// Restore container
   600  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   601  		result.WaitWithDefaultTimeout()
   602  
   603  		Expect(result).Should(ExitCleanly())
   604  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   605  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   606  
   607  		// Checkpoint with the gzip algorithm
   608  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "gzip"})
   609  		result.WaitWithDefaultTimeout()
   610  
   611  		// As the container has been started with '--rm' it will be completely
   612  		// cleaned up after checkpointing.
   613  		Expect(result).Should(ExitCleanly())
   614  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   615  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   616  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   617  
   618  		// Restore container
   619  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   620  		result.WaitWithDefaultTimeout()
   621  
   622  		Expect(result).Should(ExitCleanly())
   623  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   624  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   625  
   626  		// Checkpoint with the non-existing algorithm
   627  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName, "-c", "non-existing"})
   628  		result.WaitWithDefaultTimeout()
   629  
   630  		Expect(result).Should(ExitWithError(125, `selected compression algorithm ("non-existing") not supported. Please select one from`))
   631  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   632  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   633  
   634  		result = podmanTest.Podman([]string{"rm", "--time", "0", "-fa"})
   635  		result.WaitWithDefaultTimeout()
   636  		Expect(result).Should(ExitCleanly())
   637  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   638  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   639  
   640  		// Remove exported checkpoint
   641  		os.Remove(fileName)
   642  	})
   643  
   644  	It("podman checkpoint and restore container with root file-system changes", func() {
   645  		// Start the container
   646  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   647  		session := podmanTest.Podman(localRunString)
   648  		session.WaitWithDefaultTimeout()
   649  		Expect(session).Should(ExitCleanly())
   650  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   651  		cid := session.OutputToString()
   652  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   653  
   654  		// Change the container's root file-system
   655  		result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
   656  		result.WaitWithDefaultTimeout()
   657  		Expect(result).Should(ExitCleanly())
   658  
   659  		result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "rm /etc/motd"})
   660  		result.WaitWithDefaultTimeout()
   661  		Expect(result).Should(ExitCleanly())
   662  
   663  		result = podmanTest.Podman([]string{"diff", cid})
   664  		result.WaitWithDefaultTimeout()
   665  		Expect(result).Should(ExitCleanly())
   666  		Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
   667  		Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
   668  		Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
   669  		Expect(result.OutputToStringArray()).To(HaveLen(3))
   670  
   671  		// Checkpoint the container
   672  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   673  		result.WaitWithDefaultTimeout()
   674  
   675  		Expect(result).Should(ExitCleanly())
   676  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   677  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   678  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   679  
   680  		// Restore the container
   681  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   682  		result.WaitWithDefaultTimeout()
   683  
   684  		Expect(result).Should(ExitCleanly())
   685  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   686  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   687  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   688  
   689  		// Verify the changes to the container's root file-system
   690  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
   691  		result.WaitWithDefaultTimeout()
   692  		Expect(result).Should(ExitCleanly())
   693  		Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
   694  
   695  		result = podmanTest.Podman([]string{"diff", cid})
   696  		result.WaitWithDefaultTimeout()
   697  		Expect(result).Should(ExitCleanly())
   698  		Expect(result.OutputToString()).To(ContainSubstring("C /etc"))
   699  		Expect(result.OutputToString()).To(ContainSubstring("A /test.output"))
   700  		Expect(result.OutputToString()).To(ContainSubstring("D /etc/motd"))
   701  		Expect(result.OutputToStringArray()).To(HaveLen(3))
   702  
   703  		// Remove exported checkpoint
   704  		os.Remove(fileName)
   705  	})
   706  	It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during restore", func() {
   707  		// Start the container
   708  		// test that restore works without network namespace (https://github.com/containers/podman/issues/14389)
   709  		session := podmanTest.Podman([]string{"run", "--network=none", "-d", "--rm", ALPINE, "top"})
   710  		session.WaitWithDefaultTimeout()
   711  		Expect(session).Should(ExitCleanly())
   712  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   713  		cid := session.OutputToString()
   714  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   715  
   716  		// Change the container's root file-system
   717  		result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
   718  		result.WaitWithDefaultTimeout()
   719  		Expect(result).Should(ExitCleanly())
   720  
   721  		// Checkpoint the container
   722  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   723  		result.WaitWithDefaultTimeout()
   724  
   725  		Expect(result).Should(ExitCleanly())
   726  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   727  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   728  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   729  
   730  		// Restore the container
   731  		result = podmanTest.Podman([]string{"container", "restore", "--ignore-rootfs", "-i", fileName})
   732  		result.WaitWithDefaultTimeout()
   733  
   734  		Expect(result).Should(ExitCleanly())
   735  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   736  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   737  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   738  
   739  		// Verify the changes to the container's root file-system
   740  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
   741  		result.WaitWithDefaultTimeout()
   742  		Expect(result).Should(ExitWithError(1, "cat: can't open '/test.output': No such file or directory"))
   743  
   744  		// Remove exported checkpoint
   745  		os.Remove(fileName)
   746  	})
   747  	It("podman checkpoint and restore container with root file-system changes using --ignore-rootfs during checkpoint", func() {
   748  		// Start the container
   749  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   750  		session := podmanTest.Podman(localRunString)
   751  		session.WaitWithDefaultTimeout()
   752  		Expect(session).Should(ExitCleanly())
   753  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   754  		cid := session.OutputToString()
   755  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   756  
   757  		// Change the container's root file-system
   758  		result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /test.output"})
   759  		result.WaitWithDefaultTimeout()
   760  		Expect(result).Should(ExitCleanly())
   761  
   762  		// Checkpoint the container
   763  		result = podmanTest.Podman([]string{"container", "checkpoint", "--ignore-rootfs", cid, "-e", fileName})
   764  		result.WaitWithDefaultTimeout()
   765  
   766  		Expect(result).Should(ExitCleanly())
   767  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   768  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   769  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   770  
   771  		// Restore the container
   772  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   773  		result.WaitWithDefaultTimeout()
   774  
   775  		Expect(result).Should(ExitCleanly())
   776  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   777  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   778  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   779  
   780  		// Verify the changes to the container's root file-system
   781  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
   782  		result.WaitWithDefaultTimeout()
   783  		Expect(result).Should(ExitWithError(1, "cat: can't open '/test.output': No such file or directory"))
   784  
   785  		// Remove exported checkpoint
   786  		os.Remove(fileName)
   787  	})
   788  
   789  	It("podman checkpoint and run exec in restored container", func() {
   790  		// Start the container
   791  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   792  		session := podmanTest.Podman(localRunString)
   793  		session.WaitWithDefaultTimeout()
   794  		Expect(session).Should(ExitCleanly())
   795  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   796  		cid := session.OutputToString()
   797  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   798  
   799  		// Checkpoint the container
   800  		result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   801  		result.WaitWithDefaultTimeout()
   802  
   803  		Expect(result).Should(ExitCleanly())
   804  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   805  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   806  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   807  
   808  		// Restore the container
   809  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   810  		result.WaitWithDefaultTimeout()
   811  
   812  		Expect(result).Should(ExitCleanly())
   813  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   814  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   815  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   816  
   817  		// Exec in the container
   818  		result = podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /test.output"})
   819  		result.WaitWithDefaultTimeout()
   820  		Expect(result).Should(ExitCleanly())
   821  
   822  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/test.output"})
   823  		result.WaitWithDefaultTimeout()
   824  		Expect(result).Should(ExitCleanly())
   825  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   826  
   827  		// Remove exported checkpoint
   828  		os.Remove(fileName)
   829  	})
   830  
   831  	It("podman checkpoint a container started with --rm", func() {
   832  		// Start the container
   833  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
   834  		session := podmanTest.Podman(localRunString)
   835  		session.WaitWithDefaultTimeout()
   836  		cid := session.OutputToString()
   837  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   838  
   839  		// Checkpoint the container - this should fail as it was started with --rm
   840  		result := podmanTest.Podman([]string{"container", "checkpoint", cid})
   841  		result.WaitWithDefaultTimeout()
   842  		Expect(result).To(ExitWithError(125, "cannot checkpoint containers that have been started with '--rm'"))
   843  
   844  		// Checkpointing with --export should still work
   845  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   846  
   847  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
   848  		result.WaitWithDefaultTimeout()
   849  
   850  		// As the container has been started with '--rm' it will be completely
   851  		// cleaned up after checkpointing.
   852  		Expect(result).Should(ExitCleanly())
   853  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   854  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   855  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   856  
   857  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
   858  		result.WaitWithDefaultTimeout()
   859  
   860  		Expect(result).Should(ExitCleanly())
   861  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   862  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   863  
   864  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
   865  		result.WaitWithDefaultTimeout()
   866  		Expect(result).Should(ExitCleanly())
   867  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   868  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   869  
   870  		// Remove exported checkpoint
   871  		os.Remove(fileName)
   872  	})
   873  
   874  	It("podman checkpoint a container with volumes", func() {
   875  		session := podmanTest.Podman([]string{
   876  			"build", "-f", "build/basicalpine/Containerfile.volume", "-t", "test-cr-volume",
   877  		})
   878  		session.WaitWithDefaultTimeout()
   879  		Expect(session).Should(ExitCleanly())
   880  
   881  		// Start the container
   882  		localRunString := getRunString([]string{
   883  			"--rm",
   884  			"-v", "/volume1",
   885  			"-v", "my-test-vol:/volume2",
   886  			"test-cr-volume",
   887  			"top",
   888  		})
   889  		session = podmanTest.Podman(localRunString)
   890  		session.WaitWithDefaultTimeout()
   891  		Expect(session).Should(ExitCleanly())
   892  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   893  
   894  		cid := session.OutputToString()
   895  
   896  		// Add file in volume0
   897  		result := podmanTest.Podman([]string{
   898  			"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume0/test.output",
   899  		})
   900  		result.WaitWithDefaultTimeout()
   901  		Expect(result).Should(ExitCleanly())
   902  
   903  		// Add file in volume1
   904  		result = podmanTest.Podman([]string{
   905  			"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume1/test.output",
   906  		})
   907  		result.WaitWithDefaultTimeout()
   908  		Expect(result).Should(ExitCleanly())
   909  
   910  		// Add file in volume2
   911  		result = podmanTest.Podman([]string{
   912  			"exec", cid, "/bin/sh", "-c", "echo " + cid + " > /volume2/test.output",
   913  		})
   914  		result.WaitWithDefaultTimeout()
   915  		Expect(result).Should(ExitCleanly())
   916  
   917  		checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
   918  
   919  		// Checkpoint the container
   920  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
   921  		result.WaitWithDefaultTimeout()
   922  		Expect(result).Should(ExitCleanly())
   923  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   924  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   925  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
   926  
   927  		// Restore container should fail because named volume still exists
   928  		result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
   929  		result.WaitWithDefaultTimeout()
   930  		Expect(result).To(ExitWithError(125, "volume with name my-test-vol already exists. Use --ignore-volumes to not restore content of volumes"))
   931  
   932  		// Remove named volume
   933  		session = podmanTest.Podman([]string{"volume", "rm", "my-test-vol"})
   934  		session.WaitWithDefaultTimeout()
   935  		Expect(session).Should(ExitCleanly())
   936  
   937  		// Restoring container
   938  		result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
   939  		result.WaitWithDefaultTimeout()
   940  		Expect(result).Should(ExitCleanly())
   941  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   942  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   943  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   944  
   945  		// Validate volume0 content
   946  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume0/test.output"})
   947  		result.WaitWithDefaultTimeout()
   948  		Expect(result).Should(ExitCleanly())
   949  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   950  
   951  		// Validate volume1 content
   952  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume1/test.output"})
   953  		result.WaitWithDefaultTimeout()
   954  		Expect(result).Should(ExitCleanly())
   955  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   956  
   957  		// Validate volume2 content
   958  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/volume2/test.output"})
   959  		result.WaitWithDefaultTimeout()
   960  		Expect(result).Should(ExitCleanly())
   961  		Expect(result.OutputToString()).To(ContainSubstring(cid))
   962  
   963  		// Remove exported checkpoint
   964  		os.Remove(checkpointFileName)
   965  	})
   966  
   967  	It("podman checkpoint container with --pre-checkpoint", func() {
   968  		if !criu.MemTrack() {
   969  			Skip("system (architecture/kernel/CRIU) does not support memory tracking")
   970  		}
   971  		localRunString := getRunString([]string{ALPINE, "top"})
   972  		session := podmanTest.Podman(localRunString)
   973  		session.WaitWithDefaultTimeout()
   974  		Expect(session).Should(ExitCleanly())
   975  		cid := session.OutputToString()
   976  
   977  		result := podmanTest.Podman([]string{"container", "checkpoint", "-P", cid})
   978  		result.WaitWithDefaultTimeout()
   979  
   980  		Expect(result).Should(ExitCleanly())
   981  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   982  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   983  
   984  		result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", cid})
   985  		result.WaitWithDefaultTimeout()
   986  
   987  		Expect(result).Should(ExitCleanly())
   988  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
   989  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
   990  
   991  		result = podmanTest.Podman([]string{"container", "restore", cid})
   992  		result.WaitWithDefaultTimeout()
   993  
   994  		Expect(result).Should(ExitCleanly())
   995  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
   996  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
   997  	})
   998  
   999  	It("podman checkpoint container with --pre-checkpoint and export (migration)", func() {
  1000  		SkipIfRemote("--import-previous is not yet supported on the remote client")
  1001  		if !criu.MemTrack() {
  1002  			Skip("system (architecture/kernel/CRIU) does not support memory tracking")
  1003  		}
  1004  		localRunString := getRunString([]string{ALPINE, "top"})
  1005  		session := podmanTest.Podman(localRunString)
  1006  		session.WaitWithDefaultTimeout()
  1007  		Expect(session).Should(ExitCleanly())
  1008  		cid := session.OutputToString()
  1009  		preCheckpointFileName := filepath.Join(podmanTest.TempDir, "/pre-checkpoint-"+cid+".tar.gz")
  1010  		checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1011  
  1012  		result := podmanTest.Podman([]string{"container", "checkpoint", "-P", "-e", preCheckpointFileName, cid})
  1013  		result.WaitWithDefaultTimeout()
  1014  
  1015  		Expect(result).Should(ExitCleanly())
  1016  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1017  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1018  
  1019  		result = podmanTest.Podman([]string{"container", "checkpoint", "--with-previous", "-e", checkpointFileName, cid})
  1020  		result.WaitWithDefaultTimeout()
  1021  
  1022  		Expect(result).Should(ExitCleanly())
  1023  		Expect(result.OutputToString()).To(ContainSubstring(cid))
  1024  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1025  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
  1026  
  1027  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-f", cid})
  1028  		result.WaitWithDefaultTimeout()
  1029  		Expect(result).Should(ExitCleanly())
  1030  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1031  
  1032  		result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName, "--import-previous", preCheckpointFileName})
  1033  		result.WaitWithDefaultTimeout()
  1034  
  1035  		Expect(result).Should(ExitCleanly())
  1036  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1037  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1038  
  1039  		os.Remove(checkpointFileName)
  1040  		os.Remove(preCheckpointFileName)
  1041  	})
  1042  
  1043  	It("podman checkpoint and restore container with different port mappings", func() {
  1044  		randomPort, err := utils.GetRandomPort()
  1045  		Expect(err).ShouldNot(HaveOccurred())
  1046  		localRunString := getRunString([]string{"-p", fmt.Sprintf("%d:6379", randomPort), "--rm", REDIS_IMAGE})
  1047  		session := podmanTest.Podman(localRunString)
  1048  		session.WaitWithDefaultTimeout()
  1049  		Expect(session).Should(ExitCleanly())
  1050  		cid := session.OutputToString()
  1051  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1052  
  1053  		if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
  1054  			Fail("Container failed to get ready")
  1055  		}
  1056  
  1057  		GinkgoWriter.Printf("Trying to connect to redis server at localhost:%d\n", randomPort)
  1058  		// Open a network connection to the redis server via initial port mapping
  1059  		conn, err := net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
  1060  		Expect(err).ShouldNot(HaveOccurred())
  1061  		conn.Close()
  1062  
  1063  		// Checkpoint the container
  1064  		result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
  1065  		result.WaitWithDefaultTimeout()
  1066  
  1067  		// As the container has been started with '--rm' it will be completely
  1068  		// cleaned up after checkpointing.
  1069  		Expect(result).Should(ExitCleanly())
  1070  		Expect(result.OutputToString()).To(ContainSubstring(cid))
  1071  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1072  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1073  
  1074  		// Restore container with different port mapping
  1075  		newRandomPort, err := utils.GetRandomPort()
  1076  		Expect(err).ShouldNot(HaveOccurred())
  1077  		result = podmanTest.Podman([]string{"container", "restore", "-p", fmt.Sprintf("%d:6379", newRandomPort), "-i", fileName})
  1078  		result.WaitWithDefaultTimeout()
  1079  
  1080  		Expect(result).Should(ExitCleanly())
  1081  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1082  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1083  
  1084  		// Open a network connection to the redis server via initial port mapping
  1085  		// This should fail
  1086  		_, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
  1087  		Expect(err).To(HaveOccurred())
  1088  		Expect(err.Error()).To(ContainSubstring("connection refused"))
  1089  		// Open a network connection to the redis server via new port mapping
  1090  		GinkgoWriter.Printf("Trying to reconnect to redis server at localhost:%d\n", newRandomPort)
  1091  		conn, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", newRandomPort), time.Duration(3)*time.Second)
  1092  		Expect(err).ShouldNot(HaveOccurred())
  1093  		conn.Close()
  1094  
  1095  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
  1096  		result.WaitWithDefaultTimeout()
  1097  		Expect(result).Should(ExitCleanly())
  1098  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1099  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1100  
  1101  		// Remove exported checkpoint
  1102  		os.Remove(fileName)
  1103  	})
  1104  
  1105  	namespaceCombination := []string{
  1106  		"ipc,net,uts,pid",
  1107  		"ipc,net,uts",
  1108  		"ipc,net",
  1109  		"net,uts,pid",
  1110  		"net,uts",
  1111  		"uts,pid",
  1112  	}
  1113  	for _, share := range namespaceCombination {
  1114  		testName := fmt.Sprintf(
  1115  			"podman checkpoint and restore container out of and into pod (%s)",
  1116  			share,
  1117  		)
  1118  
  1119  		share := share // copy into local scope, for use inside function
  1120  
  1121  		It(testName, func() {
  1122  			if err := criu.CheckForCriu(criu.PodCriuVersion); err != nil {
  1123  				Skip(fmt.Sprintf("check CRIU pod version error: %v", err))
  1124  			}
  1125  			if !crutils.CRRuntimeSupportsPodCheckpointRestore(podmanTest.OCIRuntime) {
  1126  				Skip("runtime does not support pod restore: " + podmanTest.OCIRuntime)
  1127  			}
  1128  			// Create a pod
  1129  			session := podmanTest.Podman([]string{
  1130  				"pod",
  1131  				"create",
  1132  				"--share",
  1133  				share,
  1134  			})
  1135  			session.WaitWithDefaultTimeout()
  1136  			Expect(session).To(ExitCleanly())
  1137  			podID := session.OutputToString()
  1138  
  1139  			session = podmanTest.Podman([]string{
  1140  				"run",
  1141  				"-d",
  1142  				"--rm",
  1143  				"--pod",
  1144  				podID,
  1145  				ALPINE,
  1146  				"top",
  1147  			})
  1148  			session.WaitWithDefaultTimeout()
  1149  			Expect(session).To(ExitCleanly())
  1150  			cid := session.OutputToString()
  1151  
  1152  			fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1153  
  1154  			// Checkpoint the container
  1155  			result := podmanTest.Podman([]string{
  1156  				"container",
  1157  				"checkpoint",
  1158  				"-e",
  1159  				fileName,
  1160  				cid,
  1161  			})
  1162  			result.WaitWithDefaultTimeout()
  1163  
  1164  			// As the container has been started with '--rm' it will be completely
  1165  			// cleaned up after checkpointing.
  1166  			// #11784 (closed wontfix): runc warns "lstat /sys/.../machine.slice/...: ENOENT"
  1167  			// so we can't use ExitCleanly()
  1168  			if podmanTest.OCIRuntime == "runc" {
  1169  				Expect(result).To(Exit(0))
  1170  			} else {
  1171  				Expect(result).To(ExitCleanly())
  1172  			}
  1173  			Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1174  			Expect(podmanTest.NumberOfContainers()).To(Equal(1))
  1175  
  1176  			// Remove the pod and create a new pod
  1177  			result = podmanTest.Podman([]string{
  1178  				"pod",
  1179  				"rm",
  1180  				podID,
  1181  			})
  1182  			result.WaitWithDefaultTimeout()
  1183  			Expect(result).To(ExitCleanly())
  1184  
  1185  			// First create a pod with different shared namespaces.
  1186  			// Restore should fail
  1187  
  1188  			wrongShare := share[:strings.LastIndex(share, ",")]
  1189  
  1190  			session = podmanTest.Podman([]string{
  1191  				"pod",
  1192  				"create",
  1193  				"--share",
  1194  				wrongShare,
  1195  			})
  1196  			session.WaitWithDefaultTimeout()
  1197  			Expect(session).To(ExitCleanly())
  1198  			podID = session.OutputToString()
  1199  
  1200  			// Restore container with different port mapping
  1201  			result = podmanTest.Podman([]string{
  1202  				"container",
  1203  				"restore",
  1204  				"--pod",
  1205  				podID,
  1206  				"-i",
  1207  				fileName,
  1208  			})
  1209  			result.WaitWithDefaultTimeout()
  1210  			Expect(result).To(ExitWithError(125, "does not share the "))
  1211  
  1212  			// Remove the pod and create a new pod
  1213  			result = podmanTest.Podman([]string{
  1214  				"pod",
  1215  				"rm",
  1216  				podID,
  1217  			})
  1218  			result.WaitWithDefaultTimeout()
  1219  			Expect(result).To(ExitCleanly())
  1220  
  1221  			session = podmanTest.Podman([]string{
  1222  				"pod",
  1223  				"create",
  1224  				"--share",
  1225  				share,
  1226  			})
  1227  			session.WaitWithDefaultTimeout()
  1228  			Expect(session).To(ExitCleanly())
  1229  			podID = session.OutputToString()
  1230  
  1231  			// Restore container with different port mapping
  1232  			result = podmanTest.Podman([]string{
  1233  				"container",
  1234  				"restore",
  1235  				"--pod",
  1236  				podID,
  1237  				"-i",
  1238  				fileName,
  1239  			})
  1240  			result.WaitWithDefaultTimeout()
  1241  
  1242  			Expect(result).To(ExitCleanly())
  1243  			Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
  1244  			Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1245  
  1246  			result = podmanTest.Podman([]string{
  1247  				"rm",
  1248  				"-f",
  1249  				result.OutputToString(),
  1250  			})
  1251  			result.WaitWithDefaultTimeout()
  1252  			// #11784 (closed wontfix): runc warns "lstat /sys/.../machine.slice/...: ENOENT"
  1253  			// so we can't use ExitCleanly()
  1254  			if podmanTest.OCIRuntime == "runc" {
  1255  				Expect(result).To(Exit(0))
  1256  			} else {
  1257  				Expect(result).To(ExitCleanly())
  1258  			}
  1259  			Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1260  			Expect(podmanTest.NumberOfContainers()).To(Equal(1))
  1261  
  1262  			result = podmanTest.Podman([]string{
  1263  				"pod",
  1264  				"rm",
  1265  				"-fa",
  1266  			})
  1267  			result.WaitWithDefaultTimeout()
  1268  			Expect(result).To(ExitCleanly())
  1269  
  1270  			// Remove exported checkpoint
  1271  			os.Remove(fileName)
  1272  		})
  1273  	}
  1274  
  1275  	It("podman checkpoint container with export (migration) and --ipc host", func() {
  1276  		localRunString := getRunString([]string{"--rm", "--ipc", "host", ALPINE, "top"})
  1277  		session := podmanTest.Podman(localRunString)
  1278  		session.WaitWithDefaultTimeout()
  1279  		Expect(session).Should(ExitCleanly())
  1280  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1281  		cid := session.OutputToString()
  1282  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1283  
  1284  		result := podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", fileName})
  1285  		result.WaitWithDefaultTimeout()
  1286  
  1287  		// As the container has been started with '--rm' it will be completely
  1288  		// cleaned up after checkpointing.
  1289  		// Cannot use ExitCleanly() because "skipping [ssh-agent-path] since it is a socket"
  1290  		Expect(result).Should(Exit(0))
  1291  		Expect(result.OutputToString()).To(ContainSubstring(cid))
  1292  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1293  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1294  
  1295  		result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
  1296  		result.WaitWithDefaultTimeout()
  1297  
  1298  		Expect(result).Should(ExitCleanly())
  1299  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1300  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1301  
  1302  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
  1303  		result.WaitWithDefaultTimeout()
  1304  		Expect(result).Should(ExitCleanly())
  1305  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1306  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1307  
  1308  		// Remove exported checkpoint
  1309  		os.Remove(fileName)
  1310  	})
  1311  
  1312  	It("podman checkpoint container with export and statistics", func() {
  1313  		localRunString := getRunString([]string{
  1314  			"--rm",
  1315  			ALPINE,
  1316  			"top",
  1317  		})
  1318  		session := podmanTest.Podman(localRunString)
  1319  		session.WaitWithDefaultTimeout()
  1320  		Expect(session).Should(ExitCleanly())
  1321  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1322  		cid := session.OutputToString()
  1323  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1324  		defer os.Remove(fileName)
  1325  
  1326  		result := podmanTest.Podman([]string{
  1327  			"container",
  1328  			"checkpoint",
  1329  			cid, "-e",
  1330  			fileName,
  1331  		})
  1332  		result.WaitWithDefaultTimeout()
  1333  
  1334  		// As the container has been started with '--rm' it will be completely
  1335  		// cleaned up after checkpointing.
  1336  		Expect(result).Should(ExitCleanly())
  1337  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1338  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1339  
  1340  		// Extract checkpoint archive
  1341  		destinationDirectory := filepath.Join(podmanTest.TempDir, "dest")
  1342  		err = os.MkdirAll(destinationDirectory, os.ModePerm)
  1343  		Expect(err).ToNot(HaveOccurred())
  1344  
  1345  		tarsession := SystemExec(
  1346  			"tar",
  1347  			[]string{
  1348  				"xf",
  1349  				fileName,
  1350  				"-C",
  1351  				destinationDirectory,
  1352  			},
  1353  		)
  1354  		Expect(tarsession).Should(ExitCleanly())
  1355  
  1356  		_, err = os.Stat(filepath.Join(destinationDirectory, stats.StatsDump))
  1357  		Expect(err).ShouldNot(HaveOccurred())
  1358  	})
  1359  
  1360  	It("podman checkpoint and restore containers with --print-stats", func() {
  1361  		session1 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE}))
  1362  		session1.WaitWithDefaultTimeout()
  1363  		Expect(session1).Should(ExitCleanly())
  1364  
  1365  		session2 := podmanTest.Podman(getRunString([]string{REDIS_IMAGE, "top"}))
  1366  		session2.WaitWithDefaultTimeout()
  1367  		Expect(session2).Should(ExitCleanly())
  1368  
  1369  		result := podmanTest.Podman([]string{
  1370  			"container",
  1371  			"checkpoint",
  1372  			"-a",
  1373  			"--print-stats",
  1374  		})
  1375  		result.WaitWithDefaultTimeout()
  1376  
  1377  		Expect(result).Should(ExitCleanly())
  1378  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1379  
  1380  		type checkpointStatistics struct {
  1381  			PodmanDuration      int64                        `json:"podman_checkpoint_duration"`
  1382  			ContainerStatistics []*entities.CheckpointReport `json:"container_statistics"`
  1383  		}
  1384  
  1385  		cS := new(checkpointStatistics)
  1386  		err := json.Unmarshal([]byte(result.OutputToString()), cS)
  1387  		Expect(err).ShouldNot(HaveOccurred())
  1388  
  1389  		Expect(cS.ContainerStatistics).To(HaveLen(2))
  1390  		Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
  1391  		Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
  1392  		Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
  1393  			BeNumerically(">", cS.ContainerStatistics[0].CRIUStatistics.FrozenTime),
  1394  		)
  1395  		Expect(cS.ContainerStatistics[1].RuntimeDuration).To(
  1396  			BeNumerically(">", cS.ContainerStatistics[1].CRIUStatistics.FrozenTime),
  1397  		)
  1398  
  1399  		ps := podmanTest.Podman([]string{
  1400  			"ps",
  1401  			"-q",
  1402  			"--no-trunc",
  1403  		})
  1404  		ps.WaitWithDefaultTimeout()
  1405  		Expect(ps).Should(ExitCleanly())
  1406  		Expect(ps.OutputToString()).To(Not(ContainSubstring(session1.OutputToString())))
  1407  		Expect(ps.OutputToString()).To(Not(ContainSubstring(session2.OutputToString())))
  1408  
  1409  		result = podmanTest.Podman([]string{
  1410  			"container",
  1411  			"restore",
  1412  			"-a",
  1413  			"--print-stats",
  1414  		})
  1415  		result.WaitWithDefaultTimeout()
  1416  
  1417  		Expect(result).Should(ExitCleanly())
  1418  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
  1419  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1420  		Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
  1421  
  1422  		type restoreStatistics struct {
  1423  			PodmanDuration      int64                     `json:"podman_restore_duration"`
  1424  			ContainerStatistics []*entities.RestoreReport `json:"container_statistics"`
  1425  		}
  1426  
  1427  		rS := new(restoreStatistics)
  1428  		err = json.Unmarshal([]byte(result.OutputToString()), rS)
  1429  		Expect(err).ShouldNot(HaveOccurred())
  1430  
  1431  		Expect(cS.ContainerStatistics).To(HaveLen(2))
  1432  		Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[0].RuntimeDuration))
  1433  		Expect(cS.PodmanDuration).To(BeNumerically(">", cS.ContainerStatistics[1].RuntimeDuration))
  1434  		Expect(cS.ContainerStatistics[0].RuntimeDuration).To(
  1435  			BeNumerically(">", cS.ContainerStatistics[0].CRIUStatistics.RestoreTime),
  1436  		)
  1437  		Expect(cS.ContainerStatistics[1].RuntimeDuration).To(
  1438  			BeNumerically(">", cS.ContainerStatistics[1].CRIUStatistics.RestoreTime),
  1439  		)
  1440  
  1441  		result = podmanTest.Podman([]string{
  1442  			"rm",
  1443  			"-t",
  1444  			"0",
  1445  			"-fa",
  1446  		})
  1447  		result.WaitWithDefaultTimeout()
  1448  		Expect(result).Should(ExitCleanly())
  1449  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1450  	})
  1451  
  1452  	It("podman checkpoint and restore container with --file-locks", func() {
  1453  		localRunString := getRunString([]string{"--name", "test_name", ALPINE, "flock", "test.lock", "sh", "-c", "echo READY;sleep 100"})
  1454  		session := podmanTest.Podman(localRunString)
  1455  		session.WaitWithDefaultTimeout()
  1456  		Expect(session).Should(ExitCleanly())
  1457  		Expect(WaitContainerReady(podmanTest, "test_name", "READY", 5, 1)).To(BeTrue(), "Timed out waiting for READY")
  1458  
  1459  		// Checkpoint is expected to fail without --file-locks
  1460  		result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
  1461  		result.WaitWithDefaultTimeout()
  1462  		Expect(result).Should(ExitWithError(125, "failed: exit status 1"))
  1463  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1464  
  1465  		// Checkpoint is expected to succeed with --file-locks
  1466  		result = podmanTest.Podman([]string{"container", "checkpoint", "--file-locks", "test_name"})
  1467  		result.WaitWithDefaultTimeout()
  1468  		Expect(result).Should(ExitCleanly())
  1469  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1470  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
  1471  
  1472  		result = podmanTest.Podman([]string{"container", "restore", "--file-locks", "test_name"})
  1473  		result.WaitWithDefaultTimeout()
  1474  
  1475  		Expect(result).Should(ExitCleanly())
  1476  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1477  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1478  
  1479  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-f", "test_name"})
  1480  		result.WaitWithDefaultTimeout()
  1481  		Expect(result).Should(ExitCleanly())
  1482  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1483  	})
  1484  
  1485  	It("podman checkpoint container with export and verify runtime", func() {
  1486  		SkipIfRemote("podman-remote does not support --runtime flag")
  1487  		localRunString := getRunString([]string{
  1488  			"--rm",
  1489  			ALPINE,
  1490  			"top",
  1491  		})
  1492  		session := podmanTest.Podman(localRunString)
  1493  		session.WaitWithDefaultTimeout()
  1494  		Expect(session).Should(ExitCleanly())
  1495  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1496  		cid := session.OutputToString()
  1497  
  1498  		session = podmanTest.Podman([]string{
  1499  			"inspect",
  1500  			"--format",
  1501  			"{{.OCIRuntime}}",
  1502  			cid,
  1503  		})
  1504  		session.WaitWithDefaultTimeout()
  1505  		Expect(session).Should(ExitCleanly())
  1506  		runtime := session.OutputToString()
  1507  
  1508  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1509  
  1510  		result := podmanTest.Podman([]string{
  1511  			"container",
  1512  			"checkpoint",
  1513  			cid, "-e",
  1514  			fileName,
  1515  		})
  1516  		result.WaitWithDefaultTimeout()
  1517  
  1518  		// As the container has been started with '--rm' it will be completely
  1519  		// cleaned up after checkpointing.
  1520  		Expect(result).Should(ExitCleanly())
  1521  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1522  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1523  
  1524  		result = podmanTest.Podman([]string{
  1525  			"container",
  1526  			"restore",
  1527  			"-i",
  1528  			fileName,
  1529  		})
  1530  		result.WaitWithDefaultTimeout()
  1531  		Expect(result).Should(ExitCleanly())
  1532  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1533  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1534  
  1535  		// The restored container should have the same runtime as the original container
  1536  		result = podmanTest.Podman([]string{
  1537  			"inspect",
  1538  			"--format",
  1539  			"{{.OCIRuntime}}",
  1540  			cid,
  1541  		})
  1542  		result.WaitWithDefaultTimeout()
  1543  		Expect(result).Should(ExitCleanly())
  1544  		Expect(session.OutputToString()).To(Equal(runtime))
  1545  
  1546  		// Remove exported checkpoint
  1547  		os.Remove(fileName)
  1548  	})
  1549  
  1550  	It("podman checkpoint container with export and verify non-default runtime", func() {
  1551  		SkipIfRemote("podman-remote does not support --runtime flag")
  1552  		// This test triggers the edge case where:
  1553  		// 1. Default runtime is crun
  1554  		// 2. Container is created with runc
  1555  		// 3. Checkpoint without setting --runtime into archive
  1556  		// 4. Restore without setting --runtime from archive
  1557  		// It should be expected that podman identifies runtime
  1558  		// from the checkpoint archive.
  1559  
  1560  		// Prevent --runtime arg from being set to force using default
  1561  		// runtime unless explicitly set through passed args.
  1562  		preservedMakeOptions := podmanTest.PodmanMakeOptions
  1563  		podmanTest.PodmanMakeOptions = func(args []string, noEvents, noCache bool) []string {
  1564  			defaultArgs := preservedMakeOptions(args, noEvents, noCache)
  1565  			for i := range args {
  1566  				// Runtime is set explicitly, so we should keep --runtime arg.
  1567  				if args[i] == "--runtime" {
  1568  					return defaultArgs
  1569  				}
  1570  			}
  1571  			updatedArgs := make([]string, 0)
  1572  			for i := 0; i < len(defaultArgs); i++ {
  1573  				// Remove --runtime arg, letting podman fall back to its default
  1574  				if defaultArgs[i] == "--runtime" {
  1575  					i++
  1576  				} else {
  1577  					updatedArgs = append(updatedArgs, defaultArgs[i])
  1578  				}
  1579  			}
  1580  			return updatedArgs
  1581  		}
  1582  
  1583  		for _, runtime := range []string{"runc", "crun"} {
  1584  			if err := exec.Command(runtime, "--help").Run(); err != nil {
  1585  				Skip(fmt.Sprintf("%s not found in PATH; this test requires both runc and crun", runtime))
  1586  			}
  1587  		}
  1588  
  1589  		// Detect default runtime
  1590  		session := podmanTest.Podman([]string{"info", "--format", "{{.Host.OCIRuntime.Name}}"})
  1591  		session.WaitWithDefaultTimeout()
  1592  		Expect(session).Should(ExitCleanly())
  1593  		if defaultRuntime := session.OutputToString(); defaultRuntime != "crun" {
  1594  			Skip(fmt.Sprintf("Default runtime is %q; this test requires crun to be default", defaultRuntime))
  1595  		}
  1596  
  1597  		// Force non-default runtime "runc"
  1598  		localRunString := getRunString([]string{"--runtime", "runc", "--rm", ALPINE, "top"})
  1599  		session = podmanTest.Podman(localRunString)
  1600  		session.WaitWithDefaultTimeout()
  1601  		Expect(session).Should(ExitCleanly())
  1602  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1603  		cid := session.OutputToString()
  1604  
  1605  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
  1606  		session.WaitWithDefaultTimeout()
  1607  		Expect(session).Should(ExitCleanly())
  1608  		Expect(session.OutputToString()).To(Equal("runc"))
  1609  
  1610  		checkpointExportPath := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1611  
  1612  		session = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointExportPath})
  1613  		session.WaitWithDefaultTimeout()
  1614  		// As the container has been started with '--rm' it will be completely
  1615  		// cleaned up after checkpointing.
  1616  		Expect(session).Should(ExitCleanly())
  1617  		Expect(session.OutputToString()).To(ContainSubstring(cid))
  1618  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1619  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1620  
  1621  		session = podmanTest.Podman([]string{"container", "restore", "-i", checkpointExportPath})
  1622  		session.WaitWithDefaultTimeout()
  1623  		Expect(session).Should(ExitCleanly())
  1624  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1625  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1626  
  1627  		// The restored container should have the same runtime as the original container
  1628  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
  1629  		session.WaitWithDefaultTimeout()
  1630  		Expect(session).Should(ExitCleanly())
  1631  		Expect(session.OutputToString()).To(Equal("runc"))
  1632  
  1633  		// Remove exported checkpoint
  1634  		os.Remove(checkpointExportPath)
  1635  	})
  1636  
  1637  	It("podman checkpoint container with export and try to change the runtime", func() {
  1638  		SkipIfRemote("podman-remote does not support --runtime flag")
  1639  		// This test will only run if runc and crun both exist
  1640  		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
  1641  			Skip("Test requires crun and runc")
  1642  		}
  1643  		cmd := exec.Command("runc")
  1644  		if err := cmd.Start(); err != nil {
  1645  			Skip("Test requires crun and runc")
  1646  		}
  1647  		if err := cmd.Wait(); err != nil {
  1648  			Skip("Test requires crun and runc")
  1649  		}
  1650  		localRunString := getRunString([]string{
  1651  			"--rm",
  1652  			ALPINE,
  1653  			"top",
  1654  		})
  1655  		// Let's start a container with runc and try to restore it with crun (expected to fail)
  1656  		localRunString = append(
  1657  			[]string{
  1658  				"--runtime",
  1659  				"runc",
  1660  			},
  1661  			localRunString...,
  1662  		)
  1663  		session := podmanTest.Podman(localRunString)
  1664  		session.WaitWithDefaultTimeout()
  1665  		Expect(session).Should(ExitCleanly())
  1666  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1667  		cid := session.OutputToString()
  1668  
  1669  		session = podmanTest.Podman([]string{
  1670  			"inspect",
  1671  			"--format",
  1672  			"{{.OCIRuntime}}",
  1673  			cid,
  1674  		})
  1675  		session.WaitWithDefaultTimeout()
  1676  		Expect(session).Should(ExitCleanly())
  1677  		runtime := session.OutputToString()
  1678  
  1679  		fileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1680  
  1681  		result := podmanTest.Podman([]string{
  1682  			"container",
  1683  			"checkpoint",
  1684  			cid, "-e",
  1685  			fileName,
  1686  		})
  1687  		result.WaitWithDefaultTimeout()
  1688  
  1689  		// As the container has been started with '--rm' it will be completely
  1690  		// cleaned up after checkpointing.
  1691  		Expect(result).Should(ExitCleanly())
  1692  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1693  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1694  
  1695  		// This should fail as the container was checkpointed with runc
  1696  		result = podmanTest.Podman([]string{
  1697  			"--runtime",
  1698  			"crun",
  1699  			"container",
  1700  			"restore",
  1701  			"-i",
  1702  			fileName,
  1703  		})
  1704  		result.WaitWithDefaultTimeout()
  1705  
  1706  		Expect(result).Should(ExitWithError(125, "and cannot be restored with runtime"))
  1707  
  1708  		result = podmanTest.Podman([]string{
  1709  			"--runtime",
  1710  			"runc",
  1711  			"container",
  1712  			"restore",
  1713  			"-i",
  1714  			fileName,
  1715  		})
  1716  		result.WaitWithDefaultTimeout()
  1717  		Expect(result).Should(ExitCleanly())
  1718  
  1719  		result = podmanTest.Podman([]string{
  1720  			"inspect",
  1721  			"--format",
  1722  			"{{.OCIRuntime}}",
  1723  			cid,
  1724  		})
  1725  		result.WaitWithDefaultTimeout()
  1726  		Expect(result).Should(ExitCleanly())
  1727  		Expect(result.OutputToString()).To(Equal(runtime))
  1728  
  1729  		result = podmanTest.Podman([]string{
  1730  			"--runtime",
  1731  			"runc",
  1732  			"rm",
  1733  			"-fa",
  1734  		})
  1735  		result.WaitWithDefaultTimeout()
  1736  		Expect(result).Should(ExitCleanly())
  1737  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1738  		// Remove exported checkpoint
  1739  		os.Remove(fileName)
  1740  	})
  1741  
  1742  	It("podman checkpoint and restore dev/shm content with --export and --import", func() {
  1743  		localRunString := getRunString([]string{"--rm", ALPINE, "top"})
  1744  		session := podmanTest.Podman(localRunString)
  1745  		session.WaitWithDefaultTimeout()
  1746  		Expect(session).Should(ExitCleanly())
  1747  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1748  		cid := session.OutputToString()
  1749  
  1750  		// Add test file in dev/shm
  1751  		result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /dev/shm/test.output"})
  1752  		result.WaitWithDefaultTimeout()
  1753  		Expect(result).Should(ExitCleanly())
  1754  
  1755  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
  1756  		session.WaitWithDefaultTimeout()
  1757  		Expect(session).Should(ExitCleanly())
  1758  		runtime := session.OutputToString()
  1759  
  1760  		checkpointFileName := filepath.Join(podmanTest.TempDir, "/checkpoint-"+cid+".tar.gz")
  1761  		result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
  1762  		result.WaitWithDefaultTimeout()
  1763  
  1764  		// As the container has been started with '--rm' it will be completely
  1765  		// cleaned up after checkpointing.
  1766  		Expect(result).Should(ExitCleanly())
  1767  		Expect(result.OutputToString()).To(ContainSubstring(cid))
  1768  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1769  		Expect(podmanTest.NumberOfContainers()).To(Equal(0))
  1770  
  1771  		result = podmanTest.Podman([]string{"container", "restore", "-i", checkpointFileName})
  1772  		result.WaitWithDefaultTimeout()
  1773  		Expect(result).Should(ExitCleanly())
  1774  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1775  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1776  
  1777  		// The restored container should have the same runtime as the original container
  1778  		result = podmanTest.Podman([]string{"inspect", "--format", "{{.OCIRuntime}}", cid})
  1779  		result.WaitWithDefaultTimeout()
  1780  		Expect(result).Should(ExitCleanly())
  1781  		Expect(session.OutputToString()).To(Equal(runtime))
  1782  
  1783  		// Verify the test file content in dev/shm
  1784  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/dev/shm/test.output"})
  1785  		result.WaitWithDefaultTimeout()
  1786  		Expect(result).Should(ExitCleanly())
  1787  		Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
  1788  
  1789  		// Remove exported checkpoint
  1790  		os.Remove(checkpointFileName)
  1791  	})
  1792  
  1793  	It("podman checkpoint and restore dev/shm content", func() {
  1794  		localRunString := getRunString([]string{ALPINE, "top"})
  1795  		session := podmanTest.Podman(localRunString)
  1796  		session.WaitWithDefaultTimeout()
  1797  		Expect(session).Should(ExitCleanly())
  1798  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1799  		cid := session.OutputToString()
  1800  
  1801  		// Add test file in dev/shm
  1802  		result := podmanTest.Podman([]string{"exec", cid, "/bin/sh", "-c", "echo test" + cid + "test > /dev/shm/test.output"})
  1803  		result.WaitWithDefaultTimeout()
  1804  		Expect(result).Should(ExitCleanly())
  1805  
  1806  		result = podmanTest.Podman([]string{"container", "checkpoint", cid})
  1807  		result.WaitWithDefaultTimeout()
  1808  		Expect(result).Should(ExitCleanly())
  1809  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1810  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
  1811  
  1812  		result = podmanTest.Podman([]string{"container", "restore", cid})
  1813  		result.WaitWithDefaultTimeout()
  1814  		Expect(result).Should(ExitCleanly())
  1815  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
  1816  		Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
  1817  
  1818  		// Verify the test file content in dev/shm
  1819  		result = podmanTest.Podman([]string{"exec", cid, "cat", "/dev/shm/test.output"})
  1820  		result.WaitWithDefaultTimeout()
  1821  		Expect(result).Should(ExitCleanly())
  1822  		Expect(result.OutputToString()).To(ContainSubstring("test" + cid + "test"))
  1823  
  1824  		result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
  1825  		result.WaitWithDefaultTimeout()
  1826  		Expect(result).Should(ExitCleanly())
  1827  		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
  1828  	})
  1829  })