summaryrefslogtreecommitdiff
path: root/cmd/podman/stop.go
blob: f5c0fca854cfcd923da9571d74a897a354de3e3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main

import (
	"fmt"
	"os"
	rt "runtime"

	"github.com/containers/libpod/cmd/podman/libpodruntime"
	"github.com/containers/libpod/libpod"
	"github.com/containers/libpod/pkg/rootless"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

var (
	stopFlags = []cli.Flag{
		cli.UintFlag{
			Name:  "timeout, time, t",
			Usage: "Seconds to wait for stop before killing the container",
			Value: libpod.CtrRemoveTimeout,
		},
		cli.BoolFlag{
			Name:  "all, a",
			Usage: "stop all running containers",
		}, LatestFlag,
	}
	stopDescription = `
   podman stop

   Stops one or more running containers.  The container name or ID can be used.
   A timeout to forcibly stop the container can also be set but defaults to 10
   seconds otherwise.
`

	stopCommand = cli.Command{
		Name:         "stop",
		Usage:        "Stop one or more containers",
		Description:  stopDescription,
		Flags:        sortFlags(stopFlags),
		Action:       stopCmd,
		ArgsUsage:    "CONTAINER-NAME [CONTAINER-NAME ...]",
		OnUsageError: usageErrorHandler,
	}
)

func stopCmd(c *cli.Context) error {

	if err := checkAllAndLatest(c); err != nil {
		return err
	}

	if err := validateFlags(c, stopFlags); err != nil {
		return err
	}

	rootless.SetSkipStorageSetup(true)
	runtime, err := libpodruntime.GetRuntime(c)
	if err != nil {
		return errors.Wrapf(err, "could not get runtime")
	}
	defer runtime.Shutdown(false)

	var filterFuncs []libpod.ContainerFilter
	var containers []*libpod.Container
	var lastError error

	if c.Bool("all") {
		// only get running containers
		filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
			state, _ := c.State()
			return state == libpod.ContainerStateRunning
		})
		containers, err = runtime.GetContainers(filterFuncs...)
		if err != nil {
			return errors.Wrapf(err, "unable to get running containers")
		}
	} else if c.Bool("latest") {
		lastCtr, err := runtime.GetLatestContainer()
		if err != nil {
			return errors.Wrapf(err, "unable to get last created container")
		}
		containers = append(containers, lastCtr)
	} else {
		args := c.Args()
		for _, i := range args {
			container, err := runtime.LookupContainer(i)
			if err != nil {
				if lastError != nil {
					fmt.Fprintln(os.Stderr, lastError)
				}
				lastError = errors.Wrapf(err, "unable to find container %s", i)
				continue
			}
			containers = append(containers, container)
		}
	}

	var stopFuncs []workerInput
	for _, ctr := range containers {
		con := ctr
		var stopTimeout uint
		if c.IsSet("timeout") {
			stopTimeout = c.Uint("timeout")
		} else {
			stopTimeout = ctr.StopTimeout()
		}
		f := func() error {
			return con.StopWithTimeout(stopTimeout)
		}
		stopFuncs = append(stopFuncs, workerInput{
			containerID:  con.ID(),
			parallelFunc: f,
		})
	}

	stopErrors := parallelExecuteWorkerPool(rt.NumCPU()*3, stopFuncs)

	for cid, result := range stopErrors {
		if result != nil && result != libpod.ErrCtrStopped {
			fmt.Println(result.Error())
			lastError = result
			continue
		}
		fmt.Println(cid)
	}
	return lastError
}