mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
ed39fbeb2a
Previous versions of libcontainer allowed CpuShares that were greater than the maximum or less than the minimum supported by the kernel, and relied on the kernel to do the right thing. Newer libcontainer fails after creating the container if the requested CpuShares is different from what was actually created by the kernel, which breaks compatibility with earlier Docker Remote API versions. This change explicitly adjusts the requested CpuShares in API versions < 1.20. Signed-off-by: Samuel Karp <skarp@amazon.com>
122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
// +build linux
|
|
|
|
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"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 (
|
|
err error
|
|
ls []net.Listener
|
|
)
|
|
switch proto {
|
|
case "fd":
|
|
ls, err = systemd.ListenFD(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// We don't want to start serving on these sockets until the
|
|
// daemon is initialized and installed. Otherwise required handlers
|
|
// won't be ready.
|
|
<-s.start
|
|
case "tcp":
|
|
l, err := s.initTcpSocket(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ls = append(ls, l)
|
|
case "unix":
|
|
l, err := sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ls = append(ls, l)
|
|
default:
|
|
return nil, fmt.Errorf("Invalid protocol format: %q", proto)
|
|
}
|
|
var res []serverCloser
|
|
for _, l := range ls {
|
|
res = append(res, &HttpServer{
|
|
&http.Server{
|
|
Addr: addr,
|
|
Handler: s.router,
|
|
},
|
|
l,
|
|
})
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func (s *Server) AcceptConnections(d *daemon.Daemon) {
|
|
// Tell the init daemon we are accepting requests
|
|
s.daemon = d
|
|
go systemd.SdNotify("READY=1")
|
|
// close the lock so the listeners start accepting connections
|
|
select {
|
|
case <-s.start:
|
|
default:
|
|
close(s.start)
|
|
}
|
|
}
|
|
|
|
func allocateDaemonPort(addr string) error {
|
|
host, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
intPort, err := strconv.Atoi(port)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var hostIPs []net.IP
|
|
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
|
hostIPs = append(hostIPs, parsedIP)
|
|
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
|
return fmt.Errorf("failed to lookup %s address in host specification", host)
|
|
}
|
|
|
|
pa := portallocator.Get()
|
|
for _, hostIP := range hostIPs {
|
|
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
|
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
|
}
|
|
}
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|