diff --git a/api/server/server.go b/api/server/server.go index d7ec2d47d7..0b7fa916d2 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -894,6 +894,7 @@ func (s *Server) postContainersCreate(version version.Version, w http.ResponseWr if err != nil { return err } + adjustCpuShares(version, hostConfig) containerId, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig) if err != nil { diff --git a/api/server/server_linux.go b/api/server/server_linux.go index f1a3c88250..93dd42990a 100644 --- a/api/server/server_linux.go +++ b/api/server/server_linux.go @@ -8,12 +8,21 @@ 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 ( @@ -96,3 +105,18 @@ func allocateDaemonPort(addr string) error { } return nil } + +func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) { + if version.LessThan("1.19") { + if 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 + } + } + } +} diff --git a/api/server/server_linux_test.go b/api/server/server_linux_test.go new file mode 100644 index 0000000000..47289653eb --- /dev/null +++ b/api/server/server_linux_test.go @@ -0,0 +1,68 @@ +// +build linux + +package server + +import ( + "testing" + + "github.com/docker/docker/pkg/version" + "github.com/docker/docker/runconfig" +) + +func TestAdjustCpuSharesOldApi(t *testing.T) { + apiVersion := version.Version("1.18") + hostConfig := &runconfig.HostConfig{ + CpuShares: linuxMinCpuShares - 1, + } + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != linuxMinCpuShares { + t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares) + } + + hostConfig.CpuShares = linuxMaxCpuShares + 1 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != linuxMaxCpuShares { + t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares) + } + + hostConfig.CpuShares = 0 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != 0 { + t.Error("Expected CpuShares to be unchanged") + } + + hostConfig.CpuShares = 1024 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != 1024 { + t.Error("Expected CpuShares to be unchanged") + } +} + +func TestAdjustCpuSharesNoAdjustment(t *testing.T) { + apiVersion := version.Version("1.19") + hostConfig := &runconfig.HostConfig{ + CpuShares: linuxMinCpuShares - 1, + } + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != linuxMinCpuShares-1 { + t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares-1) + } + + hostConfig.CpuShares = linuxMaxCpuShares + 1 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != linuxMaxCpuShares+1 { + t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares+1) + } + + hostConfig.CpuShares = 0 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != 0 { + t.Error("Expected CpuShares to be unchanged") + } + + hostConfig.CpuShares = 1024 + adjustCpuShares(apiVersion, hostConfig) + if hostConfig.CpuShares != 1024 { + t.Error("Expected CpuShares to be unchanged") + } +} diff --git a/api/server/server_windows.go b/api/server/server_windows.go index 010582f634..2e33af8d25 100644 --- a/api/server/server_windows.go +++ b/api/server/server_windows.go @@ -54,3 +54,6 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) { func allocateDaemonPort(addr string) error { return nil } + +func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) { +}