Add parallel operation to podman stop

This is the other command that benefits greatly from being run in
parallel, due to the potential 15-second timeout for containers
that ignore SIGTERM.

While we're at it, also clean up how stop timeout is set. This
needs to be an optional parameter, so that the value set when the
container is created with `--stop-timeout` will be respected.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
Matthew Heon
2020-06-05 16:09:26 -04:00
parent 723e823439
commit 1cc9731dfa
4 changed files with 29 additions and 29 deletions

View File

@ -85,9 +85,8 @@ func stop(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
stopOptions.Timeout = containerConfig.Engine.StopTimeout
if cmd.Flag("time").Changed { if cmd.Flag("time").Changed {
stopOptions.Timeout = stopTimeout stopOptions.Timeout = &stopTimeout
} }
responses, err := registry.ContainerEngine().ContainerStop(context.Background(), args, stopOptions) responses, err := registry.ContainerEngine().ContainerStop(context.Background(), args, stopOptions)

View File

@ -84,7 +84,7 @@ type StopOptions struct {
CIDFiles []string CIDFiles []string
Ignore bool Ignore bool
Latest bool Latest bool
Timeout uint Timeout *uint
} }
type StopReport struct { type StopReport struct {

View File

@ -162,32 +162,33 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) { if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
return nil, err return nil, err
} }
for _, con := range ctrs { errMap, err := parallel.ParallelContainerOp(ctx, ctrs, func(c *libpod.Container) error {
report := entities.StopReport{Id: con.ID()} var err error
err = con.StopWithTimeout(options.Timeout) if options.Timeout != nil {
if err != nil { err = c.StopWithTimeout(*options.Timeout)
// These first two are considered non-fatal under the right conditions } else {
if errors.Cause(err) == define.ErrCtrStopped { err = c.Stop()
logrus.Debugf("Container %s is already stopped", con.ID())
reports = append(reports, &report)
continue
} else if options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
logrus.Debugf("Container %s is not running, could not stop", con.ID())
reports = append(reports, &report)
continue
}
report.Err = err
reports = append(reports, &report)
continue
} else if err := con.Cleanup(ctx); err != nil {
// Only if no error, proceed to cleanup to ensure all
// mounts are removed before we exit.
report.Err = err
reports = append(reports, &report)
continue
} }
reports = append(reports, &report) if err != nil {
switch {
case errors.Cause(err) == define.ErrCtrStopped:
logrus.Debugf("Container %s is already stopped", c.ID())
case options.All && errors.Cause(err) == define.ErrCtrStateInvalid:
logrus.Debugf("Container %s is not running, could not stop", c.ID())
default:
return err
}
}
return c.Cleanup(ctx)
})
if err != nil {
return nil, err
}
for ctr, err := range errMap {
report := new(entities.StopReport)
report.Id = ctr.ID()
report.Err = err
reports = append(reports, report)
} }
return reports, nil return reports, nil
} }

View File

@ -100,7 +100,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
} }
for _, c := range ctrs { for _, c := range ctrs {
report := entities.StopReport{Id: c.ID} report := entities.StopReport{Id: c.ID}
if err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout); err != nil { if err = containers.Stop(ic.ClientCxt, c.ID, options.Timeout); err != nil {
// These first two are considered non-fatal under the right conditions // These first two are considered non-fatal under the right conditions
if errors.Cause(err).Error() == define.ErrCtrStopped.Error() { if errors.Cause(err).Error() == define.ErrCtrStopped.Error() {
logrus.Debugf("Container %s is already stopped", c.ID) logrus.Debugf("Container %s is already stopped", c.ID)