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