Add --sync option to podman rm

With the changes made recently to ensure Podman does not hit the
OCI runtime as often to sync state, we can find ourselves in a
situation where the runtime's state does not match ours.

Add a --sync flag to podman rm to ensure we can still remove
containers when this happens.

Signed-off-by: Matthew Heon <mheon@redhat.com>
This commit is contained in:
Matthew Heon
2018-11-28 12:24:14 -05:00
parent 75b19ca8ab
commit a0c9be2061
4 changed files with 29 additions and 11 deletions

View File

@ -20,6 +20,10 @@ var (
Usage: "Force removal of a running container. The default is false", Usage: "Force removal of a running container. The default is false",
}, },
LatestFlag, LatestFlag,
cli.BoolFlag{
Name: "sync",
Usage: "Sync container state with OCI runtime before removing",
},
cli.BoolFlag{ cli.BoolFlag{
Name: "volumes, v", Name: "volumes, v",
Usage: "Remove the volumes associated with the container (Not implemented yet)", Usage: "Remove the volumes associated with the container (Not implemented yet)",
@ -73,6 +77,12 @@ func rmCmd(c *cli.Context) error {
for _, container := range delContainers { for _, container := range delContainers {
con := container con := container
f := func() error { f := func() error {
if c.Bool("sync") {
if err := con.Sync(); err != nil {
return err
}
}
return runtime.RemoveContainer(ctx, con, c.Bool("force")) return runtime.RemoveContainer(ctx, con, c.Bool("force"))
} }

View File

@ -1828,6 +1828,7 @@ _podman_rm() {
-h -h
--latest --latest
-l -l
--sync
--volumes --volumes
-v -v
" "

View File

@ -24,6 +24,13 @@ Remove all containers. Can be used in conjunction with -f as well.
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
to run containers such as CRI-O, the last started container could be from either of those methods. to run containers such as CRI-O, the last started container could be from either of those methods.
**--sync**
Force a sync of container state with the OCI runtime before attempting to remove.
In some cases, a container's state in the runtime can become out of sync with Podman's state,
which can cause Podman to refuse to remove containers because it believes they are still running.
A sync will resolve this issue.
**--volumes, -v** **--volumes, -v**
Remove the volumes associated with the container. (Not yet implemented) Remove the volumes associated with the container. (Not yet implemented)

View File

@ -675,22 +675,22 @@ func (c *Container) Batch(batchFunc func(*Container) error) error {
return err return err
} }
// Sync updates the current state of the container, checking whether its state // Sync updates the status of a container by querying the OCI runtime.
// has changed // If the container has not been created inside the OCI runtime, nothing will be
// Sync can only be used inside Batch() - otherwise, it will be done // done.
// automatically. // Most of the time, Podman does not explicitly query the OCI runtime for
// When called outside Batch(), Sync() is a no-op // container status, and instead relies upon exit files created by conmon.
// This can cause a disconnect between running state and what Podman sees in
// cases where Conmon was killed unexpected, or runc was upgraded.
// Running a manual Sync() ensures that container state will be correct in
// such situations.
func (c *Container) Sync() error { func (c *Container) Sync() error {
if !c.batched {
return nil
}
// If runtime knows about the container, update its status in runtime // If runtime knows about the container, update its status in runtime
// And then save back to disk // And then save back to disk
if (c.state.State != ContainerStateUnknown) && if (c.state.State != ContainerStateUnknown) &&
(c.state.State != ContainerStateConfigured) { (c.state.State != ContainerStateConfigured) &&
(c.state.State != ContainerStateExited) {
oldState := c.state.State oldState := c.state.State
// TODO: optionally replace this with a stat for the exit file
if err := c.runtime.ociRuntime.updateContainerStatus(c, true); err != nil { if err := c.runtime.ociRuntime.updateContainerStatus(c, true); err != nil {
return err return err
} }