From 10875a67e4c6ebaf28aa8109c7a4001e70840883 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 4 Jun 2021 13:43:43 +0000 Subject: Order checkpoint options in man page alphabetically This just reorders the options in the podman-container-checkpoint man page alphabetically. No actual content changed. Signed-off-by: Adrian Reber --- .../markdown/podman-container-checkpoint.1.md | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index 46b6cb646..a7d707249 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -10,32 +10,10 @@ podman\-container\-checkpoint - Checkpoints one or more running containers Checkpoints all the processes in one or more containers. You may use container IDs or names as input. ## OPTIONS -#### **--keep**, **-k** - -Keep all temporary log and statistics files created by CRIU during checkpointing. These files -are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these -files are theoretically not needed, but if these files are needed Podman can keep the files -for further analysis. - #### **--all**, **-a** Checkpoint all running containers. -#### **--latest**, **-l** - -Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client) - -#### **--leave-running**, **-R** - -Leave the container running after checkpointing instead of stopping it. - -#### **--tcp-established** - -Checkpoint a container with established TCP connections. If the checkpoint -image contains established TCP connections, this options is required during -restore. Defaults to not checkpointing containers with established TCP -connections. - #### **--export**, **-e** Export the checkpoint to a tar.gz file. The exported checkpoint can be used @@ -56,11 +34,33 @@ This option must be used in combination with the **--export, -e** option. When this option is specified, the content of volumes associated with the container will not be included into the checkpoint tar.gz file. +#### **--keep**, **-k** + +Keep all temporary log and statistics files created by CRIU during checkpointing. These files +are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these +files are theoretically not needed, but if these files are needed Podman can keep the files +for further analysis. + +#### **--latest**, **-l** + +Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client) + +#### **--leave-running**, **-R** + +Leave the container running after checkpointing instead of stopping it. + #### **--pre-checkpoint**, **-P** Dump the container's memory information only, leaving the container running. Later operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher. +#### **--tcp-established** + +Checkpoint a container with established TCP connections. If the checkpoint +image contains established TCP connections, this options is required during +restore. Defaults to not checkpointing containers with established TCP +connections. + #### **--with-previous** Check out the container with previous criu image files in pre-dump. It only works -- cgit v1.2.3-54-g00ecf From 8aa5340ade611bf3bce3c8613efce28f2b174a1b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 4 Jun 2021 13:45:33 +0000 Subject: Add parameter to specify checkpoint archive compression The checkpoint archive compression was hardcoded to `archive.Gzip`. There have been requests to make the used compression algorithm selectable. There was especially the request to not compress the checkpoint archive to be able to create faster checkpoints when not compressing it. This also changes the default from `gzip` to `zstd`. This change should not break anything as the restore code path automatically handles whatever compression the user provides during restore. Signed-off-by: Adrian Reber --- cmd/podman/common/completion.go | 7 +++++++ cmd/podman/containers/checkpoint.go | 27 ++++++++++++++++++++++++--- libpod/container_api.go | 4 ++++ libpod/container_internal_linux.go | 2 +- pkg/domain/entities/containers.go | 2 ++ pkg/domain/infra/abi/containers.go | 1 + 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index de5b2995a..c93f2017c 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -1211,3 +1211,10 @@ func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete str } return completeKeyValues(toComplete, kv) } + +// AutocompleteCheckpointCompressType - Autocomplete checkpoint compress type options. +// -> "gzip", "none", "zstd" +func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + types := []string{"gzip", "none", "zstd"} + return types, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/podman/containers/checkpoint.go b/cmd/podman/containers/checkpoint.go index 47d60453b..4fa72d520 100644 --- a/cmd/podman/containers/checkpoint.go +++ b/cmd/podman/containers/checkpoint.go @@ -3,6 +3,7 @@ package containers import ( "context" "fmt" + "strings" "github.com/containers/common/pkg/completion" "github.com/containers/podman/v3/cmd/podman/common" @@ -11,6 +12,7 @@ import ( "github.com/containers/podman/v3/cmd/podman/validate" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/rootless" + "github.com/containers/storage/pkg/archive" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -36,9 +38,7 @@ var ( } ) -var ( - checkpointOptions entities.CheckpointOptions -) +var checkpointOptions entities.CheckpointOptions func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ @@ -60,11 +60,32 @@ func init() { flags.BoolVarP(&checkpointOptions.PreCheckPoint, "pre-checkpoint", "P", false, "Dump container's memory information only, leave the container running") flags.BoolVar(&checkpointOptions.WithPrevious, "with-previous", false, "Checkpoint container with pre-checkpoint images") + flags.StringP("compress", "c", "zstd", "Select compression algorithm (gzip, none, zstd) for checkpoint archive.") + _ = checkpointCommand.RegisterFlagCompletionFunc("compress", common.AutocompleteCheckpointCompressType) + validate.AddLatestFlag(checkpointCommand, &checkpointOptions.Latest) } func checkpoint(cmd *cobra.Command, args []string) error { var errs utils.OutputErrors + if cmd.Flags().Changed("compress") { + if checkpointOptions.Export == "" { + return errors.Errorf("--compress can only be used with --export") + } + compress, _ := cmd.Flags().GetString("compress") + switch strings.ToLower(compress) { + case "none": + checkpointOptions.Compression = archive.Uncompressed + case "gzip": + checkpointOptions.Compression = archive.Gzip + case "zstd": + checkpointOptions.Compression = archive.Zstd + default: + return errors.Errorf("Selected compression algorithm (%q) not supported. Please select one from: gzip, none, zstd", compress) + } + } else { + checkpointOptions.Compression = archive.Zstd + } if rootless.IsRootless() { return errors.New("checkpointing a container requires root") } diff --git a/libpod/container_api.go b/libpod/container_api.go index 4ccb240e7..b75d0b41d 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -12,6 +12,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/events" "github.com/containers/podman/v3/pkg/signal" + "github.com/containers/storage/pkg/archive" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -776,6 +777,9 @@ type ContainerCheckpointOptions struct { // ImportPrevious tells the API to restore container with two // images. One is TargetFile, the other is ImportPrevious. ImportPrevious string + // Compression tells the API which compression to use for + // the exported checkpoint archive. + Compression archive.Compression } // Checkpoint checkpoints a container diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 74a3fec32..a3acc3198 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -985,7 +985,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { } input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{ - Compression: archive.Gzip, + Compression: options.Compression, IncludeSourceDir: true, IncludeFiles: includeFiles, }) diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index eacc14d50..bae55e64f 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -9,6 +9,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" + "github.com/containers/storage/pkg/archive" "github.com/cri-o/ocicni/pkg/ocicni" ) @@ -178,6 +179,7 @@ type CheckpointOptions struct { TCPEstablished bool PreCheckPoint bool WithPrevious bool + Compression archive.Compression } type CheckpointReport struct { diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 237a43441..4908e72f6 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -483,6 +483,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [ KeepRunning: options.LeaveRunning, PreCheckPoint: options.PreCheckPoint, WithPrevious: options.WithPrevious, + Compression: options.Compression, } if options.All { -- cgit v1.2.3-54-g00ecf From 68070f1b2afc757e1dc8dfa09ea69ad6c9b72671 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 4 Jun 2021 15:28:28 +0000 Subject: Add --compress to podman-container-checkpoint.1.md Signed-off-by: Adrian Reber --- docs/source/markdown/podman-container-checkpoint.1.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index a7d707249..271a44c9d 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -14,6 +14,22 @@ Checkpoints all the processes in one or more containers. You may use container I Checkpoint all running containers. +#### **--compress**, **-c** + +Specify the compression algorithm used for the checkpoint archive created +with the **--export, -e** option. Possible algorithms are *gzip*, *none* +and *zstd*. If no compression algorithm is specified Podman will use +*zstd*. + +One possible reason to use *none* is to enable faster creation of checkpoint +archives. Not compressing the checkpoint archive can result in faster checkpoint +archive creation. + +``` +# podman container checkpoint -l --compress=none --export=dump.tar +# podman container checkpoint -l --compress=gzip --export=dump.tar.gz +``` + #### **--export**, **-e** Export the checkpoint to a tar.gz file. The exported checkpoint can be used -- cgit v1.2.3-54-g00ecf From 949374e589876dcf726a9b93c48ac51bb625fed3 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 4 Jun 2021 15:42:58 +0000 Subject: Added tests for different checkpoint archive compressions Signed-off-by: Adrian Reber --- test/e2e/checkpoint_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index 9d0049910..4aca3682b 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -425,6 +425,106 @@ var _ = Describe("Podman checkpoint", func() { // Remove exported checkpoint os.Remove(fileName) }) + // This test does the same steps which are necessary for migrating + // a container from one host to another + It("podman checkpoint container with export and different compression algorithms", func() { + localRunString := getRunString([]string{"--rm", ALPINE, "top"}) + session := podmanTest.Podman(localRunString) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + cid := session.OutputToString() + fileName := "/tmp/checkpoint-" + cid + ".tar" + + // Checkpoint with the default algorithm + result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName}) + result.WaitWithDefaultTimeout() + + // As the container has been started with '--rm' it will be completely + // cleaned up after checkpointing. + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + + // Restore container + result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Checkpoint with the zstd algorithm + result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "--compress", "zstd"}) + result.WaitWithDefaultTimeout() + + // As the container has been started with '--rm' it will be completely + // cleaned up after checkpointing. + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + + // Restore container + result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Checkpoint with the none algorithm + result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "none"}) + result.WaitWithDefaultTimeout() + + // As the container has been started with '--rm' it will be completely + // cleaned up after checkpointing. + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + + // Restore container + result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Checkpoint with the gzip algorithm + result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "gzip"}) + result.WaitWithDefaultTimeout() + + // As the container has been started with '--rm' it will be completely + // cleaned up after checkpointing. + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + + // Restore container + result = podmanTest.Podman([]string{"container", "restore", "-i", fileName}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Checkpoint with the non-existing algorithm + result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "non-existing"}) + result.WaitWithDefaultTimeout() + + Expect(result.ExitCode()).To(Equal(125)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + result = podmanTest.Podman([]string{"rm", "-fa"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + + // Remove exported checkpoint + os.Remove(fileName) + }) It("podman checkpoint and restore container with root file-system changes", func() { // Start the container -- cgit v1.2.3-54-g00ecf