mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Remove jobs from daemon/networkdriver/bridge
Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
parent
7233bd223d
commit
53582321ee
11 changed files with 233 additions and 433 deletions
|
@ -1,10 +1,10 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/nat"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
)
|
||||
|
@ -23,12 +23,13 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
env := engine.Env{}
|
||||
if err := env.Decode(stream); err != nil {
|
||||
return err
|
||||
var c struct {
|
||||
NetworkSettings struct {
|
||||
Ports nat.PortMap
|
||||
}
|
||||
ports := nat.PortMap{}
|
||||
if err := env.GetSubEnv("NetworkSettings").GetJson("Ports", &ports); err != nil {
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(stream).Decode(&c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
|||
proto = parts[1]
|
||||
}
|
||||
natPort := port + "/" + proto
|
||||
if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
||||
if frontends, exists := c.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
||||
for _, frontend := range frontends {
|
||||
fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
|
||||
}
|
||||
|
@ -53,7 +54,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
|||
return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
|
||||
}
|
||||
|
||||
for from, frontends := range ports {
|
||||
for from, frontends := range c.NetworkSettings.Ports {
|
||||
for _, frontend := range frontends {
|
||||
fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
|
||||
}
|
||||
|
|
|
@ -6,15 +6,11 @@ import (
|
|||
"github.com/docker/docker/api"
|
||||
apiserver "github.com/docker/docker/api/server"
|
||||
"github.com/docker/docker/autogen/dockerversion"
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
)
|
||||
|
||||
func Register(eng *engine.Engine) error {
|
||||
if err := daemon(eng); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := remote(eng); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,25 +29,6 @@ func remote(eng *engine.Engine) error {
|
|||
return eng.Register("acceptconnections", apiserver.AcceptConnections)
|
||||
}
|
||||
|
||||
// daemon: a default execution and storage backend for Docker on Linux,
|
||||
// with the following underlying components:
|
||||
//
|
||||
// * Pluggable storage drivers including aufs, vfs, lvm and btrfs.
|
||||
// * Pluggable execution drivers including lxc and chroot.
|
||||
//
|
||||
// In practice `daemon` still includes most core Docker components, including:
|
||||
//
|
||||
// * The reference registry client implementation
|
||||
// * Image management
|
||||
// * The build facility
|
||||
// * Logging
|
||||
//
|
||||
// These components should be broken off into plugins of their own.
|
||||
//
|
||||
func daemon(eng *engine.Engine) error {
|
||||
return eng.Register("init_networkdriver", bridge.InitDriver)
|
||||
}
|
||||
|
||||
// builtins jobs independent of any subsystem
|
||||
func dockerVersion(job *engine.Job) error {
|
||||
v := &engine.Env{}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/daemon/networkdriver"
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/ulimit"
|
||||
|
@ -20,21 +19,13 @@ const (
|
|||
// to the docker daemon when you launch it with say: `docker -d -e lxc`
|
||||
// FIXME: separate runtime configuration from http api configuration
|
||||
type Config struct {
|
||||
Bridge bridge.Config
|
||||
|
||||
Pidfile string
|
||||
Root string
|
||||
AutoRestart bool
|
||||
Dns []string
|
||||
DnsSearch []string
|
||||
EnableIPv6 bool
|
||||
EnableIptables bool
|
||||
EnableIpForward bool
|
||||
EnableIpMasq bool
|
||||
DefaultIp net.IP
|
||||
BridgeIface string
|
||||
BridgeIP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
InterContainerCommunication bool
|
||||
GraphDriver string
|
||||
GraphOptions []string
|
||||
ExecDriver string
|
||||
|
@ -59,15 +50,15 @@ func (config *Config) InstallFlags() {
|
|||
flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
|
||||
flag.StringVar(&config.Root, []string{"g", "-graph"}, "/var/lib/docker", "Root of the Docker runtime")
|
||||
flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
|
||||
flag.BoolVar(&config.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.EnableIpMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
flag.BoolVar(&config.Bridge.EnableIptables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
|
||||
flag.BoolVar(&config.Bridge.EnableIpForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flag.BoolVar(&config.Bridge.EnableIpMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
||||
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
|
||||
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")
|
||||
flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
|
||||
|
@ -75,7 +66,7 @@ func (config *Config) InstallFlags() {
|
|||
flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
|
||||
flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
|
||||
flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
|
||||
opts.IPVar(&config.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
opts.IPVar(&config.Bridge.DefaultIp, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
|
||||
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||
// FIXME: why the inconsistency between "hosts" and "sockets"?
|
||||
opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||
"github.com/docker/docker/daemon/logger/syslog"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/links"
|
||||
|
@ -73,7 +75,7 @@ type Container struct {
|
|||
Config *runconfig.Config
|
||||
ImageID string `json:"Image"`
|
||||
|
||||
NetworkSettings *NetworkSettings
|
||||
NetworkSettings *network.Settings
|
||||
|
||||
ResolvConfPath string
|
||||
HostnamePath string
|
||||
|
@ -571,17 +573,12 @@ func (container *Container) AllocateNetwork() error {
|
|||
}
|
||||
|
||||
var (
|
||||
env *engine.Env
|
||||
err error
|
||||
eng = container.daemon.eng
|
||||
)
|
||||
|
||||
job := eng.Job("allocate_interface", container.ID)
|
||||
job.Setenv("RequestedMac", container.Config.MacAddress)
|
||||
if env, err = job.Stdout.AddEnv(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = job.Run(); err != nil {
|
||||
networkSettings, err := bridge.Allocate(container.ID, container.Config.MacAddress, "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -591,12 +588,12 @@ func (container *Container) AllocateNetwork() error {
|
|||
|
||||
if container.Config.PortSpecs != nil {
|
||||
if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
|
||||
eng.Job("release_interface", container.ID).Run()
|
||||
bridge.Release(container.ID)
|
||||
return err
|
||||
}
|
||||
container.Config.PortSpecs = nil
|
||||
if err = container.WriteHostConfig(); err != nil {
|
||||
eng.Job("release_interface", container.ID).Run()
|
||||
bridge.Release(container.ID)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -626,23 +623,14 @@ func (container *Container) AllocateNetwork() error {
|
|||
|
||||
for port := range portSpecs {
|
||||
if err = container.allocatePort(eng, port, bindings); err != nil {
|
||||
eng.Job("release_interface", container.ID).Run()
|
||||
bridge.Release(container.ID)
|
||||
return err
|
||||
}
|
||||
}
|
||||
container.WriteHostConfig()
|
||||
|
||||
container.NetworkSettings.Ports = bindings
|
||||
container.NetworkSettings.Bridge = env.Get("Bridge")
|
||||
container.NetworkSettings.IPAddress = env.Get("IP")
|
||||
container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
|
||||
container.NetworkSettings.MacAddress = env.Get("MacAddress")
|
||||
container.NetworkSettings.Gateway = env.Get("Gateway")
|
||||
container.NetworkSettings.LinkLocalIPv6Address = env.Get("LinkLocalIPv6")
|
||||
container.NetworkSettings.LinkLocalIPv6PrefixLen = 64
|
||||
container.NetworkSettings.GlobalIPv6Address = env.Get("GlobalIPv6")
|
||||
container.NetworkSettings.GlobalIPv6PrefixLen = env.GetInt("GlobalIPv6PrefixLen")
|
||||
container.NetworkSettings.IPv6Gateway = env.Get("IPv6Gateway")
|
||||
networkSettings.Ports = bindings
|
||||
container.NetworkSettings = networkSettings
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -651,12 +639,10 @@ func (container *Container) ReleaseNetwork() {
|
|||
if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
|
||||
return
|
||||
}
|
||||
eng := container.daemon.eng
|
||||
|
||||
job := eng.Job("release_interface", container.ID)
|
||||
job.SetenvBool("overrideShutdown", true)
|
||||
job.Run()
|
||||
container.NetworkSettings = &NetworkSettings{}
|
||||
bridge.Release(container.ID)
|
||||
|
||||
container.NetworkSettings = &network.Settings{}
|
||||
}
|
||||
|
||||
func (container *Container) isNetworkAllocated() bool {
|
||||
|
@ -675,10 +661,7 @@ func (container *Container) RestoreNetwork() error {
|
|||
eng := container.daemon.eng
|
||||
|
||||
// Re-allocate the interface with the same IP and MAC address.
|
||||
job := eng.Job("allocate_interface", container.ID)
|
||||
job.Setenv("RequestedIP", container.NetworkSettings.IPAddress)
|
||||
job.Setenv("RequestedMac", container.NetworkSettings.MacAddress)
|
||||
if err := job.Run(); err != nil {
|
||||
if _, err := bridge.Allocate(container.ID, container.NetworkSettings.MacAddress, container.NetworkSettings.IPAddress, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1060,7 @@ func (container *Container) setupContainerDns() error {
|
|||
latestResolvConf, latestHash := resolvconf.GetLastModified()
|
||||
|
||||
// clean container resolv.conf re: localhost nameservers and IPv6 NS (if IPv6 disabled)
|
||||
updatedResolvConf, modified := resolvconf.FilterResolvDns(latestResolvConf, container.daemon.config.EnableIPv6)
|
||||
updatedResolvConf, modified := resolvconf.FilterResolvDns(latestResolvConf, container.daemon.config.Bridge.EnableIPv6)
|
||||
if modified {
|
||||
// changes have occurred during resolv.conf localhost cleanup: generate an updated hash
|
||||
newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
|
||||
|
@ -1131,7 +1114,7 @@ func (container *Container) setupContainerDns() error {
|
|||
}
|
||||
|
||||
// replace any localhost/127.*, and remove IPv6 nameservers if IPv6 disabled in daemon
|
||||
resolvConf, _ = resolvconf.FilterResolvDns(resolvConf, daemon.config.EnableIPv6)
|
||||
resolvConf, _ = resolvconf.FilterResolvDns(resolvConf, daemon.config.Bridge.EnableIPv6)
|
||||
}
|
||||
//get a sha256 hash of the resolv conf at this point so we can check
|
||||
//for changes when the host resolv.conf changes (e.g. network update)
|
||||
|
@ -1481,24 +1464,10 @@ func (container *Container) allocatePort(eng *engine.Engine, port nat.Port, bind
|
|||
}
|
||||
|
||||
for i := 0; i < len(binding); i++ {
|
||||
b := binding[i]
|
||||
|
||||
job := eng.Job("allocate_port", container.ID)
|
||||
job.Setenv("HostIP", b.HostIp)
|
||||
job.Setenv("HostPort", b.HostPort)
|
||||
job.Setenv("Proto", port.Proto())
|
||||
job.Setenv("ContainerPort", port.Port())
|
||||
|
||||
portEnv, err := job.Stdout.AddEnv()
|
||||
b, err := bridge.AllocatePort(container.ID, port, binding[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := job.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
b.HostIp = portEnv.Get("HostIP")
|
||||
b.HostPort = portEnv.Get("HostPort")
|
||||
|
||||
binding[i] = b
|
||||
}
|
||||
bindings[port] = binding
|
||||
|
|
|
@ -25,7 +25,8 @@ import (
|
|||
"github.com/docker/docker/daemon/execdriver/lxc"
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
_ "github.com/docker/docker/daemon/graphdriver/vfs"
|
||||
_ "github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/graph"
|
||||
"github.com/docker/docker/image"
|
||||
|
@ -445,7 +446,7 @@ func (daemon *Daemon) setupResolvconfWatcher() error {
|
|||
logrus.Debugf("Error retrieving updated host resolv.conf: %v", err)
|
||||
} else if updatedResolvConf != nil {
|
||||
// because the new host resolv.conf might have localhost nameservers..
|
||||
updatedResolvConf, modified := resolvconf.FilterResolvDns(updatedResolvConf, daemon.config.EnableIPv6)
|
||||
updatedResolvConf, modified := resolvconf.FilterResolvDns(updatedResolvConf, daemon.config.Bridge.EnableIPv6)
|
||||
if modified {
|
||||
// changes have occurred during localhost cleanup: generate an updated hash
|
||||
newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
|
||||
|
@ -653,7 +654,7 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
|
|||
Config: config,
|
||||
hostConfig: &runconfig.HostConfig{},
|
||||
ImageID: imgID,
|
||||
NetworkSettings: &NetworkSettings{},
|
||||
NetworkSettings: &network.Settings{},
|
||||
Name: name,
|
||||
Driver: daemon.driver.String(),
|
||||
ExecDriver: daemon.execDriver.Name(),
|
||||
|
@ -807,16 +808,16 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
|
|||
config.Mtu = getDefaultNetworkMtu()
|
||||
}
|
||||
// Check for mutually incompatible config options
|
||||
if config.BridgeIface != "" && config.BridgeIP != "" {
|
||||
if config.Bridge.Iface != "" && config.Bridge.IP != "" {
|
||||
return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
|
||||
}
|
||||
if !config.EnableIptables && !config.InterContainerCommunication {
|
||||
if !config.Bridge.EnableIptables && !config.Bridge.InterContainerCommunication {
|
||||
return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
|
||||
}
|
||||
if !config.EnableIptables && config.EnableIpMasq {
|
||||
config.EnableIpMasq = false
|
||||
if !config.Bridge.EnableIptables && config.Bridge.EnableIpMasq {
|
||||
config.Bridge.EnableIpMasq = false
|
||||
}
|
||||
config.DisableNetwork = config.BridgeIface == disableNetworkBridge
|
||||
config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge
|
||||
|
||||
// Claim the pidfile first, to avoid any and all unexpected race conditions.
|
||||
// Some of the init doesn't need a pidfile lock - but let's not try to be smart.
|
||||
|
@ -948,20 +949,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
|
|||
}
|
||||
|
||||
if !config.DisableNetwork {
|
||||
job := eng.Job("init_networkdriver")
|
||||
|
||||
job.SetenvBool("EnableIptables", config.EnableIptables)
|
||||
job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication)
|
||||
job.SetenvBool("EnableIpForward", config.EnableIpForward)
|
||||
job.SetenvBool("EnableIpMasq", config.EnableIpMasq)
|
||||
job.SetenvBool("EnableIPv6", config.EnableIPv6)
|
||||
job.Setenv("BridgeIface", config.BridgeIface)
|
||||
job.Setenv("BridgeIP", config.BridgeIP)
|
||||
job.Setenv("FixedCIDR", config.FixedCIDR)
|
||||
job.Setenv("FixedCIDRv6", config.FixedCIDRv6)
|
||||
job.Setenv("DefaultBindingIP", config.DefaultIp.String())
|
||||
|
||||
if err := job.Run(); err != nil {
|
||||
if err := bridge.InitDriver(&config.Bridge); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
package daemon
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/nat"
|
||||
)
|
||||
import "github.com/docker/docker/nat"
|
||||
|
||||
// FIXME: move deprecated port stuff to nat to clean up the core.
|
||||
type PortMapping map[string]string // Deprecated
|
||||
|
||||
type NetworkSettings struct {
|
||||
type Settings struct {
|
||||
IPAddress string
|
||||
IPPrefixLen int
|
||||
MacAddress string
|
||||
|
@ -18,6 +13,6 @@ type NetworkSettings struct {
|
|||
Gateway string
|
||||
IPv6Gateway string
|
||||
Bridge string
|
||||
PortMapping map[string]PortMapping // Deprecated
|
||||
PortMapping map[string]map[string]string // Deprecated
|
||||
Ports nat.PortMap
|
||||
}
|
|
@ -7,14 +7,15 @@ import (
|
|||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/daemon/networkdriver"
|
||||
"github.com/docker/docker/daemon/networkdriver/ipallocator"
|
||||
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/nat"
|
||||
"github.com/docker/docker/pkg/iptables"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
|
@ -91,29 +92,34 @@ func initPortMapper() {
|
|||
})
|
||||
}
|
||||
|
||||
func InitDriver(job *engine.Job) error {
|
||||
type Config struct {
|
||||
EnableIPv6 bool
|
||||
EnableIptables bool
|
||||
EnableIpForward bool
|
||||
EnableIpMasq bool
|
||||
DefaultIp net.IP
|
||||
Iface string
|
||||
IP string
|
||||
FixedCIDR string
|
||||
FixedCIDRv6 string
|
||||
InterContainerCommunication bool
|
||||
}
|
||||
|
||||
func InitDriver(config *Config) error {
|
||||
var (
|
||||
networkv4 *net.IPNet
|
||||
networkv6 *net.IPNet
|
||||
addrv4 net.Addr
|
||||
addrsv6 []net.Addr
|
||||
enableIPTables = job.GetenvBool("EnableIptables")
|
||||
enableIPv6 = job.GetenvBool("EnableIPv6")
|
||||
icc = job.GetenvBool("InterContainerCommunication")
|
||||
ipMasq = job.GetenvBool("EnableIpMasq")
|
||||
ipForward = job.GetenvBool("EnableIpForward")
|
||||
bridgeIP = job.Getenv("BridgeIP")
|
||||
bridgeIPv6 = "fe80::1/64"
|
||||
fixedCIDR = job.Getenv("FixedCIDR")
|
||||
fixedCIDRv6 = job.Getenv("FixedCIDRv6")
|
||||
)
|
||||
initPortMapper()
|
||||
|
||||
if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
|
||||
defaultBindingIP = net.ParseIP(defaultIP)
|
||||
if config.DefaultIp != nil {
|
||||
defaultBindingIP = config.DefaultIp
|
||||
}
|
||||
|
||||
bridgeIface = job.Getenv("BridgeIface")
|
||||
bridgeIface = config.Iface
|
||||
usingDefaultBridge := false
|
||||
if bridgeIface == "" {
|
||||
usingDefaultBridge = true
|
||||
|
@ -130,7 +136,7 @@ func InitDriver(job *engine.Job) error {
|
|||
}
|
||||
|
||||
// If the iface is not found, try to create it
|
||||
if err := configureBridge(bridgeIP, bridgeIPv6, enableIPv6); err != nil {
|
||||
if err := configureBridge(config.IP, bridgeIPv6, config.EnableIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -139,19 +145,19 @@ func InitDriver(job *engine.Job) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if fixedCIDRv6 != "" {
|
||||
if config.FixedCIDRv6 != "" {
|
||||
// Setting route to global IPv6 subnet
|
||||
logrus.Infof("Adding route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
|
||||
if err := netlink.AddRoute(fixedCIDRv6, "", "", bridgeIface); err != nil {
|
||||
logrus.Fatalf("Could not add route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
|
||||
logrus.Infof("Adding route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
|
||||
if err := netlink.AddRoute(config.FixedCIDRv6, "", "", bridgeIface); err != nil {
|
||||
logrus.Fatalf("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Bridge exists already, getting info...
|
||||
// Validate that the bridge ip matches the ip specified by BridgeIP
|
||||
if bridgeIP != "" {
|
||||
if config.IP != "" {
|
||||
networkv4 = addrv4.(*net.IPNet)
|
||||
bip, _, err := net.ParseCIDR(bridgeIP)
|
||||
bip, _, err := net.ParseCIDR(config.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -164,7 +170,7 @@ func InitDriver(job *engine.Job) error {
|
|||
// (for example, an existing Docker installation that has only been used
|
||||
// with IPv4 and docker0 already is set up) In that case, we can perform
|
||||
// the bridge init for IPv6 here, else we will error out below if --ipv6=true
|
||||
if len(addrsv6) == 0 && enableIPv6 {
|
||||
if len(addrsv6) == 0 && config.EnableIPv6 {
|
||||
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -175,10 +181,10 @@ func InitDriver(job *engine.Job) error {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Check if route to fixedCIDRv6 is set
|
||||
// TODO: Check if route to config.FixedCIDRv6 is set
|
||||
}
|
||||
|
||||
if enableIPv6 {
|
||||
if config.EnableIPv6 {
|
||||
bip6, _, err := net.ParseCIDR(bridgeIPv6)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -198,7 +204,7 @@ func InitDriver(job *engine.Job) error {
|
|||
|
||||
networkv4 = addrv4.(*net.IPNet)
|
||||
|
||||
if enableIPv6 {
|
||||
if config.EnableIPv6 {
|
||||
if len(addrsv6) == 0 {
|
||||
return errors.New("IPv6 enabled but no IPv6 detected")
|
||||
}
|
||||
|
@ -206,20 +212,20 @@ func InitDriver(job *engine.Job) error {
|
|||
}
|
||||
|
||||
// Configure iptables for link support
|
||||
if enableIPTables {
|
||||
if err := setupIPTables(addrv4, icc, ipMasq); err != nil {
|
||||
if config.EnableIptables {
|
||||
if err := setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ipForward {
|
||||
if config.EnableIpForward {
|
||||
// Enable IPv4 forwarding
|
||||
if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
|
||||
logrus.Warnf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
|
||||
}
|
||||
|
||||
if fixedCIDRv6 != "" {
|
||||
if config.FixedCIDRv6 != "" {
|
||||
// Enable IPv6 forwarding
|
||||
if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
|
||||
logrus.Warnf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
|
||||
|
@ -235,7 +241,7 @@ func InitDriver(job *engine.Job) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if enableIPTables {
|
||||
if config.EnableIptables {
|
||||
_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -248,8 +254,8 @@ func InitDriver(job *engine.Job) error {
|
|||
}
|
||||
|
||||
bridgeIPv4Network = networkv4
|
||||
if fixedCIDR != "" {
|
||||
_, subnet, err := net.ParseCIDR(fixedCIDR)
|
||||
if config.FixedCIDR != "" {
|
||||
_, subnet, err := net.ParseCIDR(config.FixedCIDR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -259,8 +265,8 @@ func InitDriver(job *engine.Job) error {
|
|||
}
|
||||
}
|
||||
|
||||
if fixedCIDRv6 != "" {
|
||||
_, subnet, err := net.ParseCIDR(fixedCIDRv6)
|
||||
if config.FixedCIDRv6 != "" {
|
||||
_, subnet, err := net.ParseCIDR(config.FixedCIDRv6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -274,19 +280,6 @@ func InitDriver(job *engine.Job) error {
|
|||
// Block BridgeIP in IP allocator
|
||||
ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
|
||||
|
||||
// https://github.com/docker/docker/issues/2768
|
||||
job.Eng.HackSetGlobalVar("httpapi.bridgeIP", bridgeIPv4Network.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 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -513,70 +506,67 @@ func linkLocalIPv6FromMac(mac string) (string, error) {
|
|||
}
|
||||
|
||||
// Allocate a network interface
|
||||
func Allocate(job *engine.Job) error {
|
||||
func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Settings, error) {
|
||||
var (
|
||||
ip net.IP
|
||||
mac net.HardwareAddr
|
||||
err error
|
||||
id = job.Args[0]
|
||||
requestedIP = net.ParseIP(job.Getenv("RequestedIP"))
|
||||
requestedIPv6 = net.ParseIP(job.Getenv("RequestedIPv6"))
|
||||
globalIPv6 net.IP
|
||||
)
|
||||
|
||||
ip, err = ipAllocator.RequestIP(bridgeIPv4Network, requestedIP)
|
||||
ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP))
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If no explicit mac address was given, generate a random one.
|
||||
if mac, err = net.ParseMAC(job.Getenv("RequestedMac")); err != nil {
|
||||
if mac, err = net.ParseMAC(requestedMac); err != nil {
|
||||
mac = generateMacAddr(ip)
|
||||
}
|
||||
|
||||
if globalIPv6Network != nil {
|
||||
// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
|
||||
netmaskOnes, _ := globalIPv6Network.Mask.Size()
|
||||
if requestedIPv6 == nil && netmaskOnes <= 80 {
|
||||
requestedIPv6 = make(net.IP, len(globalIPv6Network.IP))
|
||||
copy(requestedIPv6, globalIPv6Network.IP)
|
||||
ipv6 := net.ParseIP(requestedIPv6)
|
||||
if ipv6 == nil && netmaskOnes <= 80 {
|
||||
ipv6 = make(net.IP, len(globalIPv6Network.IP))
|
||||
copy(ipv6, globalIPv6Network.IP)
|
||||
for i, h := range mac {
|
||||
requestedIPv6[i+10] = h
|
||||
ipv6[i+10] = h
|
||||
}
|
||||
}
|
||||
|
||||
globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, requestedIPv6)
|
||||
globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, ipv6)
|
||||
if err != nil {
|
||||
logrus.Errorf("Allocator: RequestIP v6: %v", err)
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
logrus.Infof("Allocated IPv6 %s", globalIPv6)
|
||||
}
|
||||
|
||||
out := engine.Env{}
|
||||
out.Set("IP", ip.String())
|
||||
out.Set("Mask", bridgeIPv4Network.Mask.String())
|
||||
out.Set("Gateway", bridgeIPv4Network.IP.String())
|
||||
out.Set("MacAddress", mac.String())
|
||||
out.Set("Bridge", bridgeIface)
|
||||
|
||||
size, _ := bridgeIPv4Network.Mask.Size()
|
||||
out.SetInt("IPPrefixLen", size)
|
||||
maskSize, _ := bridgeIPv4Network.Mask.Size()
|
||||
|
||||
// If linklocal IPv6
|
||||
localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
|
||||
out.Set("LinkLocalIPv6", localIPv6.String())
|
||||
out.Set("MacAddress", mac.String())
|
||||
|
||||
networkSettings := &network.Settings{
|
||||
IPAddress: ip.String(),
|
||||
Gateway: bridgeIPv4Network.IP.String(),
|
||||
MacAddress: mac.String(),
|
||||
Bridge: bridgeIface,
|
||||
IPPrefixLen: maskSize,
|
||||
LinkLocalIPv6Address: localIPv6.String(),
|
||||
}
|
||||
|
||||
if globalIPv6Network != nil {
|
||||
out.Set("GlobalIPv6", globalIPv6.String())
|
||||
sizev6, _ := globalIPv6Network.Mask.Size()
|
||||
out.SetInt("GlobalIPv6PrefixLen", sizev6)
|
||||
out.Set("IPv6Gateway", bridgeIPv6Addr.String())
|
||||
networkSettings.GlobalIPv6Address = globalIPv6.String()
|
||||
maskV6Size, _ := globalIPv6Network.Mask.Size()
|
||||
networkSettings.GlobalIPv6PrefixLen = maskV6Size
|
||||
networkSettings.IPv6Gateway = bridgeIPv6Addr.String()
|
||||
}
|
||||
|
||||
currentInterfaces.Set(id, &networkInterface{
|
||||
|
@ -584,20 +574,15 @@ func Allocate(job *engine.Job) error {
|
|||
IPv6: globalIPv6,
|
||||
})
|
||||
|
||||
out.WriteTo(job.Stdout)
|
||||
|
||||
return nil
|
||||
return networkSettings, nil
|
||||
}
|
||||
|
||||
// Release an interface for a select ip
|
||||
func Release(job *engine.Job) error {
|
||||
var (
|
||||
id = job.Args[0]
|
||||
containerInterface = currentInterfaces.Get(id)
|
||||
)
|
||||
func Release(id string) {
|
||||
var containerInterface = currentInterfaces.Get(id)
|
||||
|
||||
if containerInterface == nil {
|
||||
return fmt.Errorf("No network information to release for %s", id)
|
||||
logrus.Warnf("No network information to release for %s", id)
|
||||
}
|
||||
|
||||
for _, nat := range containerInterface.PortMappings {
|
||||
|
@ -614,27 +599,21 @@ func Release(job *engine.Job) error {
|
|||
logrus.Infof("Unable to release IPv6 %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Allocate an external port and map it to the interface
|
||||
func AllocatePort(job *engine.Job) error {
|
||||
func AllocatePort(id string, port nat.Port, binding nat.PortBinding) (nat.PortBinding, error) {
|
||||
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")
|
||||
proto = port.Proto()
|
||||
containerPort = port.Int()
|
||||
network = currentInterfaces.Get(id)
|
||||
)
|
||||
|
||||
if hostIP != "" {
|
||||
ip = net.ParseIP(hostIP)
|
||||
if binding.HostIp != "" {
|
||||
ip = net.ParseIP(binding.HostIp)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("Bad parameter: invalid host ip %s", hostIP)
|
||||
return nat.PortBinding{}, fmt.Errorf("Bad parameter: invalid host ip %s", binding.HostIp)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -646,7 +625,7 @@ func AllocatePort(job *engine.Job) error {
|
|||
case "udp":
|
||||
container = &net.UDPAddr{IP: network.IP, Port: containerPort}
|
||||
default:
|
||||
return fmt.Errorf("unsupported address type %s", proto)
|
||||
return nat.PortBinding{}, fmt.Errorf("unsupported address type %s", proto)
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -656,7 +635,14 @@ func AllocatePort(job *engine.Job) error {
|
|||
// yields.
|
||||
//
|
||||
|
||||
var host net.Addr
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
)
|
||||
hostPort, err := nat.ParsePort(binding.HostPort)
|
||||
if err != nil {
|
||||
return nat.PortBinding{}, err
|
||||
}
|
||||
for i := 0; i < MaxAllocatedPortAttempts; i++ {
|
||||
if host, err = portMapper.Map(container, ip, hostPort); err == nil {
|
||||
break
|
||||
|
@ -671,36 +657,24 @@ func AllocatePort(job *engine.Job) error {
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
return nat.PortBinding{}, err
|
||||
}
|
||||
|
||||
network.PortMappings = append(network.PortMappings, host)
|
||||
|
||||
out := engine.Env{}
|
||||
switch netAddr := host.(type) {
|
||||
case *net.TCPAddr:
|
||||
out.Set("HostIP", netAddr.IP.String())
|
||||
out.SetInt("HostPort", netAddr.Port)
|
||||
return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
|
||||
case *net.UDPAddr:
|
||||
out.Set("HostIP", netAddr.IP.String())
|
||||
out.SetInt("HostPort", netAddr.Port)
|
||||
return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
|
||||
default:
|
||||
return nat.PortBinding{}, fmt.Errorf("unsupported address type %T", netAddr)
|
||||
}
|
||||
if _, err := out.WriteTo(job.Stdout); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func LinkContainers(job *engine.Job) error {
|
||||
var (
|
||||
action = job.Args[0]
|
||||
nfAction iptables.Action
|
||||
childIP = job.Getenv("ChildIP")
|
||||
parentIP = job.Getenv("ParentIP")
|
||||
ignoreErrors = job.GetenvBool("IgnoreErrors")
|
||||
ports = job.GetenvList("Ports")
|
||||
)
|
||||
//TODO: should it return something more than just an error?
|
||||
func LinkContainers(action, parentIP, childIP string, ports []nat.Port, ignoreErrors bool) error {
|
||||
var nfAction iptables.Action
|
||||
|
||||
switch action {
|
||||
case "-A":
|
||||
|
@ -723,8 +697,7 @@ func LinkContainers(job *engine.Job) error {
|
|||
}
|
||||
|
||||
chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
|
||||
for _, p := range ports {
|
||||
port := nat.Port(p)
|
||||
for _, port := range ports {
|
||||
if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -6,8 +6,9 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/nat"
|
||||
"github.com/docker/docker/pkg/iptables"
|
||||
)
|
||||
|
||||
|
@ -16,7 +17,7 @@ func init() {
|
|||
portmapper.NewProxy = portmapper.NewMockProxyCommand
|
||||
}
|
||||
|
||||
func findFreePort(t *testing.T) int {
|
||||
func findFreePort(t *testing.T) string {
|
||||
l, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to find a free port")
|
||||
|
@ -27,143 +28,85 @@ func findFreePort(t *testing.T) int {
|
|||
if err != nil {
|
||||
t.Fatal("Failed to resolve address to identify free port")
|
||||
}
|
||||
return result.Port
|
||||
}
|
||||
|
||||
func newPortAllocationJob(eng *engine.Engine, port int) (job *engine.Job) {
|
||||
strPort := strconv.Itoa(port)
|
||||
|
||||
job = eng.Job("allocate_port", "container_id")
|
||||
job.Setenv("HostIP", "127.0.0.1")
|
||||
job.Setenv("HostPort", strPort)
|
||||
job.Setenv("Proto", "tcp")
|
||||
job.Setenv("ContainerPort", strPort)
|
||||
return
|
||||
}
|
||||
|
||||
func newPortAllocationJobWithInvalidHostIP(eng *engine.Engine, port int) (job *engine.Job) {
|
||||
strPort := strconv.Itoa(port)
|
||||
|
||||
job = eng.Job("allocate_port", "container_id")
|
||||
job.Setenv("HostIP", "localhost")
|
||||
job.Setenv("HostPort", strPort)
|
||||
job.Setenv("Proto", "tcp")
|
||||
job.Setenv("ContainerPort", strPort)
|
||||
return
|
||||
return strconv.Itoa(result.Port)
|
||||
}
|
||||
|
||||
func TestAllocatePortDetection(t *testing.T) {
|
||||
eng := engine.New()
|
||||
eng.Logging = false
|
||||
|
||||
freePort := findFreePort(t)
|
||||
|
||||
// Init driver
|
||||
job := eng.Job("initdriver")
|
||||
if res := InitDriver(job); res != nil {
|
||||
if err := InitDriver(new(Config)); err != nil {
|
||||
t.Fatal("Failed to initialize network driver")
|
||||
}
|
||||
|
||||
// Allocate interface
|
||||
job = eng.Job("allocate_interface", "container_id")
|
||||
if res := Allocate(job); res != nil {
|
||||
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||
t.Fatal("Failed to allocate network interface")
|
||||
}
|
||||
|
||||
port := nat.Port(freePort + "/tcp")
|
||||
binding := nat.PortBinding{HostIp: "127.0.0.1", HostPort: freePort}
|
||||
|
||||
// Allocate same port twice, expect failure on second call
|
||||
job = newPortAllocationJob(eng, freePort)
|
||||
if res := AllocatePort(job); res != nil {
|
||||
if _, err := AllocatePort("container_id", port, binding); err != nil {
|
||||
t.Fatal("Failed to find a free port to allocate")
|
||||
}
|
||||
if res := AllocatePort(job); res == nil {
|
||||
if _, err := AllocatePort("container_id", port, binding); err == nil {
|
||||
t.Fatal("Duplicate port allocation granted by AllocatePort")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostnameFormatChecking(t *testing.T) {
|
||||
eng := engine.New()
|
||||
eng.Logging = false
|
||||
|
||||
freePort := findFreePort(t)
|
||||
|
||||
// Init driver
|
||||
job := eng.Job("initdriver")
|
||||
if res := InitDriver(job); res != nil {
|
||||
if err := InitDriver(new(Config)); err != nil {
|
||||
t.Fatal("Failed to initialize network driver")
|
||||
}
|
||||
|
||||
// Allocate interface
|
||||
job = eng.Job("allocate_interface", "container_id")
|
||||
if res := Allocate(job); res != nil {
|
||||
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||
t.Fatal("Failed to allocate network interface")
|
||||
}
|
||||
|
||||
// Allocate port with invalid HostIP, expect failure with Bad Request http status
|
||||
job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
|
||||
if res := AllocatePort(job); res == nil {
|
||||
port := nat.Port(freePort + "/tcp")
|
||||
binding := nat.PortBinding{HostIp: "localhost", HostPort: freePort}
|
||||
|
||||
if _, err := AllocatePort("container_id", port, binding); err == nil {
|
||||
t.Fatal("Failed to check invalid HostIP")
|
||||
}
|
||||
}
|
||||
|
||||
func newInterfaceAllocation(t *testing.T, input engine.Env) (output engine.Env) {
|
||||
eng := engine.New()
|
||||
eng.Logging = false
|
||||
|
||||
done := make(chan bool)
|
||||
|
||||
func newInterfaceAllocation(t *testing.T, globalIPv6 *net.IPNet, requestedMac, requestedIP, requestedIPv6 string, expectFail bool) *network.Settings {
|
||||
// set IPv6 global if given
|
||||
if input.Exists("globalIPv6Network") {
|
||||
_, globalIPv6Network, _ = net.ParseCIDR(input.Get("globalIPv6Network"))
|
||||
if globalIPv6 != nil {
|
||||
globalIPv6Network = globalIPv6
|
||||
}
|
||||
|
||||
job := eng.Job("allocate_interface", "container_id")
|
||||
job.Env().Init(&input)
|
||||
reader, _ := job.Stdout.AddPipe()
|
||||
go func() {
|
||||
output.Decode(reader)
|
||||
done <- true
|
||||
}()
|
||||
|
||||
res := Allocate(job)
|
||||
job.Stdout.Close()
|
||||
<-done
|
||||
|
||||
if input.Exists("expectFail") && input.GetBool("expectFail") {
|
||||
if res == nil {
|
||||
networkSettings, err := Allocate("container_id", requestedMac, requestedIP, requestedIPv6)
|
||||
if err == nil && expectFail {
|
||||
t.Fatal("Doesn't fail to allocate network interface")
|
||||
}
|
||||
} else {
|
||||
if res != nil {
|
||||
} else if err != nil && !expectFail {
|
||||
t.Fatal("Failed to allocate network interface")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if input.Exists("globalIPv6Network") {
|
||||
if globalIPv6 != nil {
|
||||
// check for bug #11427
|
||||
_, subnet, _ := net.ParseCIDR(input.Get("globalIPv6Network"))
|
||||
if globalIPv6Network.IP.String() != subnet.IP.String() {
|
||||
if globalIPv6Network.IP.String() != globalIPv6.IP.String() {
|
||||
t.Fatal("globalIPv6Network was modified during allocation")
|
||||
}
|
||||
// clean up IPv6 global
|
||||
globalIPv6Network = nil
|
||||
}
|
||||
|
||||
return
|
||||
return networkSettings
|
||||
}
|
||||
|
||||
func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
|
||||
|
||||
input := engine.Env{}
|
||||
|
||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81")
|
||||
|
||||
// set global ipv6
|
||||
input.Set("globalIPv6Network", subnet.String())
|
||||
|
||||
output := newInterfaceAllocation(t, input)
|
||||
networkSettings := newInterfaceAllocation(t, subnet, "", "", "", false)
|
||||
|
||||
// ensure low manually assigend global ip
|
||||
ip := net.ParseIP(output.Get("GlobalIPv6"))
|
||||
ip := net.ParseIP(networkSettings.GlobalIPv6Address)
|
||||
_, subnet, _ = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet.IP.String(), 120))
|
||||
if !subnet.Contains(ip) {
|
||||
t.Fatalf("Error ip %s not in subnet %s", ip.String(), subnet.String())
|
||||
|
@ -171,26 +114,18 @@ func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
|
||||
|
||||
input := engine.Env{}
|
||||
|
||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
|
||||
|
||||
// set global ipv6
|
||||
input.Set("globalIPv6Network", subnet.String())
|
||||
input.Set("RequestedMac", "ab:cd:ab:cd:ab:cd")
|
||||
|
||||
output := newInterfaceAllocation(t, input)
|
||||
networkSettings := newInterfaceAllocation(t, subnet, "ab:cd:ab:cd:ab:cd", "", "", false)
|
||||
|
||||
// ensure global ip with mac
|
||||
ip := net.ParseIP(output.Get("GlobalIPv6"))
|
||||
ip := net.ParseIP(networkSettings.GlobalIPv6Address)
|
||||
expectedIP := net.ParseIP("2001:db8:1234:1234:1234:abcd:abcd:abcd")
|
||||
if ip.String() != expectedIP.String() {
|
||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
||||
}
|
||||
|
||||
// ensure link local format
|
||||
ip = net.ParseIP(output.Get("LinkLocalIPv6"))
|
||||
ip = net.ParseIP(networkSettings.LinkLocalIPv6Address)
|
||||
expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd")
|
||||
if ip.String() != expectedIP.String() {
|
||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
||||
|
@ -199,27 +134,19 @@ func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIPv6InterfaceAllocationRequest(t *testing.T) {
|
||||
|
||||
input := engine.Env{}
|
||||
|
||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
|
||||
expectedIP := net.ParseIP("2001:db8:1234:1234:1234::1328")
|
||||
expectedIP := "2001:db8:1234:1234:1234::1328"
|
||||
|
||||
// set global ipv6
|
||||
input.Set("globalIPv6Network", subnet.String())
|
||||
input.Set("RequestedIPv6", expectedIP.String())
|
||||
|
||||
output := newInterfaceAllocation(t, input)
|
||||
networkSettings := newInterfaceAllocation(t, subnet, "", "", expectedIP, false)
|
||||
|
||||
// ensure global ip with mac
|
||||
ip := net.ParseIP(output.Get("GlobalIPv6"))
|
||||
if ip.String() != expectedIP.String() {
|
||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
||||
ip := net.ParseIP(networkSettings.GlobalIPv6Address)
|
||||
if ip.String() != expectedIP {
|
||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP)
|
||||
}
|
||||
|
||||
// retry -> fails for duplicated address
|
||||
input.SetBool("expectFail", true)
|
||||
output = newInterfaceAllocation(t, input)
|
||||
_ = newInterfaceAllocation(t, subnet, "", "", expectedIP, true)
|
||||
}
|
||||
|
||||
func TestMacAddrGeneration(t *testing.T) {
|
||||
|
@ -239,40 +166,27 @@ func TestMacAddrGeneration(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLinkContainers(t *testing.T) {
|
||||
eng := engine.New()
|
||||
eng.Logging = false
|
||||
|
||||
// Init driver
|
||||
job := eng.Job("initdriver")
|
||||
if res := InitDriver(job); res != nil {
|
||||
if err := InitDriver(new(Config)); err != nil {
|
||||
t.Fatal("Failed to initialize network driver")
|
||||
}
|
||||
|
||||
// Allocate interface
|
||||
job = eng.Job("allocate_interface", "container_id")
|
||||
if res := Allocate(job); res != nil {
|
||||
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||
t.Fatal("Failed to allocate network interface")
|
||||
}
|
||||
|
||||
job.Args[0] = "-I"
|
||||
|
||||
job.Setenv("ChildIP", "172.17.0.2")
|
||||
job.Setenv("ParentIP", "172.17.0.1")
|
||||
job.SetenvBool("IgnoreErrors", false)
|
||||
job.SetenvList("Ports", []string{"1234"})
|
||||
|
||||
bridgeIface = "lo"
|
||||
_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
|
||||
if err != nil {
|
||||
if _, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if res := LinkContainers(job); res != nil {
|
||||
t.Fatalf("LinkContainers failed")
|
||||
if err := LinkContainers("-I", "172.17.0.1", "172.17.0.2", []nat.Port{nat.Port("1234")}, false); err != nil {
|
||||
t.Fatal("LinkContainers failed")
|
||||
}
|
||||
|
||||
// flush rules
|
||||
if _, err = iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
|
||||
if _, err := iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/builtins"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/engine"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/registry"
|
||||
|
@ -185,7 +186,9 @@ func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine {
|
|||
ExecDriver: "native",
|
||||
// Either InterContainerCommunication or EnableIptables must be set,
|
||||
// otherwise NewDaemon will fail because of conflicting settings.
|
||||
Bridge: bridge.Config{
|
||||
InterContainerCommunication: true,
|
||||
},
|
||||
TrustKeyPath: filepath.Join(root, "key.json"),
|
||||
LogConfig: runconfig.LogConfig{Type: "json-file"},
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@ package links
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/nat"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/nat"
|
||||
)
|
||||
|
||||
type Link struct {
|
||||
|
@ -158,21 +160,5 @@ func (l *Link) Disable() {
|
|||
}
|
||||
|
||||
func (l *Link) toggle(action string, ignoreErrors bool) error {
|
||||
job := l.eng.Job("link", action)
|
||||
|
||||
job.Setenv("ParentIP", l.ParentIP)
|
||||
job.Setenv("ChildIP", l.ChildIP)
|
||||
job.SetenvBool("IgnoreErrors", ignoreErrors)
|
||||
|
||||
out := make([]string, len(l.Ports))
|
||||
for i, p := range l.Ports {
|
||||
out[i] = string(p)
|
||||
}
|
||||
job.SetenvList("Ports", out)
|
||||
|
||||
if err := job.Run(); err != nil {
|
||||
// TODO: get ouput from job
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return bridge.LinkContainers(action, l.ParentIP, l.ChildIP, l.Ports, ignoreErrors)
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ func NewPort(proto, port string) Port {
|
|||
}
|
||||
|
||||
func ParsePort(rawPort string) (int, error) {
|
||||
if len(rawPort) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
port, err := strconv.ParseUint(rawPort, 10, 16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
|
Loading…
Reference in a new issue