diff options
-rw-r--r-- | cmd/podman/kill.go | 64 | ||||
-rw-r--r-- | completions/bash/podman | 2 | ||||
-rw-r--r-- | docs/podman-kill.1.md | 6 | ||||
-rw-r--r-- | docs/podman-stop.1.md | 8 | ||||
-rw-r--r-- | libpod/container_internal.go | 2 | ||||
-rw-r--r-- | pkg/spec/config_linux.go | 25 | ||||
-rw-r--r-- | pkg/spec/spec.go | 176 |
7 files changed, 170 insertions, 113 deletions
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index f80d77b8f..db3300984 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/rootless" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" @@ -14,6 +15,10 @@ import ( var ( killFlags = []cli.Flag{ + cli.BoolFlag{ + Name: "all, a", + Usage: "Signal all running containers", + }, cli.StringFlag{ Name: "signal, s", Usage: "Signal to send to the container", @@ -28,7 +33,7 @@ var ( Description: killDescription, Flags: killFlags, Action: killCmd, - ArgsUsage: "[CONTAINER_NAME_OR_ID]", + ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", UseShortOptionHandling: true, OnUsageError: usageErrorHandler, } @@ -37,11 +42,17 @@ var ( // killCmd kills one or more containers with a signal func killCmd(c *cli.Context) error { args := c.Args() - if len(args) == 0 && !c.Bool("latest") { - return errors.Errorf("specify one or more containers to kill") + if (!c.Bool("all") && !c.Bool("latest")) && len(args) == 0 { + return errors.Errorf("you must specify one or more containers to kill") + } + if (c.Bool("all") || c.Bool("latest")) && len(args) > 0 { + return errors.Errorf("you cannot specify any containers to kill with --latest or --all") + } + if c.Bool("all") && c.Bool("latest") { + return errors.Errorf("--all and --latest cannot be used together") } - if len(args) > 0 && c.Bool("latest") { - return errors.Errorf("you cannot specific any containers to kill with --latest") + if len(args) < 1 && !c.Bool("all") && !c.Bool("latest") { + return errors.Errorf("you must provide at least one container name or id") } if err := validateFlags(c, killFlags); err != nil { return err @@ -65,30 +76,45 @@ func killCmd(c *cli.Context) error { killSignal = uint(sysSignal) } - if c.Bool("latest") { - latestCtr, err := runtime.GetLatestContainer() + 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 latest container") + return errors.Wrapf(err, "unable to get running containers") } - args = append(args, latestCtr.ID()) - } - - var lastError error - for _, container := range args { - ctr, err := runtime.LookupContainer(container) + } else if c.Bool("latest") { + lastCtr, err := runtime.GetLatestContainer() if err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) + return errors.Wrapf(err, "unable to get last created container") + } + containers = append(containers, lastCtr) + } else { + 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 } - lastError = errors.Wrapf(err, "unable to find container %v", container) - continue + containers = append(containers, container) } + } + for _, ctr := range containers { if err := ctr.Kill(killSignal); err != nil { if lastError != nil { fmt.Fprintln(os.Stderr, lastError) } - lastError = errors.Wrapf(err, "unable to find container %v", container) + lastError = errors.Wrapf(err, "unable to find container %v", ctr.ID()) } else { fmt.Println(ctr.ID()) } diff --git a/completions/bash/podman b/completions/bash/podman index b97c4b0d5..bdd5a34e2 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1282,6 +1282,8 @@ _podman_kill() { --signal -s " local boolean_options=" + --all + -a --help -h --latest diff --git a/docs/podman-kill.1.md b/docs/podman-kill.1.md index 79449fc57..14066d151 100644 --- a/docs/podman-kill.1.md +++ b/docs/podman-kill.1.md @@ -10,6 +10,10 @@ podman\-kill - Kills one or more containers with a signal The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal. ## OPTIONS +**--all, -a** + +Signal all running containers. This does not include paused containers. + **--latest, -l** Instead of providing the container name or ID, use the last created container. If you use methods other than Podman @@ -30,6 +34,8 @@ podman kill --signal TERM 860a4b23 podman kill --latest +podman kill --signal KILL -a + ## SEE ALSO podman(1), podman-stop(1) diff --git a/docs/podman-stop.1.md b/docs/podman-stop.1.md index 98f74f269..813f0ef9e 100644 --- a/docs/podman-stop.1.md +++ b/docs/podman-stop.1.md @@ -15,10 +15,6 @@ container and also via command line when creating the container. ## OPTIONS -**--timeout, --time, t** - -Timeout to wait before forcibly stopping the container - **--all, -a** Stop all running containers. This does not include paused containers. @@ -28,6 +24,10 @@ Stop all running containers. This does not include paused containers. 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. +**--timeout, --time, t** + +Timeout to wait before forcibly stopping the container + ## EXAMPLE podman stop mywebserver diff --git a/libpod/container_internal.go b/libpod/container_internal.go index c88794212..0642c5aad 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1286,7 +1286,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } - var allHooks map[string][]spec.Hook + allHooks := make(map[string][]spec.Hook) for _, hDir := range c.runtime.config.HooksDir { manager, err := hooks.New(ctx, []string{hDir}, []string{"poststop"}, lang) if err != nil { diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 6c0a99419..20cdcc458 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -91,18 +91,23 @@ func getSeccompConfig(config *CreateConfig, configSpec *spec.Spec) (*spec.LinuxS } func (c *CreateConfig) createBlockIO() (*spec.LinuxBlockIO, error) { + var ret *spec.LinuxBlockIO bio := &spec.LinuxBlockIO{} - bio.Weight = &c.Resources.BlkioWeight + if c.Resources.BlkioWeight > 0 { + ret = bio + bio.Weight = &c.Resources.BlkioWeight + } if len(c.Resources.BlkioWeightDevice) > 0 { var lwds []spec.LinuxWeightDevice + ret = bio for _, i := range c.Resources.BlkioWeightDevice { wd, err := validateweightDevice(i) if err != nil { - return bio, errors.Wrapf(err, "invalid values for blkio-weight-device") + return ret, errors.Wrapf(err, "invalid values for blkio-weight-device") } wdStat, err := getStatFromPath(wd.path) if err != nil { - return bio, errors.Wrapf(err, "error getting stat from path %q", wd.path) + return ret, errors.Wrapf(err, "error getting stat from path %q", wd.path) } lwd := spec.LinuxWeightDevice{ Weight: &wd.weight, @@ -114,34 +119,38 @@ func (c *CreateConfig) createBlockIO() (*spec.LinuxBlockIO, error) { bio.WeightDevice = lwds } if len(c.Resources.DeviceReadBps) > 0 { + ret = bio readBps, err := makeThrottleArray(c.Resources.DeviceReadBps, bps) if err != nil { - return bio, err + return ret, err } bio.ThrottleReadBpsDevice = readBps } if len(c.Resources.DeviceWriteBps) > 0 { + ret = bio writeBpds, err := makeThrottleArray(c.Resources.DeviceWriteBps, bps) if err != nil { - return bio, err + return ret, err } bio.ThrottleWriteBpsDevice = writeBpds } if len(c.Resources.DeviceReadIOps) > 0 { + ret = bio readIOps, err := makeThrottleArray(c.Resources.DeviceReadIOps, iops) if err != nil { - return bio, err + return ret, err } bio.ThrottleReadIOPSDevice = readIOps } if len(c.Resources.DeviceWriteIOps) > 0 { + ret = bio writeIOps, err := makeThrottleArray(c.Resources.DeviceWriteIOps, iops) if err != nil { - return bio, err + return ret, err } bio.ThrottleWriteIOPSDevice = writeIOps } - return bio, nil + return ret, nil } func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrottleDevice, error) { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index ad14ea65d..1ad55fc8c 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -159,73 +159,86 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } g.AddProcessEnv("container", "podman") - canAddResources := !rootless.IsRootless() - - if canAddResources { - // RESOURCES - MEMORY - if config.Resources.Memory != 0 { - g.SetLinuxResourcesMemoryLimit(config.Resources.Memory) - // If a swap limit is not explicitly set, also set a swap limit - // Default to double the memory limit - if config.Resources.MemorySwap == 0 { - g.SetLinuxResourcesMemorySwap(2 * config.Resources.Memory) - } - } - if config.Resources.MemoryReservation != 0 { - g.SetLinuxResourcesMemoryReservation(config.Resources.MemoryReservation) - } - if config.Resources.MemorySwap != 0 { - g.SetLinuxResourcesMemorySwap(config.Resources.MemorySwap) - } - if config.Resources.KernelMemory != 0 { - g.SetLinuxResourcesMemoryKernel(config.Resources.KernelMemory) - } - if config.Resources.MemorySwappiness != -1 { - g.SetLinuxResourcesMemorySwappiness(uint64(config.Resources.MemorySwappiness)) - } - g.SetLinuxResourcesMemoryDisableOOMKiller(config.Resources.DisableOomKiller) - g.SetProcessOOMScoreAdj(config.Resources.OomScoreAdj) - - // RESOURCES - CPU - if config.Resources.CPUShares != 0 { - g.SetLinuxResourcesCPUShares(config.Resources.CPUShares) - } - if config.Resources.CPUQuota != 0 { - g.SetLinuxResourcesCPUQuota(config.Resources.CPUQuota) - } - if config.Resources.CPUPeriod != 0 { - g.SetLinuxResourcesCPUPeriod(config.Resources.CPUPeriod) - } - if config.Resources.CPUs != 0 { - g.SetLinuxResourcesCPUPeriod(cpuPeriod) - g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * cpuPeriod)) - } - if config.Resources.CPURtRuntime != 0 { - g.SetLinuxResourcesCPURealtimeRuntime(config.Resources.CPURtRuntime) - } - if config.Resources.CPURtPeriod != 0 { - g.SetLinuxResourcesCPURealtimePeriod(config.Resources.CPURtPeriod) - } - if config.Resources.CPUsetCPUs != "" { - g.SetLinuxResourcesCPUCpus(config.Resources.CPUsetCPUs) - } - if config.Resources.CPUsetMems != "" { - g.SetLinuxResourcesCPUMems(config.Resources.CPUsetMems) - } - - // Devices - if config.Privileged { - // If privileged, we need to add all the host devices to the - // spec. We do not add the user provided ones because we are - // already adding them all. + addedResources := false + + // RESOURCES - MEMORY + if config.Resources.Memory != 0 { + g.SetLinuxResourcesMemoryLimit(config.Resources.Memory) + // If a swap limit is not explicitly set, also set a swap limit + // Default to double the memory limit + if config.Resources.MemorySwap == 0 { + g.SetLinuxResourcesMemorySwap(2 * config.Resources.Memory) + } + addedResources = true + } + if config.Resources.MemoryReservation != 0 { + g.SetLinuxResourcesMemoryReservation(config.Resources.MemoryReservation) + addedResources = true + } + if config.Resources.MemorySwap != 0 { + g.SetLinuxResourcesMemorySwap(config.Resources.MemorySwap) + addedResources = true + } + if config.Resources.KernelMemory != 0 { + g.SetLinuxResourcesMemoryKernel(config.Resources.KernelMemory) + addedResources = true + } + if config.Resources.MemorySwappiness != -1 { + g.SetLinuxResourcesMemorySwappiness(uint64(config.Resources.MemorySwappiness)) + addedResources = true + } + g.SetLinuxResourcesMemoryDisableOOMKiller(config.Resources.DisableOomKiller) + g.SetProcessOOMScoreAdj(config.Resources.OomScoreAdj) + + // RESOURCES - CPU + if config.Resources.CPUShares != 0 { + g.SetLinuxResourcesCPUShares(config.Resources.CPUShares) + addedResources = true + } + if config.Resources.CPUQuota != 0 { + g.SetLinuxResourcesCPUQuota(config.Resources.CPUQuota) + addedResources = true + } + if config.Resources.CPUPeriod != 0 { + g.SetLinuxResourcesCPUPeriod(config.Resources.CPUPeriod) + addedResources = true + } + if config.Resources.CPUs != 0 { + g.SetLinuxResourcesCPUPeriod(cpuPeriod) + g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * cpuPeriod)) + addedResources = true + } + if config.Resources.CPURtRuntime != 0 { + g.SetLinuxResourcesCPURealtimeRuntime(config.Resources.CPURtRuntime) + addedResources = true + } + if config.Resources.CPURtPeriod != 0 { + g.SetLinuxResourcesCPURealtimePeriod(config.Resources.CPURtPeriod) + addedResources = true + } + if config.Resources.CPUsetCPUs != "" { + g.SetLinuxResourcesCPUCpus(config.Resources.CPUsetCPUs) + addedResources = true + } + if config.Resources.CPUsetMems != "" { + g.SetLinuxResourcesCPUMems(config.Resources.CPUsetMems) + addedResources = true + } + + // Devices + if config.Privileged { + // If privileged, we need to add all the host devices to the + // spec. We do not add the user provided ones because we are + // already adding them all. + if !rootless.IsRootless() { if err := config.AddPrivilegedDevices(&g); err != nil { return nil, err } - } else { - for _, device := range config.Devices { - if err := addDevice(&g, device); err != nil { - return nil, err - } + } + } else { + for _, device := range config.Devices { + if err := addDevice(&g, device); err != nil { + return nil, err } } } @@ -240,13 +253,12 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint g.SetProcessNoNewPrivileges(config.NoNewPrivs) g.SetProcessApparmorProfile(config.ApparmorProfile) - if canAddResources { - blockAccessToKernelFilesystems(config, &g) + blockAccessToKernelFilesystems(config, &g) - // RESOURCES - PIDS - if config.Resources.PidsLimit != 0 { - g.SetLinuxResourcesPidsLimit(config.Resources.PidsLimit) - } + // RESOURCES - PIDS + if config.Resources.PidsLimit != 0 { + g.SetLinuxResourcesPidsLimit(config.Resources.PidsLimit) + addedResources = true } if config.Systemd && (strings.HasSuffix(config.Command[0], "init") || @@ -347,21 +359,23 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint configSpec.Mounts = supercedeUserMounts(volumeMounts, configSpec.Mounts) //--mount configSpec.Mounts = supercedeUserMounts(config.initFSMounts(), configSpec.Mounts) - if canAddResources { - // BLOCK IO - blkio, err := config.CreateBlockIO() - if err != nil { - return nil, errors.Wrapf(err, "error creating block io") - } - if blkio != nil { - configSpec.Linux.Resources.BlockIO = blkio - } + // BLOCK IO + blkio, err := config.CreateBlockIO() + if err != nil { + return nil, errors.Wrapf(err, "error creating block io") + } + if blkio != nil { + configSpec.Linux.Resources.BlockIO = blkio + addedResources = true } - // If we cannot add resources be sure everything is cleared out - if !canAddResources { + if rootless.IsRootless() { + if addedResources { + return nil, errors.New("invalid configuration, cannot set resources with rootless containers") + } configSpec.Linux.Resources = &spec.LinuxResources{} } + return configSpec, nil } |