mirror of
https://github.com/containers/podman.git
synced 2025-07-15 03:02:52 +08:00
Merge pull request #12333 from rst0git/file-locks
Add --file-locks checkpoint/restore option
This commit is contained in:
@ -55,6 +55,7 @@ func init() {
|
|||||||
flags.BoolVarP(&checkpointOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
flags.BoolVarP(&checkpointOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
||||||
flags.BoolVarP(&checkpointOptions.LeaveRunning, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk")
|
flags.BoolVarP(&checkpointOptions.LeaveRunning, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk")
|
||||||
flags.BoolVar(&checkpointOptions.TCPEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
|
flags.BoolVar(&checkpointOptions.TCPEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
|
||||||
|
flags.BoolVar(&checkpointOptions.FileLocks, "file-locks", false, "Checkpoint a container with file locks")
|
||||||
flags.BoolVarP(&checkpointOptions.All, "all", "a", false, "Checkpoint all running containers")
|
flags.BoolVarP(&checkpointOptions.All, "all", "a", false, "Checkpoint all running containers")
|
||||||
|
|
||||||
exportFlagName := "export"
|
exportFlagName := "export"
|
||||||
|
@ -53,6 +53,7 @@ func init() {
|
|||||||
flags.BoolVarP(&restoreOptions.All, "all", "a", false, "Restore all checkpointed containers")
|
flags.BoolVarP(&restoreOptions.All, "all", "a", false, "Restore all checkpointed containers")
|
||||||
flags.BoolVarP(&restoreOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
flags.BoolVarP(&restoreOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
||||||
flags.BoolVar(&restoreOptions.TCPEstablished, "tcp-established", false, "Restore a container with established TCP connections")
|
flags.BoolVar(&restoreOptions.TCPEstablished, "tcp-established", false, "Restore a container with established TCP connections")
|
||||||
|
flags.BoolVar(&restoreOptions.FileLocks, "file-locks", false, "Restore a container with file locks")
|
||||||
|
|
||||||
importFlagName := "import"
|
importFlagName := "import"
|
||||||
flags.StringVarP(&restoreOptions.Import, importFlagName, "i", "", "Restore from exported checkpoint archive (tar.gz)")
|
flags.StringVarP(&restoreOptions.Import, importFlagName, "i", "", "Restore from exported checkpoint archive (tar.gz)")
|
||||||
|
@ -110,6 +110,14 @@ restore. Defaults to not checkpointing *containers* with established TCP
|
|||||||
connections.\
|
connections.\
|
||||||
The default is **false**.
|
The default is **false**.
|
||||||
|
|
||||||
|
#### **--file-locks**
|
||||||
|
|
||||||
|
Checkpoint a *container* with file locks. If an application running in the container
|
||||||
|
is using file locks, this OPTION is required during checkpoint and restore. Otherwise
|
||||||
|
checkpointing *containers* with file locks is expected to fail. If file locks are not
|
||||||
|
used, this option is ignored.\
|
||||||
|
The default is **false**.
|
||||||
|
|
||||||
#### **--with-previous**
|
#### **--with-previous**
|
||||||
|
|
||||||
Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`.\
|
Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`.\
|
||||||
|
@ -143,6 +143,14 @@ option is ignored. Defaults to not restoring *containers* with established TCP
|
|||||||
connections.\
|
connections.\
|
||||||
The default is **false**.
|
The default is **false**.
|
||||||
|
|
||||||
|
#### **--file-locks**
|
||||||
|
|
||||||
|
Restore a *container* with file locks. This option is required to
|
||||||
|
restore file locks from a checkpoint image. If the checkpoint image
|
||||||
|
does not contain file locks, this option is ignored. Defaults to not
|
||||||
|
restoring file locks.\
|
||||||
|
The default is **false**.
|
||||||
|
|
||||||
## EXAMPLE
|
## EXAMPLE
|
||||||
Restores the container "mywebserver".
|
Restores the container "mywebserver".
|
||||||
```
|
```
|
||||||
|
@ -798,6 +798,9 @@ type ContainerCheckpointOptions struct {
|
|||||||
// how much time each component in the stack requires to
|
// how much time each component in the stack requires to
|
||||||
// checkpoint a container.
|
// checkpoint a container.
|
||||||
PrintStats bool
|
PrintStats bool
|
||||||
|
// FileLocks tells the API to checkpoint/restore a container
|
||||||
|
// with file-locks
|
||||||
|
FileLocks bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkpoint checkpoints a container
|
// Checkpoint checkpoints a container
|
||||||
|
@ -794,6 +794,9 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container
|
|||||||
if options.TCPEstablished {
|
if options.TCPEstablished {
|
||||||
args = append(args, "--tcp-established")
|
args = append(args, "--tcp-established")
|
||||||
}
|
}
|
||||||
|
if options.FileLocks {
|
||||||
|
args = append(args, "--file-locks")
|
||||||
|
}
|
||||||
if !options.PreCheckPoint && options.KeepRunning {
|
if !options.PreCheckPoint && options.KeepRunning {
|
||||||
args = append(args, "--leave-running")
|
args = append(args, "--leave-running")
|
||||||
}
|
}
|
||||||
@ -1101,6 +1104,9 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
|
|||||||
if restoreOptions.TCPEstablished {
|
if restoreOptions.TCPEstablished {
|
||||||
args = append(args, "--runtime-opt", "--tcp-established")
|
args = append(args, "--runtime-opt", "--tcp-established")
|
||||||
}
|
}
|
||||||
|
if restoreOptions.FileLocks {
|
||||||
|
args = append(args, "--runtime-opt", "--file-locks")
|
||||||
|
}
|
||||||
if restoreOptions.Pod != "" {
|
if restoreOptions.Pod != "" {
|
||||||
mountLabel := ctr.config.MountLabel
|
mountLabel := ctr.config.MountLabel
|
||||||
processLabel := ctr.config.ProcessLabel
|
processLabel := ctr.config.ProcessLabel
|
||||||
|
@ -53,6 +53,7 @@ type CheckpointOptions struct {
|
|||||||
PrintStats *bool
|
PrintStats *bool
|
||||||
PreCheckpoint *bool
|
PreCheckpoint *bool
|
||||||
WithPrevious *bool
|
WithPrevious *bool
|
||||||
|
FileLocks *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run ../generator/generator.go RestoreOptions
|
//go:generate go run ../generator/generator.go RestoreOptions
|
||||||
@ -69,6 +70,7 @@ type RestoreOptions struct {
|
|||||||
Pod *string
|
Pod *string
|
||||||
PrintStats *bool
|
PrintStats *bool
|
||||||
PublishPorts []string
|
PublishPorts []string
|
||||||
|
FileLocks *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run ../generator/generator.go CreateOptions
|
//go:generate go run ../generator/generator.go CreateOptions
|
||||||
|
@ -136,3 +136,18 @@ func (o *CheckpointOptions) GetWithPrevious() bool {
|
|||||||
}
|
}
|
||||||
return *o.WithPrevious
|
return *o.WithPrevious
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithFileLocks set field FileLocks to given value
|
||||||
|
func (o *CheckpointOptions) WithFileLocks(value bool) *CheckpointOptions {
|
||||||
|
o.FileLocks = &value
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFileLocks returns value of field FileLocks
|
||||||
|
func (o *CheckpointOptions) GetFileLocks() bool {
|
||||||
|
if o.FileLocks == nil {
|
||||||
|
var z bool
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
return *o.FileLocks
|
||||||
|
}
|
||||||
|
@ -181,3 +181,18 @@ func (o *RestoreOptions) GetPublishPorts() []string {
|
|||||||
}
|
}
|
||||||
return o.PublishPorts
|
return o.PublishPorts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithFileLocks set field FileLocks to given value
|
||||||
|
func (o *RestoreOptions) WithFileLocks(value bool) *RestoreOptions {
|
||||||
|
o.FileLocks = &value
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFileLocks returns value of field FileLocks
|
||||||
|
func (o *RestoreOptions) GetFileLocks() bool {
|
||||||
|
if o.FileLocks == nil {
|
||||||
|
var z bool
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
return *o.FileLocks
|
||||||
|
}
|
||||||
|
@ -191,6 +191,7 @@ type CheckpointOptions struct {
|
|||||||
WithPrevious bool
|
WithPrevious bool
|
||||||
Compression archive.Compression
|
Compression archive.Compression
|
||||||
PrintStats bool
|
PrintStats bool
|
||||||
|
FileLocks bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckpointReport struct {
|
type CheckpointReport struct {
|
||||||
@ -215,6 +216,7 @@ type RestoreOptions struct {
|
|||||||
PublishPorts []string
|
PublishPorts []string
|
||||||
Pod string
|
Pod string
|
||||||
PrintStats bool
|
PrintStats bool
|
||||||
|
FileLocks bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type RestoreReport struct {
|
type RestoreReport struct {
|
||||||
|
@ -516,6 +516,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
|
|||||||
WithPrevious: options.WithPrevious,
|
WithPrevious: options.WithPrevious,
|
||||||
Compression: options.Compression,
|
Compression: options.Compression,
|
||||||
PrintStats: options.PrintStats,
|
PrintStats: options.PrintStats,
|
||||||
|
FileLocks: options.FileLocks,
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.All {
|
if options.All {
|
||||||
|
@ -303,6 +303,7 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string,
|
|||||||
|
|
||||||
func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, opts entities.CheckpointOptions) ([]*entities.CheckpointReport, error) {
|
func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, opts entities.CheckpointOptions) ([]*entities.CheckpointReport, error) {
|
||||||
options := new(containers.CheckpointOptions)
|
options := new(containers.CheckpointOptions)
|
||||||
|
options.WithFileLocks(opts.FileLocks)
|
||||||
options.WithIgnoreRootfs(opts.IgnoreRootFS)
|
options.WithIgnoreRootfs(opts.IgnoreRootFS)
|
||||||
options.WithKeep(opts.Keep)
|
options.WithKeep(opts.Keep)
|
||||||
options.WithExport(opts.Export)
|
options.WithExport(opts.Export)
|
||||||
@ -352,6 +353,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
options := new(containers.RestoreOptions)
|
options := new(containers.RestoreOptions)
|
||||||
|
options.WithFileLocks(opts.FileLocks)
|
||||||
options.WithIgnoreRootfs(opts.IgnoreRootFS)
|
options.WithIgnoreRootfs(opts.IgnoreRootFS)
|
||||||
options.WithIgnoreVolumes(opts.IgnoreVolumes)
|
options.WithIgnoreVolumes(opts.IgnoreVolumes)
|
||||||
options.WithIgnoreStaticIP(opts.IgnoreStaticIP)
|
options.WithIgnoreStaticIP(opts.IgnoreStaticIP)
|
||||||
|
@ -1340,4 +1340,41 @@ var _ = Describe("Podman checkpoint", func() {
|
|||||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman checkpoint and restore container with --file-locks", func() {
|
||||||
|
if !strings.Contains(podmanTest.OCIRuntime, "runc") {
|
||||||
|
// TODO: Enable test for crun when this feature has been released
|
||||||
|
// https://github.com/containers/crun/pull/783
|
||||||
|
Skip("FIXME: requires crun >= 1.4")
|
||||||
|
}
|
||||||
|
localRunString := getRunString([]string{"--name", "test_name", ALPINE, "flock", "test.lock", "sleep", "100"})
|
||||||
|
session := podmanTest.Podman(localRunString)
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
// Checkpoint is expected to fail without --file-locks
|
||||||
|
result := podmanTest.Podman([]string{"container", "checkpoint", "test_name"})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).Should(Exit(125))
|
||||||
|
Expect(result.ErrorToString()).To(ContainSubstring("criu failed"))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
|
||||||
|
// Checkpoint is expected to succeed with --file-locks
|
||||||
|
result = podmanTest.Podman([]string{"container", "checkpoint", "--file-locks", "test_name"})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).Should(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||||
|
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
|
||||||
|
|
||||||
|
result = podmanTest.Podman([]string{"container", "restore", "--file-locks", "test_name"})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
|
||||||
|
Expect(result).Should(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
|
||||||
|
|
||||||
|
result = podmanTest.Podman([]string{"rm", "-t", "0", "-f", "test_name"})
|
||||||
|
result.WaitWithDefaultTimeout()
|
||||||
|
Expect(result).Should(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user