func jobVersion(job *engine.Job) engine.Status { if _, err := dockerVersion().WriteTo(job.Stdout); err != nil { job.Errorf("%s", err) return engine.StatusErr } return engine.StatusOK }
// Allocate a network interface func Allocate(job *engine.Job) engine.Status { var ( ip *net.IP err error id = job.Args[0] requestedIP = net.ParseIP(job.Getenv("RequestedIP")) ) if requestedIP != nil { ip, err = ipallocator.RequestIP(bridgeNetwork, &requestedIP) } else { ip, err = ipallocator.RequestIP(bridgeNetwork, nil) } if err != nil { job.Error(err) return engine.StatusErr } out := engine.Env{} out.Set("IP", ip.String()) out.Set("Mask", bridgeNetwork.Mask.String()) out.Set("Gateway", bridgeNetwork.IP.String()) out.Set("Bridge", bridgeIface) size, _ := bridgeNetwork.Mask.Size() out.SetInt("IPPrefixLen", size) currentInterfaces[id] = &networkInterface{ IP: *ip, } out.WriteTo(job.Stdout) return engine.StatusOK }
// ServeApi loops through all of the protocols sent in to docker and spawns // off a go routine to setup a serving http.Server for each. func ServeApi(job *engine.Job) engine.Status { protoAddrs := job.Args chErrors := make(chan error, len(protoAddrs)) for _, protoAddr := range protoAddrs { protoAddrParts := strings.SplitN(protoAddr, "://", 2) go func() { log.Printf("Listening for HTTP on %s (%s)\n", protoAddrParts[0], protoAddrParts[1]) chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version")) }() } for i := 0; i < len(protoAddrs); i += 1 { err := <-chErrors if err != nil { return job.Error(err) } } // Tell the init daemon we are accepting requests go systemd.SdNotify("READY=1") return engine.StatusOK }
func InitDriver(job *engine.Job) engine.Status { var ( network *net.IPNet enableIPTables = job.GetenvBool("EnableIptables") icc = job.GetenvBool("InterContainerCommunication") ipForward = job.GetenvBool("EnableIpForward") bridgeIP = job.Getenv("BridgeIP") ) if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" { defaultBindingIP = net.ParseIP(defaultIP) } bridgeIface = job.Getenv("BridgeIface") if bridgeIface == "" { bridgeIface = DefaultNetworkBridge } addr, err := networkdriver.GetIfaceAddr(bridgeIface) if err != nil { // If the iface is not found, try to create it job.Logf("creating new bridge for %s", bridgeIface) if err := createBridge(bridgeIP); err != nil { job.Error(err) return engine.StatusErr } job.Logf("getting iface addr") addr, err = networkdriver.GetIfaceAddr(bridgeIface) if err != nil { job.Error(err) return engine.StatusErr } network = addr.(*net.IPNet) } else { network = addr.(*net.IPNet) } // Configure iptables for link support if enableIPTables { if err := setupIPTables(addr, icc); err != nil { job.Error(err) return engine.StatusErr } } if ipForward { // Enable IPv4 forwarding if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil { job.Logf("WARNING: unable to enable IPv4 forwarding: %s\n", err) } } // We can always try removing the iptables if err := iptables.RemoveExistingChain("DOCKER"); err != nil { job.Error(err) return engine.StatusErr } if enableIPTables { chain, err := iptables.NewChain("DOCKER", bridgeIface) if err != nil { job.Error(err) return engine.StatusErr } portmapper.SetIptablesChain(chain) } bridgeNetwork = network // https://github.com/Nerdness/docker/issues/2768 job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeNetwork.IP) for name, f := range map[string]engine.Handler{ "allocate_interface": Allocate, "release_interface": Release, "allocate_port": AllocatePort, "link": LinkContainers, } { if err := job.Eng.Register(name, f); err != nil { job.Error(err) return engine.StatusErr } } return engine.StatusOK }
func LinkContainers(job *engine.Job) engine.Status { var ( action = job.Args[0] childIP = job.Getenv("ChildIP") parentIP = job.Getenv("ParentIP") ignoreErrors = job.GetenvBool("IgnoreErrors") ports = job.GetenvList("Ports") ) split := func(p string) (string, string) { parts := strings.Split(p, "/") return parts[0], parts[1] } for _, p := range ports { port, proto := split(p) if output, err := iptables.Raw(action, "FORWARD", "-i", bridgeIface, "-o", bridgeIface, "-p", proto, "-s", parentIP, "--dport", port, "-d", childIP, "-j", "ACCEPT"); !ignoreErrors && err != nil { job.Error(err) return engine.StatusErr } else if len(output) != 0 { job.Errorf("Error toggle iptables forward: %s", output) return engine.StatusErr } } return engine.StatusOK }
// Allocate an external port and map it to the interface func AllocatePort(job *engine.Job) engine.Status { var ( err error ip = defaultBindingIP id = job.Args[0] hostIP = job.Getenv("HostIP") hostPort = job.GetenvInt("HostPort") containerPort = job.GetenvInt("ContainerPort") proto = job.Getenv("Proto") network = currentInterfaces[id] ) if hostIP != "" { ip = net.ParseIP(hostIP) } // host ip, proto, and host port hostPort, err = portallocator.RequestPort(ip, proto, hostPort) if err != nil { job.Error(err) return engine.StatusErr } var ( container net.Addr host net.Addr ) if proto == "tcp" { host = &net.TCPAddr{IP: ip, Port: hostPort} container = &net.TCPAddr{IP: network.IP, Port: containerPort} } else { host = &net.UDPAddr{IP: ip, Port: hostPort} container = &net.UDPAddr{IP: network.IP, Port: containerPort} } if err := portmapper.Map(container, ip, hostPort); err != nil { portallocator.ReleasePort(ip, proto, hostPort) job.Error(err) return engine.StatusErr } network.PortMappings = append(network.PortMappings, host) out := engine.Env{} out.Set("HostIP", ip.String()) out.SetInt("HostPort", hostPort) if _, err := out.WriteTo(job.Stdout); err != nil { job.Error(err) return engine.StatusErr } return engine.StatusOK }
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig { hostConfig := &HostConfig{ ContainerIDFile: job.Getenv("ContainerIDFile"), Privileged: job.GetenvBool("Privileged"), PublishAllPorts: job.GetenvBool("PublishAllPorts"), } job.GetenvJson("LxcConf", &hostConfig.LxcConf) job.GetenvJson("PortBindings", &hostConfig.PortBindings) if Binds := job.GetenvList("Binds"); Binds != nil { hostConfig.Binds = Binds } if Links := job.GetenvList("Links"); Links != nil { hostConfig.Links = Links } return hostConfig }
func ContainerConfigFromJob(job *engine.Job) *Config { config := &Config{ Hostname: job.Getenv("Hostname"), Domainname: job.Getenv("Domainname"), User: job.Getenv("User"), Memory: job.GetenvInt64("Memory"), MemorySwap: job.GetenvInt64("MemorySwap"), CpuShares: job.GetenvInt64("CpuShares"), AttachStdin: job.GetenvBool("AttachStdin"), AttachStdout: job.GetenvBool("AttachStdout"), AttachStderr: job.GetenvBool("AttachStderr"), Tty: job.GetenvBool("Tty"), OpenStdin: job.GetenvBool("OpenStdin"), StdinOnce: job.GetenvBool("StdinOnce"), Image: job.Getenv("Image"), VolumesFrom: job.Getenv("VolumesFrom"), WorkingDir: job.Getenv("WorkingDir"), NetworkDisabled: job.GetenvBool("NetworkDisabled"), } job.GetenvJson("ExposedPorts", &config.ExposedPorts) job.GetenvJson("Volumes", &config.Volumes) if PortSpecs := job.GetenvList("PortSpecs"); PortSpecs != nil { config.PortSpecs = PortSpecs } if Env := job.GetenvList("Env"); Env != nil { config.Env = Env } if Cmd := job.GetenvList("Cmd"); Cmd != nil { config.Cmd = Cmd } if Dns := job.GetenvList("Dns"); Dns != nil { config.Dns = Dns } if Entrypoint := job.GetenvList("Entrypoint"); Entrypoint != nil { config.Entrypoint = Entrypoint } return config }
// Creates an image from Pull or from Import func postImagesCreate(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } var ( image = r.Form.Get("fromImage") tag = r.Form.Get("tag") job *engine.Job ) authEncoded := r.Header.Get("X-Registry-Auth") authConfig := &auth.AuthConfig{} if authEncoded != "" { authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded)) if err := json.NewDecoder(authJson).Decode(authConfig); err != nil { // for a pull it is not an error if no auth was given // to increase compatibility with the existing api it is defaulting to be empty authConfig = &auth.AuthConfig{} } } if version > 1.0 { w.Header().Set("Content-Type", "application/json") } if image != "" { //pull metaHeaders := map[string][]string{} for k, v := range r.Header { if strings.HasPrefix(k, "X-Meta-") { metaHeaders[k] = v } } job = eng.Job("pull", r.Form.Get("fromImage"), tag) job.SetenvBool("parallel", version > 1.3) job.SetenvJson("metaHeaders", metaHeaders) job.SetenvJson("authConfig", authConfig) } else { //import job = eng.Job("import", r.Form.Get("fromSrc"), r.Form.Get("repo"), tag) job.Stdin.Add(r.Body) } job.SetenvBool("json", version > 1.0) job.Stdout.Add(utils.NewWriteFlusher(w)) if err := job.Run(); err != nil { if !job.Stdout.Used() { return err } sf := utils.NewStreamFormatter(version > 1.0) w.Write(sf.FormatError(err)) } return nil }
// ConfigFromJob creates and returns a new DaemonConfig object // by parsing the contents of a job's environment. func DaemonConfigFromJob(job *engine.Job) *DaemonConfig { config := &DaemonConfig{ Pidfile: job.Getenv("Pidfile"), Root: job.Getenv("Root"), AutoRestart: job.GetenvBool("AutoRestart"), EnableIptables: job.GetenvBool("EnableIptables"), EnableIpForward: job.GetenvBool("EnableIpForward"), BridgeIP: job.Getenv("BridgeIP"), DefaultIp: net.ParseIP(job.Getenv("DefaultIp")), InterContainerCommunication: job.GetenvBool("InterContainerCommunication"), GraphDriver: job.Getenv("GraphDriver"), } if dns := job.GetenvList("Dns"); dns != nil { config.Dns = dns } if mtu := job.GetenvInt("Mtu"); mtu != 0 { config.Mtu = mtu } else { config.Mtu = DefaultNetworkMtu } config.DisableNetwork = job.Getenv("BridgeIface") == DisableNetworkBridge return config }