diff --git a/api/server/container.go b/api/server/container.go index 779ed78c29..48128ed6aa 100644 --- a/api/server/container.go +++ b/api/server/container.go @@ -397,9 +397,9 @@ func (s *Server) postContainersCreate(version version.Version, w http.ResponseWr if err != nil { return err } - adjustCPUShares(version, hostConfig) + adjustCPUShares := version.LessThan("1.19") - containerID, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig) + containerID, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig, adjustCPUShares) if err != nil { return err } diff --git a/api/server/server_unix.go b/api/server/server_unix.go index 84df45bcd1..eb20ea3736 100644 --- a/api/server/server_unix.go +++ b/api/server/server_unix.go @@ -8,21 +8,12 @@ import ( "net/http" "strconv" - "github.com/Sirupsen/logrus" "github.com/docker/docker/daemon" "github.com/docker/docker/pkg/sockets" "github.com/docker/docker/pkg/systemd" - "github.com/docker/docker/pkg/version" - "github.com/docker/docker/runconfig" "github.com/docker/libnetwork/portallocator" ) -const ( - // See http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269 - linuxMinCPUShares = 2 - linuxMaxCPUShares = 262144 -) - // newServer sets up the required serverClosers and does protocol specific checking. func (s *Server) newServer(proto, addr string) ([]serverCloser, error) { var ( @@ -110,21 +101,6 @@ func allocateDaemonPort(addr string) error { return nil } -func adjustCPUShares(version version.Version, hostConfig *runconfig.HostConfig) { - if version.LessThan("1.19") { - if hostConfig != nil && hostConfig.CPUShares > 0 { - // Handle unsupported CpuShares - if hostConfig.CPUShares < linuxMinCPUShares { - logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares) - hostConfig.CPUShares = linuxMinCPUShares - } else if hostConfig.CPUShares > linuxMaxCPUShares { - logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares) - hostConfig.CPUShares = linuxMaxCPUShares - } - } - } -} - // getContainersByNameDownlevel performs processing for pre 1.20 APIs. This // is only relevant on non-Windows daemons. func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error { diff --git a/api/server/server_windows.go b/api/server/server_windows.go index 7c80cf0e1e..51c062527e 100644 --- a/api/server/server_windows.go +++ b/api/server/server_windows.go @@ -8,8 +8,6 @@ import ( "net/http" "github.com/docker/docker/daemon" - "github.com/docker/docker/pkg/version" - "github.com/docker/docker/runconfig" ) // NewServer sets up the required Server and does protocol specific checking. @@ -59,9 +57,6 @@ func allocateDaemonPort(addr string) error { return nil } -func adjustCPUShares(version version.Version, hostConfig *runconfig.HostConfig) { -} - // getContainersByNameDownlevel performs processing for pre 1.20 APIs. This // is only relevant on non-Windows daemons. func getContainersByNameDownlevel(w http.ResponseWriter, s *Server, namevar string) error { diff --git a/daemon/create.go b/daemon/create.go index e06fc1046a..7a2a603dee 100644 --- a/daemon/create.go +++ b/daemon/create.go @@ -11,12 +11,12 @@ import ( "github.com/opencontainers/runc/libcontainer/label" ) -func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) { +func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig, adjustCPUShares bool) (string, []string, error) { if config == nil { return "", nil, fmt.Errorf("Config cannot be empty in order to create a container") } - daemon.adaptContainerSettings(hostConfig) + daemon.adaptContainerSettings(hostConfig, adjustCPUShares) warnings, err := daemon.verifyContainerSettings(hostConfig, config) if err != nil { return "", warnings, err diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 561543d3fe..a4a3a50959 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -31,6 +31,12 @@ import ( "github.com/opencontainers/runc/libcontainer/label" ) +const ( + // See https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/kernel/sched/sched.h?id=8cd9234c64c584432f6992fe944ca9e46ca8ea76#n269 + linuxMinCPUShares = 2 + linuxMaxCPUShares = 262144 +) + func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) { initID := fmt.Sprintf("%s-init", container.ID) return daemon.driver.Changes(container.ID, initID) @@ -118,10 +124,21 @@ func checkKernel() error { // adaptContainerSettings is called during container creation to modify any // settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig) { +func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) { if hostConfig == nil { return } + + if adjustCPUShares && hostConfig.CPUShares > 0 { + // Handle unsupported CPUShares + if hostConfig.CPUShares < linuxMinCPUShares { + logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCPUShares) + hostConfig.CPUShares = linuxMinCPUShares + } else if hostConfig.CPUShares > linuxMaxCPUShares { + logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCPUShares) + hostConfig.CPUShares = linuxMaxCPUShares + } + } if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 { // By default, MemorySwap is set to twice the size of Memory. hostConfig.MemorySwap = hostConfig.Memory * 2 diff --git a/api/server/server_linux_test.go b/daemon/daemon_unix_test.go similarity index 59% rename from api/server/server_linux_test.go rename to daemon/daemon_unix_test.go index 83244b1cc9..fc13e667c5 100644 --- a/api/server/server_linux_test.go +++ b/daemon/daemon_unix_test.go @@ -1,67 +1,86 @@ -// +build linux +// +build !windows -package server +package daemon import ( + "io/ioutil" + "os" "testing" - "github.com/docker/docker/pkg/version" "github.com/docker/docker/runconfig" ) -func TestAdjustCPUSharesOldApi(t *testing.T) { - apiVersion := version.Version("1.18") +func TestAdjustCPUShares(t *testing.T) { + tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + daemon := &Daemon{ + repository: tmp, + root: tmp, + } + hostConfig := &runconfig.HostConfig{ CPUShares: linuxMinCPUShares - 1, } - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, true) if hostConfig.CPUShares != linuxMinCPUShares { t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares) } hostConfig.CPUShares = linuxMaxCPUShares + 1 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, true) if hostConfig.CPUShares != linuxMaxCPUShares { t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares) } hostConfig.CPUShares = 0 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, true) if hostConfig.CPUShares != 0 { t.Error("Expected CPUShares to be unchanged") } hostConfig.CPUShares = 1024 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, true) if hostConfig.CPUShares != 1024 { t.Error("Expected CPUShares to be unchanged") } } func TestAdjustCPUSharesNoAdjustment(t *testing.T) { - apiVersion := version.Version("1.19") + tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + daemon := &Daemon{ + repository: tmp, + root: tmp, + } + hostConfig := &runconfig.HostConfig{ CPUShares: linuxMinCPUShares - 1, } - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, false) if hostConfig.CPUShares != linuxMinCPUShares-1 { t.Errorf("Expected CPUShares to be %d", linuxMinCPUShares-1) } hostConfig.CPUShares = linuxMaxCPUShares + 1 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, false) if hostConfig.CPUShares != linuxMaxCPUShares+1 { t.Errorf("Expected CPUShares to be %d", linuxMaxCPUShares+1) } hostConfig.CPUShares = 0 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, false) if hostConfig.CPUShares != 0 { t.Error("Expected CPUShares to be unchanged") } hostConfig.CPUShares = 1024 - adjustCPUShares(apiVersion, hostConfig) + daemon.adaptContainerSettings(hostConfig, false) if hostConfig.CPUShares != 1024 { t.Error("Expected CPUShares to be unchanged") } diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 8b79dd540f..3e006ce790 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -75,7 +75,7 @@ func checkKernel() error { // adaptContainerSettings is called during container creation to modify any // settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig) { +func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) { } // verifyPlatformContainerSettings performs platform-specific validation of the