summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2017-11-22 07:57:31 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2017-11-22 20:53:15 +0000
commit195d48d86d871f531d72e0669ea96d315845da35 (patch)
tree8d1aaf245b769a4f9ef666f3a9b794273c7247a0 /cmd
parentc344fe61c11beaf687da284f71bde2311b91371d (diff)
downloadpodman-195d48d86d871f531d72e0669ea96d315845da35.tar.gz
podman-195d48d86d871f531d72e0669ea96d315845da35.tar.bz2
podman-195d48d86d871f531d72e0669ea96d315845da35.zip
Copy some verification code out of Docker to verify user input
Added lots of verification code to make sure resourses asociated with containers is correct. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #60 Approved by: umohnani8
Diffstat (limited to 'cmd')
-rw-r--r--cmd/kpod/common.go1
-rw-r--r--cmd/kpod/create.go24
-rw-r--r--cmd/kpod/create_cli.go148
-rw-r--r--cmd/kpod/spec.go20
4 files changed, 174 insertions, 19 deletions
diff --git a/cmd/kpod/common.go b/cmd/kpod/common.go
index d924f17a3..339f56fdd 100644
--- a/cmd/kpod/common.go
+++ b/cmd/kpod/common.go
@@ -326,6 +326,7 @@ var createFlags = []cli.Flag{
cli.Int64Flag{
Name: "memory-swappiness",
Usage: "Tune container memory swappiness (0 to 100) (default -1)",
+ Value: -1,
},
cli.StringFlag{
Name: "name",
diff --git a/cmd/kpod/create.go b/cmd/kpod/create.go
index d609d011e..9e4162993 100644
--- a/cmd/kpod/create.go
+++ b/cmd/kpod/create.go
@@ -35,8 +35,8 @@ var (
)
type createResourceConfig struct {
- blkioDevice []string // blkio-weight-device
blkioWeight uint16 // blkio-weight
+ blkioWeightDevice []string // blkio-weight-device
cpuPeriod uint64 // cpu-period
cpuQuota int64 // cpu-quota
cpuRtPeriod uint64 // cpu-rt-period
@@ -46,15 +46,15 @@ type createResourceConfig struct {
cpusetCpus string
cpusetMems string // cpuset-mems
deviceReadBps []string // device-read-bps
- deviceReadIops []string // device-read-iops
+ deviceReadIOps []string // device-read-iops
deviceWriteBps []string // device-write-bps
- deviceWriteIops []string // device-write-iops
+ deviceWriteIOps []string // device-write-iops
disableOomKiller bool // oom-kill-disable
kernelMemory int64 // kernel-memory
memory int64 //memory
memoryReservation int64 // memory-reservation
memorySwap int64 //memory-swap
- memorySwapiness uint64 // memory-swappiness
+ memorySwappiness int // memory-swappiness
oomScoreAdj int //oom-score-adj
pidsLimit int64 // pids-limit
shmSize string
@@ -373,7 +373,7 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
readOnlyRootfs: c.Bool("read-only"),
resources: createResourceConfig{
blkioWeight: blkioWeight,
- blkioDevice: c.StringSlice("blkio-weight-device"),
+ blkioWeightDevice: c.StringSlice("blkio-weight-device"),
cpuShares: c.Uint64("cpu-shares"),
cpuPeriod: c.Uint64("cpu-period"),
cpusetCpus: c.String("cpu-period"),
@@ -383,15 +383,15 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
cpuRtRuntime: c.Int64("cpu-rt-runtime"),
cpus: c.String("cpus"),
deviceReadBps: c.StringSlice("device-read-bps"),
- deviceReadIops: c.StringSlice("device-read-iops"),
+ deviceReadIOps: c.StringSlice("device-read-iops"),
deviceWriteBps: c.StringSlice("device-write-bps"),
- deviceWriteIops: c.StringSlice("device-write-iops"),
+ deviceWriteIOps: c.StringSlice("device-write-iops"),
disableOomKiller: c.Bool("oom-kill-disable"),
shmSize: c.String("shm-size"),
memory: memoryLimit,
memoryReservation: memoryReservation,
memorySwap: memorySwap,
- memorySwapiness: c.Uint64("memory-swapiness"),
+ memorySwappiness: c.Int("memory-swappiness"),
kernelMemory: memoryKernel,
oomScoreAdj: c.Int("oom-score-adj"),
@@ -418,6 +418,12 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
return nil, err
}
}
-
+ warnings, err := verifyContainerResources(config, false)
+ if err != nil {
+ return nil, err
+ }
+ for _, warning := range warnings {
+ fmt.Fprintln(os.Stderr, warning)
+ }
return config, nil
}
diff --git a/cmd/kpod/create_cli.go b/cmd/kpod/create_cli.go
index 91e984785..f90d530bf 100644
--- a/cmd/kpod/create_cli.go
+++ b/cmd/kpod/create_cli.go
@@ -1,9 +1,17 @@
package main
import (
+ "fmt"
"strings"
+ "github.com/docker/docker/pkg/sysinfo"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ // It's not kernel limit, we want this 4M limit to supply a reasonable functional container
+ linuxMinMemory = 4194304
)
func getAllLabels(labelFile, inputLabels []string) (map[string]string, error) {
@@ -26,3 +34,143 @@ func convertStringSliceToMap(strSlice []string, delimiter string) (map[string]st
}
return sysctl, nil
}
+
+func addWarning(warnings []string, msg string) []string {
+ logrus.Warn(msg)
+ return append(warnings, msg)
+}
+
+func verifyContainerResources(config *createConfig, update bool) ([]string, error) {
+ warnings := []string{}
+ sysInfo := sysinfo.New(true)
+
+ // memory subsystem checks and adjustments
+ if config.resources.memory != 0 && config.resources.memory < linuxMinMemory {
+ return warnings, fmt.Errorf("minimum memory limit allowed is 4MB")
+ }
+ if config.resources.memory > 0 && !sysInfo.MemoryLimit {
+ warnings = addWarning(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
+ config.resources.memory = 0
+ config.resources.memorySwap = -1
+ }
+ if config.resources.memory > 0 && config.resources.memorySwap != -1 && !sysInfo.SwapLimit {
+ warnings = addWarning(warnings, "Your kernel does not support swap limit capabilities,or the cgroup is not mounted. Memory limited without swap.")
+ config.resources.memorySwap = -1
+ }
+ if config.resources.memory > 0 && config.resources.memorySwap > 0 && config.resources.memorySwap < config.resources.memory {
+ return warnings, fmt.Errorf("minimum memoryswap limit should be larger than memory limit, see usage")
+ }
+ if config.resources.memory == 0 && config.resources.memorySwap > 0 && !update {
+ return warnings, fmt.Errorf("you should always set the Memory limit when using Memoryswap limit, see usage")
+ }
+ if config.resources.memorySwappiness != -1 {
+ if !sysInfo.MemorySwappiness {
+ msg := "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded."
+ warnings = addWarning(warnings, msg)
+ config.resources.memorySwappiness = -1
+ } else {
+ swappiness := config.resources.memorySwappiness
+ if swappiness < -1 || swappiness > 100 {
+ return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", swappiness)
+ }
+ }
+ }
+ if config.resources.memoryReservation > 0 && !sysInfo.MemoryReservation {
+ warnings = addWarning(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.")
+ config.resources.memoryReservation = 0
+ }
+ if config.resources.memoryReservation > 0 && config.resources.memoryReservation < linuxMinMemory {
+ return warnings, fmt.Errorf("minimum memory reservation allowed is 4MB")
+ }
+ if config.resources.memory > 0 && config.resources.memoryReservation > 0 && config.resources.memory < config.resources.memoryReservation {
+ return warnings, fmt.Errorf("minimum memory limit can not be less than memory reservation limit, see usage")
+ }
+ if config.resources.kernelMemory > 0 && !sysInfo.KernelMemory {
+ warnings = addWarning(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
+ config.resources.kernelMemory = 0
+ }
+ if config.resources.kernelMemory > 0 && config.resources.kernelMemory < linuxMinMemory {
+ return warnings, fmt.Errorf("minimum kernel memory limit allowed is 4MB")
+ }
+ if config.resources.disableOomKiller == true && !sysInfo.OomKillDisable {
+ // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point
+ // warning the caller if they already wanted the feature to be off
+ warnings = addWarning(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.")
+ config.resources.disableOomKiller = false
+ }
+
+ if config.resources.pidsLimit != 0 && !sysInfo.PidsLimit {
+ warnings = addWarning(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
+ config.resources.pidsLimit = 0
+ }
+
+ if config.resources.cpuShares > 0 && !sysInfo.CPUShares {
+ warnings = addWarning(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
+ config.resources.cpuShares = 0
+ }
+ if config.resources.cpuPeriod > 0 && !sysInfo.CPUCfsPeriod {
+ warnings = addWarning(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
+ config.resources.cpuPeriod = 0
+ }
+ if config.resources.cpuPeriod != 0 && (config.resources.cpuPeriod < 1000 || config.resources.cpuPeriod > 1000000) {
+ return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
+ }
+ if config.resources.cpuQuota > 0 && !sysInfo.CPUCfsQuota {
+ warnings = addWarning(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
+ config.resources.cpuQuota = 0
+ }
+ if config.resources.cpuQuota > 0 && config.resources.cpuQuota < 1000 {
+ return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
+ }
+ // cpuset subsystem checks and adjustments
+ if (config.resources.cpusetCpus != "" || config.resources.cpusetMems != "") && !sysInfo.Cpuset {
+ warnings = addWarning(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. Cpuset discarded.")
+ config.resources.cpusetCpus = ""
+ config.resources.cpusetMems = ""
+ }
+ cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(config.resources.cpusetCpus)
+ if err != nil {
+ return warnings, fmt.Errorf("invalid value %s for cpuset cpus", config.resources.cpusetCpus)
+ }
+ if !cpusAvailable {
+ return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", config.resources.cpusetCpus, sysInfo.Cpus)
+ }
+ memsAvailable, err := sysInfo.IsCpusetMemsAvailable(config.resources.cpusetMems)
+ if err != nil {
+ return warnings, fmt.Errorf("invalid value %s for cpuset mems", config.resources.cpusetMems)
+ }
+ if !memsAvailable {
+ return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", config.resources.cpusetMems, sysInfo.Mems)
+ }
+
+ // blkio subsystem checks and adjustments
+ if config.resources.blkioWeight > 0 && !sysInfo.BlkioWeight {
+ warnings = addWarning(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.")
+ config.resources.blkioWeight = 0
+ }
+ if config.resources.blkioWeight > 0 && (config.resources.blkioWeight < 10 || config.resources.blkioWeight > 1000) {
+ return warnings, fmt.Errorf("range of blkio weight is from 10 to 1000")
+ }
+ if len(config.resources.blkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
+ warnings = addWarning(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.")
+ config.resources.blkioWeightDevice = []string{}
+ }
+ if len(config.resources.deviceReadBps) > 0 && !sysInfo.BlkioReadBpsDevice {
+ warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded")
+ config.resources.deviceReadBps = []string{}
+ }
+ if len(config.resources.deviceWriteBps) > 0 && !sysInfo.BlkioWriteBpsDevice {
+ warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.")
+ config.resources.deviceWriteBps = []string{}
+ }
+ if len(config.resources.deviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice {
+ warnings = addWarning(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.")
+ config.resources.deviceReadIOps = []string{}
+ }
+ if len(config.resources.deviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice {
+ warnings = addWarning(warnings, "Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.")
+ config.resources.deviceWriteIOps = []string{}
+ }
+
+ return warnings, nil
+}
diff --git a/cmd/kpod/spec.go b/cmd/kpod/spec.go
index 752827669..0a99d792b 100644
--- a/cmd/kpod/spec.go
+++ b/cmd/kpod/spec.go
@@ -142,8 +142,8 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
if config.resources.kernelMemory != 0 {
g.SetLinuxResourcesMemoryKernel(config.resources.kernelMemory)
}
- if config.resources.memorySwapiness != 0 {
- g.SetLinuxResourcesMemorySwappiness(config.resources.memorySwapiness)
+ if config.resources.memorySwappiness != -1 {
+ g.SetLinuxResourcesMemorySwappiness(uint64(config.resources.memorySwappiness))
}
g.SetLinuxResourcesMemoryDisableOOMKiller(config.resources.disableOomKiller)
g.SetProcessOOMScoreAdj(config.resources.oomScoreAdj)
@@ -263,9 +263,9 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) {
bio := spec.LinuxBlockIO{}
bio.Weight = &c.resources.blkioWeight
- if len(c.resources.blkioDevice) > 0 {
+ if len(c.resources.blkioWeightDevice) > 0 {
var lwds []spec.LinuxWeightDevice
- for _, i := range c.resources.blkioDevice {
+ for _, i := range c.resources.blkioWeightDevice {
wd, err := validateweightDevice(i)
if err != nil {
return bio, errors.Wrapf(err, "invalid values for blkio-weight-device")
@@ -293,19 +293,19 @@ func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) {
}
bio.ThrottleWriteBpsDevice = writeBpds
}
- if len(c.resources.deviceReadIops) > 0 {
- readIops, err := makeThrottleArray(c.resources.deviceReadIops)
+ if len(c.resources.deviceReadIOps) > 0 {
+ readIOps, err := makeThrottleArray(c.resources.deviceReadIOps)
if err != nil {
return bio, err
}
- bio.ThrottleReadIOPSDevice = readIops
+ bio.ThrottleReadIOPSDevice = readIOps
}
- if len(c.resources.deviceWriteIops) > 0 {
- writeIops, err := makeThrottleArray(c.resources.deviceWriteIops)
+ if len(c.resources.deviceWriteIOps) > 0 {
+ writeIOps, err := makeThrottleArray(c.resources.deviceWriteIOps)
if err != nil {
return bio, err
}
- bio.ThrottleWriteIOPSDevice = writeIops
+ bio.ThrottleWriteIOPSDevice = writeIOps
}
return bio, nil