summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Reber <areber@redhat.com>2019-06-27 07:56:39 +0000
committerAdrian Reber <areber@redhat.com>2019-07-11 14:43:35 +0200
commit05549e8b2904427a1fb6d0b36889ac43360db073 (patch)
treef085e801b63094fb3f6c450ca9493f8a211414d8
parent1a3207488477876a1f4018bf0df95ed8eaf85afc (diff)
downloadpodman-05549e8b2904427a1fb6d0b36889ac43360db073.tar.gz
podman-05549e8b2904427a1fb6d0b36889ac43360db073.tar.bz2
podman-05549e8b2904427a1fb6d0b36889ac43360db073.zip
Add --ignore-rootfs option for checkpoint/restore
The newly added functionality to include the container's root file-system changes into the checkpoint archive can now be explicitly disabled. Either during checkpoint or during restore. If a container changes a lot of files during its runtime it might be more effective to migrated the root file-system changes in some other way and to not needlessly increase the size of the checkpoint archive. If a checkpoint archive does not contain the root file-system changes information it will automatically be skipped. If the root file-system changes are part of the checkpoint archive it is also possible to tell Podman to ignore these changes. Signed-off-by: Adrian Reber <areber@redhat.com>
-rw-r--r--cmd/podman/checkpoint.go1
-rw-r--r--cmd/podman/cliconfig/config.go2
-rw-r--r--cmd/podman/restore.go5
-rw-r--r--completions/bash/podman2
-rw-r--r--docs/podman-container-checkpoint.1.md10
-rw-r--r--docs/podman-container-restore.1.md7
-rw-r--r--libpod/container_api.go3
-rw-r--r--libpod/container_internal_linux.go73
-rw-r--r--pkg/adapter/containers.go5
-rw-r--r--pkg/adapter/containers_remote.go6
10 files changed, 79 insertions, 35 deletions
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go
index 6755bb073..22cdb1f39 100644
--- a/cmd/podman/checkpoint.go
+++ b/cmd/podman/checkpoint.go
@@ -46,6 +46,7 @@ func init() {
flags.BoolVarP(&checkpointCommand.All, "all", "a", false, "Checkpoint all running containers")
flags.BoolVarP(&checkpointCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.StringVarP(&checkpointCommand.Export, "export", "e", "", "Export the checkpoint image to a tar.gz")
+ flags.BoolVar(&checkpointCommand.IgnoreRootfs, "ignore-rootfs", false, "Do not include root file-system changes when exporting")
markFlagHiddenForRemoteClient("latest", flags)
}
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index e3e2edb95..be380cda0 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -92,6 +92,7 @@ type CheckpointValues struct {
All bool
Latest bool
Export string
+ IgnoreRootfs bool
}
type CommitValues struct {
@@ -433,6 +434,7 @@ type RestoreValues struct {
TcpEstablished bool
Import string
Name string
+ IgnoreRootfs bool
}
type RmValues struct {
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index 7ecec24ee..3ae141d41 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -45,6 +45,7 @@ func init() {
flags.BoolVar(&restoreCommand.TcpEstablished, "tcp-established", false, "Restore a container with established TCP connections")
flags.StringVarP(&restoreCommand.Import, "import", "i", "", "Restore from exported checkpoint archive (tar.gz)")
flags.StringVarP(&restoreCommand.Name, "name", "n", "", "Specify new name for container restored from exported checkpoint (only works with --import)")
+ flags.BoolVar(&restoreCommand.IgnoreRootfs, "ignore-rootfs", false, "Do not apply root file-system changes when importing from exported checkpoint")
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -60,6 +61,10 @@ func restoreCmd(c *cliconfig.RestoreValues, cmd *cobra.Command) error {
}
defer runtime.DeferredShutdown(false)
+ if c.Import == "" && c.IgnoreRootfs {
+ return errors.Errorf("--ignore-rootfs can only be used with --import")
+ }
+
if c.Import == "" && c.Name != "" {
return errors.Errorf("--name can only be used with --import")
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 65c6308cc..619c9e1e6 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -758,6 +758,7 @@ _podman_container_checkpoint() {
-R
--leave-running
--tcp-established
+ --ignore-rootfs
"
case "$prev" in
-e|--export)
@@ -870,6 +871,7 @@ _podman_container_restore() {
-l
--latest
--tcp-established
+ --ignore-rootfs
"
case "$prev" in
-i|--import)
diff --git a/docs/podman-container-checkpoint.1.md b/docs/podman-container-checkpoint.1.md
index 90c3919a9..034d338bb 100644
--- a/docs/podman-container-checkpoint.1.md
+++ b/docs/podman-container-checkpoint.1.md
@@ -42,7 +42,15 @@ connections.
Export the checkpoint to a tar.gz file. The exported checkpoint can be used
to import the container on another system and thus enabling container live
-migration.
+migration. This checkpoint archive also includes all changes to the container's
+root file-system, if not explicitly disabled using **--ignore-rootfs**
+
+**--ignore-rootfs**
+
+This only works in combination with **--export, -e**. If a checkpoint is
+exported to a tar.gz file it is possible with the help of **--ignore-rootfs**
+to explicitly disable including changes to the root file-system into
+the checkpoint archive file.
## EXAMPLE
diff --git a/docs/podman-container-restore.1.md b/docs/podman-container-restore.1.md
index c96a37f80..544a096d8 100644
--- a/docs/podman-container-restore.1.md
+++ b/docs/podman-container-restore.1.md
@@ -60,6 +60,13 @@ address to the container it was using before checkpointing as each IP address ca
be used once and the restored container will have another IP address. This also means
that **--name, -n** cannot be used in combination with **--tcp-established**.
+**--ignore-rootfs**
+
+This is only available in combination with **--import, -i**. If a container is restored
+from a checkpoint tar.gz file it is possible that it also contains all root file-system
+changes. With **--ignore-rootfs** it is possible to explicitly disable applying these
+root file-system changes to the restored container.
+
## EXAMPLE
podman container restore mywebserver
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 00467d2bf..c6e478846 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -799,6 +799,9 @@ type ContainerCheckpointOptions struct {
// checkpoint archive a new name should be used for the
// restored container
Name string
+ // IgnoreRootfs tells the API to not export changes to
+ // the container's root file-system (or to not import)
+ IgnoreRootfs bool
}
// Checkpoint checkpoints a container
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 77f607f0b..399220b9a 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -510,41 +510,44 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr
return nil
}
-func (c *Container) exportCheckpoint(dest string) (err error) {
+func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) (err error) {
if (len(c.config.NamedVolumes) > 0) || (len(c.Dependencies()) > 0) {
return errors.Errorf("Cannot export checkpoints of containers with named volumes or dependencies")
}
logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), dest)
+ includeFiles := []string{
+ "checkpoint",
+ "artifacts",
+ "ctr.log",
+ "config.dump",
+ "spec.dump",
+ "network.status"}
+
// Get root file-system changes included in the checkpoint archive
rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
- rootfsDiffFile, err := os.Create(rootfsDiffPath)
- if err != nil {
- return errors.Wrapf(err, "error creating root file-system diff file %q", rootfsDiffPath)
- }
- tarStream, err := c.runtime.GetDiffTarStream("", c.ID())
- if err != nil {
- return errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath)
- }
- _, err = io.Copy(rootfsDiffFile, tarStream)
- if err != nil {
- return errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath)
+ if !ignoreRootfs {
+ rootfsDiffFile, err := os.Create(rootfsDiffPath)
+ if err != nil {
+ return errors.Wrapf(err, "error creating root file-system diff file %q", rootfsDiffPath)
+ }
+ tarStream, err := c.runtime.GetDiffTarStream("", c.ID())
+ if err != nil {
+ return errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath)
+ }
+ _, err = io.Copy(rootfsDiffFile, tarStream)
+ if err != nil {
+ return errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath)
+ }
+ tarStream.Close()
+ rootfsDiffFile.Close()
+ includeFiles = append(includeFiles, "rootfs-diff.tar")
}
- tarStream.Close()
- rootfsDiffFile.Close()
-
input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{
Compression: archive.Gzip,
IncludeSourceDir: true,
- IncludeFiles: []string{
- "checkpoint",
- "artifacts",
- "ctr.log",
- "config.dump",
- "spec.dump",
- "rootfs-diff.tar",
- "network.status"},
+ IncludeFiles: includeFiles,
})
if err != nil {
@@ -627,7 +630,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
}
if options.TargetFile != "" {
- if err = c.exportCheckpoint(options.TargetFile); err != nil {
+ if err = c.exportCheckpoint(options.TargetFile, options.IgnoreRootfs); err != nil {
return err
}
}
@@ -816,17 +819,19 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
}
// Before actually restarting the container, apply the root file-system changes
- rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
- if _, err := os.Stat(rootfsDiffPath); err == nil {
- // Only do this if a rootfs-diff.tar actually exists
- rootfsDiffFile, err := os.Open(rootfsDiffPath)
- if err != nil {
- return errors.Wrapf(err, "Failed to open root file-system diff file %s", rootfsDiffPath)
- }
- if err := c.runtime.ApplyDiffTarStream(c.ID(), rootfsDiffFile); err != nil {
- return errors.Wrapf(err, "Failed to apply root file-system diff file %s", rootfsDiffPath)
+ if !options.IgnoreRootfs {
+ rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar")
+ if _, err := os.Stat(rootfsDiffPath); err == nil {
+ // Only do this if a rootfs-diff.tar actually exists
+ rootfsDiffFile, err := os.Open(rootfsDiffPath)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to open root file-system diff file %s", rootfsDiffPath)
+ }
+ if err := c.runtime.ApplyDiffTarStream(c.ID(), rootfsDiffFile); err != nil {
+ return errors.Wrapf(err, "Failed to apply root file-system diff file %s", rootfsDiffPath)
+ }
+ rootfsDiffFile.Close()
}
- rootfsDiffFile.Close()
}
if err := c.ociRuntime.createContainer(c, c.config.CgroupParent, &options); err != nil {
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 1cf9d686a..e0245d2ac 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -524,6 +524,10 @@ func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues) error {
KeepRunning: c.LeaveRunning,
TCPEstablished: c.TcpEstablished,
TargetFile: c.Export,
+ IgnoreRootfs: c.IgnoreRootfs,
+ }
+ if c.Export == "" && c.IgnoreRootfs {
+ return errors.Errorf("--ignore-rootfs can only be used with --export")
}
if c.All {
containers, err = r.Runtime.GetRunningContainers()
@@ -560,6 +564,7 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues)
TCPEstablished: c.TcpEstablished,
TargetFile: c.Import,
Name: c.Name,
+ IgnoreRootfs: c.IgnoreRootfs,
}
filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 5836d0788..5e8df1b62 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -668,6 +668,9 @@ func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues) error {
if c.Export != "" {
return errors.New("the remote client does not support exporting checkpoints")
}
+ if c.IgnoreRootfs {
+ return errors.New("the remote client does not support --ignore-rootfs")
+ }
var lastError error
ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
@@ -708,6 +711,9 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues)
if c.Import != "" {
return errors.New("the remote client does not support importing checkpoints")
}
+ if c.IgnoreRootfs {
+ return errors.New("the remote client does not support --ignore-rootfs")
+ }
var lastError error
ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)