예제 #1
0
파일: driver.go 프로젝트: Nerdness/docker
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
}
예제 #2
0
파일: driver.go 프로젝트: Nerdness/docker
// 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
}
예제 #3
0
파일: api.go 프로젝트: Nerdness/docker
// 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
}
예제 #4
0
파일: driver.go 프로젝트: Nerdness/docker
// 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
}
예제 #5
0
파일: driver.go 프로젝트: Nerdness/docker
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
}