| // +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 |
| s.registerSubRouter() |
| 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 |
| } |
| } |
| } |
| } |