diff options
author | Adrian Reber <areber@redhat.com> | 2019-06-27 06:16:32 +0000 |
---|---|---|
committer | Adrian Reber <areber@redhat.com> | 2019-07-11 14:43:34 +0200 |
commit | 217f2e77f86c95babc9697545e8880af38ec2e89 (patch) | |
tree | 0c3114b92d6e951fb927a989de95a6984472e762 /libpod | |
parent | d5f1caaf505a87f093b3c715e9c53ee304917ac4 (diff) | |
download | podman-217f2e77f86c95babc9697545e8880af38ec2e89.tar.gz podman-217f2e77f86c95babc9697545e8880af38ec2e89.tar.bz2 podman-217f2e77f86c95babc9697545e8880af38ec2e89.zip |
Include root file-system changes in container migration
One of the last limitations when migrating a container using Podman's
'podman container checkpoint --export=/path/to/archive.tar.gz' was
that it was necessary to manually handle changes to the container's root
file-system. The recommendation was to mount everything as --tmpfs where
the root file-system was changed.
This extends the checkpoint export functionality to also include all
changes to the root file-system in the checkpoint archive. The
checkpoint archive now includes a tarstream of the result from 'podman
diff'. This tarstream will be applied to the restored container before
restoring the container.
With this any container can now be migrated, even it there are changes
to the root file-system.
There was some discussion before implementing this to base the root
file-system migration on 'podman commit', but it seemed wrong to do
a 'podman commit' before the migration as that would change the parent
layer the restored container is referencing. Probably not really a
problem, but it would have meant that a migrated container will always
reference another storage top layer than it used to reference during
initial creation.
Signed-off-by: Adrian Reber <areber@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_linux.go | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index aa477611f..77f607f0b 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -515,6 +515,25 @@ func (c *Container) exportCheckpoint(dest string) (err error) { 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) + + // 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) + } + tarStream.Close() + rootfsDiffFile.Close() + + input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{ Compression: archive.Gzip, IncludeSourceDir: true, @@ -524,6 +543,7 @@ func (c *Container) exportCheckpoint(dest string) (err error) { "ctr.log", "config.dump", "spec.dump", + "rootfs-diff.tar", "network.status"}, }) @@ -546,6 +566,8 @@ func (c *Container) exportCheckpoint(dest string) (err error) { return err } + os.Remove(rootfsDiffPath) + return nil } @@ -792,6 +814,21 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if err := c.saveSpec(g.Spec()); err != nil { return err } + + // 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) + } + rootfsDiffFile.Close() + } + if err := c.ociRuntime.createContainer(c, c.config.CgroupParent, &options); err != nil { return err } @@ -809,7 +846,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if err != nil { logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err) } - cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status"} + cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status", "rootfs-diff.tar"} for _, del := range cleanup { file := filepath.Join(c.bundlePath(), del) err = os.Remove(file) |