From e894ad0fa1c84d1a01afc47ccc52c3556121bbcd Mon Sep 17 00:00:00 2001 From: zhangyu235 Date: Tue, 8 Jan 2019 20:17:21 +0800 Subject: [PATCH 056/111] docker: check cpuset.cpu and cpuset.mem reason:check cpuset.cpu and cpuset.mem cherry-pick from docker 1.11.2: - 1c769f0 check cpuset.cpu and cpuset.mem Signed-off-by: lujingxiao ----- - 782f78f check cpuset.cpu and cpuset.mem Signed-off-by: wangyi45 Change-Id: If21cad2023d737d03ba3d4a83e62d11fb2297945 Signed-off-by: zhangyu235 --- components/engine/daemon/daemon_unix.go | 2 + components/engine/pkg/sysinfo/sysinfo.go | 64 +++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index e48dfcd1ef..b20c66e27b 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -499,6 +499,7 @@ func (daemon *Daemon) verifyContainerResources(hostConfig *containertypes.HostCo } cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus) if err != nil { + logrus.Errorf("Checking cpuset.cpus got %#v", err.Error()) return warnings, errors.Wrapf(err, "Invalid value %s for cpuset cpus", resources.CpusetCpus) } if !cpusAvailable { @@ -506,6 +507,7 @@ func (daemon *Daemon) verifyContainerResources(hostConfig *containertypes.HostCo } memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems) if err != nil { + logrus.Errorf("Checking cpuset.mems got %#v", err.Error()) return warnings, errors.Wrapf(err, "Invalid value %s for cpuset mems", resources.CpusetMems) } if !memsAvailable { diff --git a/components/engine/pkg/sysinfo/sysinfo.go b/components/engine/pkg/sysinfo/sysinfo.go index 5d9320218c..7ea1be5daf 100644 --- a/components/engine/pkg/sysinfo/sysinfo.go +++ b/components/engine/pkg/sysinfo/sysinfo.go @@ -1,6 +1,12 @@ package sysinfo // import "github.com/docker/docker/pkg/sysinfo" -import "github.com/docker/docker/pkg/parsers" +import ( + "fmt" + "strconv" + "strings" + + "github.com/docker/docker/pkg/parsers" +) // SysInfo stores information about which features a kernel supports. // TODO Windows: Factor out platform specific capabilities. @@ -123,6 +129,13 @@ func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) { } func isCpusetListAvailable(provided, available string) (bool, error) { + if err := checkCPU(provided, available); err != nil { + if strings.Contains(err.Error(), "invalid format") { + return false, err + } + return false, nil + } + parsedAvailable, err := parsers.ParseUintList(available) if err != nil { return false, err @@ -147,6 +160,55 @@ func isCpusetListAvailable(provided, available string) (bool, error) { return true, nil } +func checkCPU(provided, available string) error { + if provided == "" { + return nil + } + + maxAvailable, err := maxCPU(available) + if err != nil { + return err + } + + maxRequest, err := maxCPU(provided) + if err != nil { + return err + } + + if maxRequest > maxAvailable { + return fmt.Errorf("invalid maxRequest is %d, max available: %d", maxRequest, maxAvailable) + } + + return nil +} + +func maxCPU(cores string) (int, error) { + var max int + split := strings.Split(cores, ",") + errInvalidFormat := fmt.Errorf("invalid format: %s", cores) + for _, r := range split { + if !strings.Contains(r, "-") { + v, err := strconv.Atoi(r) + if err != nil { + return max, errInvalidFormat + } + if v > max { + max = v + } + } else { + split := strings.SplitN(r, "-", 2) + end, err := strconv.Atoi(split[1]) + if err != nil { + return max, errInvalidFormat + } + if end > max { + max = end + } + } + } + return max, nil +} + // Returns bit count of 1, used by NumCPU func popcnt(x uint64) (n byte) { x -= (x >> 1) & 0x5555555555555555 -- 2.17.1