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
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/engine"
|
|
||||||
"github.com/docker/docker/nat"
|
"github.com/docker/docker/nat"
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
flag "github.com/docker/docker/pkg/mflag"
|
||||||
)
|
)
|
||||||
|
@ -23,12 +23,13 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
env := engine.Env{}
|
var c struct {
|
||||||
if err := env.Decode(stream); err != nil {
|
NetworkSettings struct {
|
||||||
return err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
||||||
proto = parts[1]
|
proto = parts[1]
|
||||||
}
|
}
|
||||||
natPort := port + "/" + proto
|
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 {
|
for _, frontend := range frontends {
|
||||||
fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
|
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))
|
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 {
|
for _, frontend := range frontends {
|
||||||
fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
|
fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,11 @@ import (
|
||||||
"github.com/docker/docker/api"
|
"github.com/docker/docker/api"
|
||||||
apiserver "github.com/docker/docker/api/server"
|
apiserver "github.com/docker/docker/api/server"
|
||||||
"github.com/docker/docker/autogen/dockerversion"
|
"github.com/docker/docker/autogen/dockerversion"
|
||||||
"github.com/docker/docker/daemon/networkdriver/bridge"
|
|
||||||
"github.com/docker/docker/engine"
|
"github.com/docker/docker/engine"
|
||||||
"github.com/docker/docker/pkg/parsers/kernel"
|
"github.com/docker/docker/pkg/parsers/kernel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Register(eng *engine.Engine) error {
|
func Register(eng *engine.Engine) error {
|
||||||
if err := daemon(eng); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := remote(eng); err != nil {
|
if err := remote(eng); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -33,25 +29,6 @@ func remote(eng *engine.Engine) error {
|
||||||
return eng.Register("acceptconnections", apiserver.AcceptConnections)
|
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
|
// builtins jobs independent of any subsystem
|
||||||
func dockerVersion(job *engine.Job) error {
|
func dockerVersion(job *engine.Job) error {
|
||||||
v := &engine.Env{}
|
v := &engine.Env{}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/docker/docker/daemon/networkdriver"
|
"github.com/docker/docker/daemon/networkdriver"
|
||||||
|
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||||
"github.com/docker/docker/opts"
|
"github.com/docker/docker/opts"
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
flag "github.com/docker/docker/pkg/mflag"
|
||||||
"github.com/docker/docker/pkg/ulimit"
|
"github.com/docker/docker/pkg/ulimit"
|
||||||
|
@ -20,35 +19,27 @@ const (
|
||||||
// to the docker daemon when you launch it with say: `docker -d -e lxc`
|
// to the docker daemon when you launch it with say: `docker -d -e lxc`
|
||||||
// FIXME: separate runtime configuration from http api configuration
|
// FIXME: separate runtime configuration from http api configuration
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Pidfile string
|
Bridge bridge.Config
|
||||||
Root string
|
|
||||||
AutoRestart bool
|
Pidfile string
|
||||||
Dns []string
|
Root string
|
||||||
DnsSearch []string
|
AutoRestart bool
|
||||||
EnableIPv6 bool
|
Dns []string
|
||||||
EnableIptables bool
|
DnsSearch []string
|
||||||
EnableIpForward bool
|
GraphDriver string
|
||||||
EnableIpMasq bool
|
GraphOptions []string
|
||||||
DefaultIp net.IP
|
ExecDriver string
|
||||||
BridgeIface string
|
Mtu int
|
||||||
BridgeIP string
|
SocketGroup string
|
||||||
FixedCIDR string
|
EnableCors bool
|
||||||
FixedCIDRv6 string
|
CorsHeaders string
|
||||||
InterContainerCommunication bool
|
DisableNetwork bool
|
||||||
GraphDriver string
|
EnableSelinuxSupport bool
|
||||||
GraphOptions []string
|
Context map[string][]string
|
||||||
ExecDriver string
|
TrustKeyPath string
|
||||||
Mtu int
|
Labels []string
|
||||||
SocketGroup string
|
Ulimits map[string]*ulimit.Ulimit
|
||||||
EnableCors bool
|
LogConfig runconfig.LogConfig
|
||||||
CorsHeaders string
|
|
||||||
DisableNetwork bool
|
|
||||||
EnableSelinuxSupport bool
|
|
||||||
Context map[string][]string
|
|
||||||
TrustKeyPath string
|
|
||||||
Labels []string
|
|
||||||
Ulimits map[string]*ulimit.Ulimit
|
|
||||||
LogConfig runconfig.LogConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallFlags adds command-line options to the top-level flag parser for
|
// InstallFlags adds command-line options to the top-level flag parser for
|
||||||
|
@ -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.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.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.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.Bridge.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.Bridge.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.Bridge.EnableIpMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
|
||||||
flag.BoolVar(&config.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
|
||||||
flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
|
||||||
flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
|
||||||
flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
|
||||||
flag.StringVar(&config.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
|
flag.StringVar(&config.Bridge.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.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
||||||
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
|
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.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")
|
||||||
flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
|
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.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.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")
|
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")
|
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
|
||||||
// FIXME: why the inconsistency between "hosts" and "sockets"?
|
// FIXME: why the inconsistency between "hosts" and "sockets"?
|
||||||
opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
|
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"
|
||||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||||
"github.com/docker/docker/daemon/logger/syslog"
|
"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/engine"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/links"
|
"github.com/docker/docker/links"
|
||||||
|
@ -73,7 +75,7 @@ type Container struct {
|
||||||
Config *runconfig.Config
|
Config *runconfig.Config
|
||||||
ImageID string `json:"Image"`
|
ImageID string `json:"Image"`
|
||||||
|
|
||||||
NetworkSettings *NetworkSettings
|
NetworkSettings *network.Settings
|
||||||
|
|
||||||
ResolvConfPath string
|
ResolvConfPath string
|
||||||
HostnamePath string
|
HostnamePath string
|
||||||
|
@ -571,17 +573,12 @@ func (container *Container) AllocateNetwork() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
env *engine.Env
|
|
||||||
err error
|
err error
|
||||||
eng = container.daemon.eng
|
eng = container.daemon.eng
|
||||||
)
|
)
|
||||||
|
|
||||||
job := eng.Job("allocate_interface", container.ID)
|
networkSettings, err := bridge.Allocate(container.ID, container.Config.MacAddress, "", "")
|
||||||
job.Setenv("RequestedMac", container.Config.MacAddress)
|
if err != nil {
|
||||||
if env, err = job.Stdout.AddEnv(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = job.Run(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,12 +588,12 @@ func (container *Container) AllocateNetwork() error {
|
||||||
|
|
||||||
if container.Config.PortSpecs != nil {
|
if container.Config.PortSpecs != nil {
|
||||||
if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
|
if err = migratePortMappings(container.Config, container.hostConfig); err != nil {
|
||||||
eng.Job("release_interface", container.ID).Run()
|
bridge.Release(container.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
container.Config.PortSpecs = nil
|
container.Config.PortSpecs = nil
|
||||||
if err = container.WriteHostConfig(); err != nil {
|
if err = container.WriteHostConfig(); err != nil {
|
||||||
eng.Job("release_interface", container.ID).Run()
|
bridge.Release(container.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,23 +623,14 @@ func (container *Container) AllocateNetwork() error {
|
||||||
|
|
||||||
for port := range portSpecs {
|
for port := range portSpecs {
|
||||||
if err = container.allocatePort(eng, port, bindings); err != nil {
|
if err = container.allocatePort(eng, port, bindings); err != nil {
|
||||||
eng.Job("release_interface", container.ID).Run()
|
bridge.Release(container.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
container.WriteHostConfig()
|
container.WriteHostConfig()
|
||||||
|
|
||||||
container.NetworkSettings.Ports = bindings
|
networkSettings.Ports = bindings
|
||||||
container.NetworkSettings.Bridge = env.Get("Bridge")
|
container.NetworkSettings = networkSettings
|
||||||
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")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -651,12 +639,10 @@ func (container *Container) ReleaseNetwork() {
|
||||||
if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
|
if container.Config.NetworkDisabled || !container.hostConfig.NetworkMode.IsPrivate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
eng := container.daemon.eng
|
|
||||||
|
|
||||||
job := eng.Job("release_interface", container.ID)
|
bridge.Release(container.ID)
|
||||||
job.SetenvBool("overrideShutdown", true)
|
|
||||||
job.Run()
|
container.NetworkSettings = &network.Settings{}
|
||||||
container.NetworkSettings = &NetworkSettings{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) isNetworkAllocated() bool {
|
func (container *Container) isNetworkAllocated() bool {
|
||||||
|
@ -675,10 +661,7 @@ func (container *Container) RestoreNetwork() error {
|
||||||
eng := container.daemon.eng
|
eng := container.daemon.eng
|
||||||
|
|
||||||
// Re-allocate the interface with the same IP and MAC address.
|
// Re-allocate the interface with the same IP and MAC address.
|
||||||
job := eng.Job("allocate_interface", container.ID)
|
if _, err := bridge.Allocate(container.ID, container.NetworkSettings.MacAddress, container.NetworkSettings.IPAddress, ""); err != nil {
|
||||||
job.Setenv("RequestedIP", container.NetworkSettings.IPAddress)
|
|
||||||
job.Setenv("RequestedMac", container.NetworkSettings.MacAddress)
|
|
||||||
if err := job.Run(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1060,7 @@ func (container *Container) setupContainerDns() error {
|
||||||
latestResolvConf, latestHash := resolvconf.GetLastModified()
|
latestResolvConf, latestHash := resolvconf.GetLastModified()
|
||||||
|
|
||||||
// clean container resolv.conf re: localhost nameservers and IPv6 NS (if IPv6 disabled)
|
// 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 {
|
if modified {
|
||||||
// changes have occurred during resolv.conf localhost cleanup: generate an updated hash
|
// changes have occurred during resolv.conf localhost cleanup: generate an updated hash
|
||||||
newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
|
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
|
// 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
|
//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)
|
//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++ {
|
for i := 0; i < len(binding); i++ {
|
||||||
b := binding[i]
|
b, err := bridge.AllocatePort(container.ID, port, 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()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := job.Run(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.HostIp = portEnv.Get("HostIP")
|
|
||||||
b.HostPort = portEnv.Get("HostPort")
|
|
||||||
|
|
||||||
binding[i] = b
|
binding[i] = b
|
||||||
}
|
}
|
||||||
bindings[port] = binding
|
bindings[port] = binding
|
||||||
|
|
|
@ -25,7 +25,8 @@ import (
|
||||||
"github.com/docker/docker/daemon/execdriver/lxc"
|
"github.com/docker/docker/daemon/execdriver/lxc"
|
||||||
"github.com/docker/docker/daemon/graphdriver"
|
"github.com/docker/docker/daemon/graphdriver"
|
||||||
_ "github.com/docker/docker/daemon/graphdriver/vfs"
|
_ "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/engine"
|
||||||
"github.com/docker/docker/graph"
|
"github.com/docker/docker/graph"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
|
@ -445,7 +446,7 @@ func (daemon *Daemon) setupResolvconfWatcher() error {
|
||||||
logrus.Debugf("Error retrieving updated host resolv.conf: %v", err)
|
logrus.Debugf("Error retrieving updated host resolv.conf: %v", err)
|
||||||
} else if updatedResolvConf != nil {
|
} else if updatedResolvConf != nil {
|
||||||
// because the new host resolv.conf might have localhost nameservers..
|
// 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 {
|
if modified {
|
||||||
// changes have occurred during localhost cleanup: generate an updated hash
|
// changes have occurred during localhost cleanup: generate an updated hash
|
||||||
newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
|
newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
|
||||||
|
@ -653,7 +654,7 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
|
||||||
Config: config,
|
Config: config,
|
||||||
hostConfig: &runconfig.HostConfig{},
|
hostConfig: &runconfig.HostConfig{},
|
||||||
ImageID: imgID,
|
ImageID: imgID,
|
||||||
NetworkSettings: &NetworkSettings{},
|
NetworkSettings: &network.Settings{},
|
||||||
Name: name,
|
Name: name,
|
||||||
Driver: daemon.driver.String(),
|
Driver: daemon.driver.String(),
|
||||||
ExecDriver: daemon.execDriver.Name(),
|
ExecDriver: daemon.execDriver.Name(),
|
||||||
|
@ -807,16 +808,16 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine, registryService
|
||||||
config.Mtu = getDefaultNetworkMtu()
|
config.Mtu = getDefaultNetworkMtu()
|
||||||
}
|
}
|
||||||
// Check for mutually incompatible config options
|
// 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.")
|
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.")
|
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 {
|
if !config.Bridge.EnableIptables && config.Bridge.EnableIpMasq {
|
||||||
config.EnableIpMasq = false
|
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.
|
// 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.
|
// 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 {
|
if !config.DisableNetwork {
|
||||||
job := eng.Job("init_networkdriver")
|
if err := bridge.InitDriver(&config.Bridge); err != nil {
|
||||||
|
|
||||||
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 {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
package daemon
|
package network
|
||||||
|
|
||||||
import (
|
import "github.com/docker/docker/nat"
|
||||||
"github.com/docker/docker/nat"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FIXME: move deprecated port stuff to nat to clean up the core.
|
type Settings struct {
|
||||||
type PortMapping map[string]string // Deprecated
|
|
||||||
|
|
||||||
type NetworkSettings struct {
|
|
||||||
IPAddress string
|
IPAddress string
|
||||||
IPPrefixLen int
|
IPPrefixLen int
|
||||||
MacAddress string
|
MacAddress string
|
||||||
|
@ -18,6 +13,6 @@ type NetworkSettings struct {
|
||||||
Gateway string
|
Gateway string
|
||||||
IPv6Gateway string
|
IPv6Gateway string
|
||||||
Bridge string
|
Bridge string
|
||||||
PortMapping map[string]PortMapping // Deprecated
|
PortMapping map[string]map[string]string // Deprecated
|
||||||
Ports nat.PortMap
|
Ports nat.PortMap
|
||||||
}
|
}
|
|
@ -7,14 +7,15 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/docker/daemon/network"
|
||||||
"github.com/docker/docker/daemon/networkdriver"
|
"github.com/docker/docker/daemon/networkdriver"
|
||||||
"github.com/docker/docker/daemon/networkdriver/ipallocator"
|
"github.com/docker/docker/daemon/networkdriver/ipallocator"
|
||||||
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
||||||
"github.com/docker/docker/engine"
|
|
||||||
"github.com/docker/docker/nat"
|
"github.com/docker/docker/nat"
|
||||||
"github.com/docker/docker/pkg/iptables"
|
"github.com/docker/docker/pkg/iptables"
|
||||||
"github.com/docker/docker/pkg/parsers/kernel"
|
"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 (
|
var (
|
||||||
networkv4 *net.IPNet
|
networkv4 *net.IPNet
|
||||||
networkv6 *net.IPNet
|
networkv6 *net.IPNet
|
||||||
addrv4 net.Addr
|
addrv4 net.Addr
|
||||||
addrsv6 []net.Addr
|
addrsv6 []net.Addr
|
||||||
enableIPTables = job.GetenvBool("EnableIptables")
|
bridgeIPv6 = "fe80::1/64"
|
||||||
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()
|
initPortMapper()
|
||||||
|
|
||||||
if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
|
if config.DefaultIp != nil {
|
||||||
defaultBindingIP = net.ParseIP(defaultIP)
|
defaultBindingIP = config.DefaultIp
|
||||||
}
|
}
|
||||||
|
|
||||||
bridgeIface = job.Getenv("BridgeIface")
|
bridgeIface = config.Iface
|
||||||
usingDefaultBridge := false
|
usingDefaultBridge := false
|
||||||
if bridgeIface == "" {
|
if bridgeIface == "" {
|
||||||
usingDefaultBridge = true
|
usingDefaultBridge = true
|
||||||
|
@ -130,7 +136,7 @@ func InitDriver(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the iface is not found, try to create it
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,19 +145,19 @@ func InitDriver(job *engine.Job) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fixedCIDRv6 != "" {
|
if config.FixedCIDRv6 != "" {
|
||||||
// Setting route to global IPv6 subnet
|
// Setting route to global IPv6 subnet
|
||||||
logrus.Infof("Adding 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(fixedCIDRv6, "", "", bridgeIface); err != nil {
|
if err := netlink.AddRoute(config.FixedCIDRv6, "", "", bridgeIface); err != nil {
|
||||||
logrus.Fatalf("Could not add route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
|
logrus.Fatalf("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Bridge exists already, getting info...
|
// Bridge exists already, getting info...
|
||||||
// Validate that the bridge ip matches the ip specified by BridgeIP
|
// Validate that the bridge ip matches the ip specified by BridgeIP
|
||||||
if bridgeIP != "" {
|
if config.IP != "" {
|
||||||
networkv4 = addrv4.(*net.IPNet)
|
networkv4 = addrv4.(*net.IPNet)
|
||||||
bip, _, err := net.ParseCIDR(bridgeIP)
|
bip, _, err := net.ParseCIDR(config.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -164,7 +170,7 @@ func InitDriver(job *engine.Job) error {
|
||||||
// (for example, an existing Docker installation that has only been used
|
// (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
|
// 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
|
// 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 {
|
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
|
||||||
return err
|
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)
|
bip6, _, err := net.ParseCIDR(bridgeIPv6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -198,7 +204,7 @@ func InitDriver(job *engine.Job) error {
|
||||||
|
|
||||||
networkv4 = addrv4.(*net.IPNet)
|
networkv4 = addrv4.(*net.IPNet)
|
||||||
|
|
||||||
if enableIPv6 {
|
if config.EnableIPv6 {
|
||||||
if len(addrsv6) == 0 {
|
if len(addrsv6) == 0 {
|
||||||
return errors.New("IPv6 enabled but no IPv6 detected")
|
return errors.New("IPv6 enabled but no IPv6 detected")
|
||||||
}
|
}
|
||||||
|
@ -206,20 +212,20 @@ func InitDriver(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure iptables for link support
|
// Configure iptables for link support
|
||||||
if enableIPTables {
|
if config.EnableIptables {
|
||||||
if err := setupIPTables(addrv4, icc, ipMasq); err != nil {
|
if err := setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ipForward {
|
if config.EnableIpForward {
|
||||||
// Enable IPv4 forwarding
|
// Enable IPv4 forwarding
|
||||||
if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
|
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)
|
logrus.Warnf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fixedCIDRv6 != "" {
|
if config.FixedCIDRv6 != "" {
|
||||||
// Enable IPv6 forwarding
|
// Enable IPv6 forwarding
|
||||||
if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
|
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)
|
logrus.Warnf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
|
||||||
|
@ -235,7 +241,7 @@ func InitDriver(job *engine.Job) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if enableIPTables {
|
if config.EnableIptables {
|
||||||
_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
|
_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -248,8 +254,8 @@ func InitDriver(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
bridgeIPv4Network = networkv4
|
bridgeIPv4Network = networkv4
|
||||||
if fixedCIDR != "" {
|
if config.FixedCIDR != "" {
|
||||||
_, subnet, err := net.ParseCIDR(fixedCIDR)
|
_, subnet, err := net.ParseCIDR(config.FixedCIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -259,8 +265,8 @@ func InitDriver(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fixedCIDRv6 != "" {
|
if config.FixedCIDRv6 != "" {
|
||||||
_, subnet, err := net.ParseCIDR(fixedCIDRv6)
|
_, subnet, err := net.ParseCIDR(config.FixedCIDRv6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -274,19 +280,6 @@ func InitDriver(job *engine.Job) error {
|
||||||
// Block BridgeIP in IP allocator
|
// Block BridgeIP in IP allocator
|
||||||
ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,70 +506,67 @@ func linkLocalIPv6FromMac(mac string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a network interface
|
// Allocate a network interface
|
||||||
func Allocate(job *engine.Job) error {
|
func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Settings, error) {
|
||||||
var (
|
var (
|
||||||
ip net.IP
|
ip net.IP
|
||||||
mac net.HardwareAddr
|
mac net.HardwareAddr
|
||||||
err error
|
err error
|
||||||
id = job.Args[0]
|
globalIPv6 net.IP
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no explicit mac address was given, generate a random one.
|
// 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)
|
mac = generateMacAddr(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if globalIPv6Network != nil {
|
if globalIPv6Network != nil {
|
||||||
// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
|
// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
|
||||||
netmaskOnes, _ := globalIPv6Network.Mask.Size()
|
netmaskOnes, _ := globalIPv6Network.Mask.Size()
|
||||||
if requestedIPv6 == nil && netmaskOnes <= 80 {
|
ipv6 := net.ParseIP(requestedIPv6)
|
||||||
requestedIPv6 = make(net.IP, len(globalIPv6Network.IP))
|
if ipv6 == nil && netmaskOnes <= 80 {
|
||||||
copy(requestedIPv6, globalIPv6Network.IP)
|
ipv6 = make(net.IP, len(globalIPv6Network.IP))
|
||||||
|
copy(ipv6, globalIPv6Network.IP)
|
||||||
for i, h := range mac {
|
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 {
|
if err != nil {
|
||||||
logrus.Errorf("Allocator: RequestIP v6: %v", err)
|
logrus.Errorf("Allocator: RequestIP v6: %v", err)
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
logrus.Infof("Allocated IPv6 %s", globalIPv6)
|
logrus.Infof("Allocated IPv6 %s", globalIPv6)
|
||||||
}
|
}
|
||||||
|
|
||||||
out := engine.Env{}
|
maskSize, _ := bridgeIPv4Network.Mask.Size()
|
||||||
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)
|
|
||||||
|
|
||||||
// If linklocal IPv6
|
// If linklocal IPv6
|
||||||
localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
|
localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
|
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 {
|
if globalIPv6Network != nil {
|
||||||
out.Set("GlobalIPv6", globalIPv6.String())
|
networkSettings.GlobalIPv6Address = globalIPv6.String()
|
||||||
sizev6, _ := globalIPv6Network.Mask.Size()
|
maskV6Size, _ := globalIPv6Network.Mask.Size()
|
||||||
out.SetInt("GlobalIPv6PrefixLen", sizev6)
|
networkSettings.GlobalIPv6PrefixLen = maskV6Size
|
||||||
out.Set("IPv6Gateway", bridgeIPv6Addr.String())
|
networkSettings.IPv6Gateway = bridgeIPv6Addr.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
currentInterfaces.Set(id, &networkInterface{
|
currentInterfaces.Set(id, &networkInterface{
|
||||||
|
@ -584,20 +574,15 @@ func Allocate(job *engine.Job) error {
|
||||||
IPv6: globalIPv6,
|
IPv6: globalIPv6,
|
||||||
})
|
})
|
||||||
|
|
||||||
out.WriteTo(job.Stdout)
|
return networkSettings, nil
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release an interface for a select ip
|
// Release an interface for a select ip
|
||||||
func Release(job *engine.Job) error {
|
func Release(id string) {
|
||||||
var (
|
var containerInterface = currentInterfaces.Get(id)
|
||||||
id = job.Args[0]
|
|
||||||
containerInterface = currentInterfaces.Get(id)
|
|
||||||
)
|
|
||||||
|
|
||||||
if containerInterface == nil {
|
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 {
|
for _, nat := range containerInterface.PortMappings {
|
||||||
|
@ -614,27 +599,21 @@ func Release(job *engine.Job) error {
|
||||||
logrus.Infof("Unable to release IPv6 %s", err)
|
logrus.Infof("Unable to release IPv6 %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate an external port and map it to the interface
|
// 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 (
|
var (
|
||||||
err error
|
|
||||||
|
|
||||||
ip = defaultBindingIP
|
ip = defaultBindingIP
|
||||||
id = job.Args[0]
|
proto = port.Proto()
|
||||||
hostIP = job.Getenv("HostIP")
|
containerPort = port.Int()
|
||||||
hostPort = job.GetenvInt("HostPort")
|
|
||||||
containerPort = job.GetenvInt("ContainerPort")
|
|
||||||
proto = job.Getenv("Proto")
|
|
||||||
network = currentInterfaces.Get(id)
|
network = currentInterfaces.Get(id)
|
||||||
)
|
)
|
||||||
|
|
||||||
if hostIP != "" {
|
if binding.HostIp != "" {
|
||||||
ip = net.ParseIP(hostIP)
|
ip = net.ParseIP(binding.HostIp)
|
||||||
if ip == nil {
|
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":
|
case "udp":
|
||||||
container = &net.UDPAddr{IP: network.IP, Port: containerPort}
|
container = &net.UDPAddr{IP: network.IP, Port: containerPort}
|
||||||
default:
|
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.
|
// 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++ {
|
for i := 0; i < MaxAllocatedPortAttempts; i++ {
|
||||||
if host, err = portMapper.Map(container, ip, hostPort); err == nil {
|
if host, err = portMapper.Map(container, ip, hostPort); err == nil {
|
||||||
break
|
break
|
||||||
|
@ -671,36 +657,24 @@ func AllocatePort(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nat.PortBinding{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
network.PortMappings = append(network.PortMappings, host)
|
network.PortMappings = append(network.PortMappings, host)
|
||||||
|
|
||||||
out := engine.Env{}
|
|
||||||
switch netAddr := host.(type) {
|
switch netAddr := host.(type) {
|
||||||
case *net.TCPAddr:
|
case *net.TCPAddr:
|
||||||
out.Set("HostIP", netAddr.IP.String())
|
return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
|
||||||
out.SetInt("HostPort", netAddr.Port)
|
|
||||||
case *net.UDPAddr:
|
case *net.UDPAddr:
|
||||||
out.Set("HostIP", netAddr.IP.String())
|
return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
|
||||||
out.SetInt("HostPort", netAddr.Port)
|
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 {
|
//TODO: should it return something more than just an error?
|
||||||
var (
|
func LinkContainers(action, parentIP, childIP string, ports []nat.Port, ignoreErrors bool) error {
|
||||||
action = job.Args[0]
|
var nfAction iptables.Action
|
||||||
nfAction iptables.Action
|
|
||||||
childIP = job.Getenv("ChildIP")
|
|
||||||
parentIP = job.Getenv("ParentIP")
|
|
||||||
ignoreErrors = job.GetenvBool("IgnoreErrors")
|
|
||||||
ports = job.GetenvList("Ports")
|
|
||||||
)
|
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case "-A":
|
case "-A":
|
||||||
|
@ -723,8 +697,7 @@ func LinkContainers(job *engine.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
|
chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
|
||||||
for _, p := range ports {
|
for _, port := range ports {
|
||||||
port := nat.Port(p)
|
|
||||||
if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
|
if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/daemon/network"
|
||||||
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
"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/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ func init() {
|
||||||
portmapper.NewProxy = portmapper.NewMockProxyCommand
|
portmapper.NewProxy = portmapper.NewMockProxyCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func findFreePort(t *testing.T) int {
|
func findFreePort(t *testing.T) string {
|
||||||
l, err := net.Listen("tcp", ":0")
|
l, err := net.Listen("tcp", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Failed to find a free port")
|
t.Fatal("Failed to find a free port")
|
||||||
|
@ -27,143 +28,85 @@ func findFreePort(t *testing.T) int {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Failed to resolve address to identify free port")
|
t.Fatal("Failed to resolve address to identify free port")
|
||||||
}
|
}
|
||||||
return result.Port
|
return strconv.Itoa(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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAllocatePortDetection(t *testing.T) {
|
func TestAllocatePortDetection(t *testing.T) {
|
||||||
eng := engine.New()
|
|
||||||
eng.Logging = false
|
|
||||||
|
|
||||||
freePort := findFreePort(t)
|
freePort := findFreePort(t)
|
||||||
|
|
||||||
// Init driver
|
if err := InitDriver(new(Config)); err != nil {
|
||||||
job := eng.Job("initdriver")
|
|
||||||
if res := InitDriver(job); res != nil {
|
|
||||||
t.Fatal("Failed to initialize network driver")
|
t.Fatal("Failed to initialize network driver")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate interface
|
// Allocate interface
|
||||||
job = eng.Job("allocate_interface", "container_id")
|
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||||
if res := Allocate(job); res != nil {
|
|
||||||
t.Fatal("Failed to allocate network interface")
|
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
|
// Allocate same port twice, expect failure on second call
|
||||||
job = newPortAllocationJob(eng, freePort)
|
if _, err := AllocatePort("container_id", port, binding); err != nil {
|
||||||
if res := AllocatePort(job); res != nil {
|
|
||||||
t.Fatal("Failed to find a free port to allocate")
|
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")
|
t.Fatal("Duplicate port allocation granted by AllocatePort")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHostnameFormatChecking(t *testing.T) {
|
func TestHostnameFormatChecking(t *testing.T) {
|
||||||
eng := engine.New()
|
|
||||||
eng.Logging = false
|
|
||||||
|
|
||||||
freePort := findFreePort(t)
|
freePort := findFreePort(t)
|
||||||
|
|
||||||
// Init driver
|
if err := InitDriver(new(Config)); err != nil {
|
||||||
job := eng.Job("initdriver")
|
|
||||||
if res := InitDriver(job); res != nil {
|
|
||||||
t.Fatal("Failed to initialize network driver")
|
t.Fatal("Failed to initialize network driver")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate interface
|
// Allocate interface
|
||||||
job = eng.Job("allocate_interface", "container_id")
|
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||||
if res := Allocate(job); res != nil {
|
|
||||||
t.Fatal("Failed to allocate network interface")
|
t.Fatal("Failed to allocate network interface")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate port with invalid HostIP, expect failure with Bad Request http status
|
port := nat.Port(freePort + "/tcp")
|
||||||
job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
|
binding := nat.PortBinding{HostIp: "localhost", HostPort: freePort}
|
||||||
if res := AllocatePort(job); res == nil {
|
|
||||||
|
if _, err := AllocatePort("container_id", port, binding); err == nil {
|
||||||
t.Fatal("Failed to check invalid HostIP")
|
t.Fatal("Failed to check invalid HostIP")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInterfaceAllocation(t *testing.T, input engine.Env) (output engine.Env) {
|
func newInterfaceAllocation(t *testing.T, globalIPv6 *net.IPNet, requestedMac, requestedIP, requestedIPv6 string, expectFail bool) *network.Settings {
|
||||||
eng := engine.New()
|
|
||||||
eng.Logging = false
|
|
||||||
|
|
||||||
done := make(chan bool)
|
|
||||||
|
|
||||||
// set IPv6 global if given
|
// set IPv6 global if given
|
||||||
if input.Exists("globalIPv6Network") {
|
if globalIPv6 != nil {
|
||||||
_, globalIPv6Network, _ = net.ParseCIDR(input.Get("globalIPv6Network"))
|
globalIPv6Network = globalIPv6
|
||||||
}
|
}
|
||||||
|
|
||||||
job := eng.Job("allocate_interface", "container_id")
|
networkSettings, err := Allocate("container_id", requestedMac, requestedIP, requestedIPv6)
|
||||||
job.Env().Init(&input)
|
if err == nil && expectFail {
|
||||||
reader, _ := job.Stdout.AddPipe()
|
t.Fatal("Doesn't fail to allocate network interface")
|
||||||
go func() {
|
} else if err != nil && !expectFail {
|
||||||
output.Decode(reader)
|
t.Fatal("Failed to allocate network interface")
|
||||||
done <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
res := Allocate(job)
|
|
||||||
job.Stdout.Close()
|
|
||||||
<-done
|
|
||||||
|
|
||||||
if input.Exists("expectFail") && input.GetBool("expectFail") {
|
|
||||||
if res == nil {
|
|
||||||
t.Fatal("Doesn't fail to allocate network interface")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if res != nil {
|
|
||||||
t.Fatal("Failed to allocate network interface")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.Exists("globalIPv6Network") {
|
if globalIPv6 != nil {
|
||||||
// check for bug #11427
|
// check for bug #11427
|
||||||
_, subnet, _ := net.ParseCIDR(input.Get("globalIPv6Network"))
|
if globalIPv6Network.IP.String() != globalIPv6.IP.String() {
|
||||||
if globalIPv6Network.IP.String() != subnet.IP.String() {
|
|
||||||
t.Fatal("globalIPv6Network was modified during allocation")
|
t.Fatal("globalIPv6Network was modified during allocation")
|
||||||
}
|
}
|
||||||
// clean up IPv6 global
|
// clean up IPv6 global
|
||||||
globalIPv6Network = nil
|
globalIPv6Network = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return networkSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
|
func TestIPv6InterfaceAllocationAutoNetmaskGt80(t *testing.T) {
|
||||||
|
|
||||||
input := engine.Env{}
|
|
||||||
|
|
||||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81")
|
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/81")
|
||||||
|
networkSettings := newInterfaceAllocation(t, subnet, "", "", "", false)
|
||||||
// set global ipv6
|
|
||||||
input.Set("globalIPv6Network", subnet.String())
|
|
||||||
|
|
||||||
output := newInterfaceAllocation(t, input)
|
|
||||||
|
|
||||||
// ensure low manually assigend global ip
|
// 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))
|
_, subnet, _ = net.ParseCIDR(fmt.Sprintf("%s/%d", subnet.IP.String(), 120))
|
||||||
if !subnet.Contains(ip) {
|
if !subnet.Contains(ip) {
|
||||||
t.Fatalf("Error ip %s not in subnet %s", ip.String(), subnet.String())
|
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) {
|
func TestIPv6InterfaceAllocationAutoNetmaskLe80(t *testing.T) {
|
||||||
|
|
||||||
input := engine.Env{}
|
|
||||||
|
|
||||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
|
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
|
||||||
|
networkSettings := newInterfaceAllocation(t, subnet, "ab:cd:ab:cd:ab:cd", "", "", false)
|
||||||
// set global ipv6
|
|
||||||
input.Set("globalIPv6Network", subnet.String())
|
|
||||||
input.Set("RequestedMac", "ab:cd:ab:cd:ab:cd")
|
|
||||||
|
|
||||||
output := newInterfaceAllocation(t, input)
|
|
||||||
|
|
||||||
// ensure global ip with mac
|
// 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")
|
expectedIP := net.ParseIP("2001:db8:1234:1234:1234:abcd:abcd:abcd")
|
||||||
if ip.String() != expectedIP.String() {
|
if ip.String() != expectedIP.String() {
|
||||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure link local format
|
// ensure link local format
|
||||||
ip = net.ParseIP(output.Get("LinkLocalIPv6"))
|
ip = net.ParseIP(networkSettings.LinkLocalIPv6Address)
|
||||||
expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd")
|
expectedIP = net.ParseIP("fe80::a9cd:abff:fecd:abcd")
|
||||||
if ip.String() != expectedIP.String() {
|
if ip.String() != expectedIP.String() {
|
||||||
t.Fatalf("Error ip %s should be %s", 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) {
|
func TestIPv6InterfaceAllocationRequest(t *testing.T) {
|
||||||
|
|
||||||
input := engine.Env{}
|
|
||||||
|
|
||||||
_, subnet, _ := net.ParseCIDR("2001:db8:1234:1234:1234::/80")
|
_, 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
|
networkSettings := newInterfaceAllocation(t, subnet, "", "", expectedIP, false)
|
||||||
input.Set("globalIPv6Network", subnet.String())
|
|
||||||
input.Set("RequestedIPv6", expectedIP.String())
|
|
||||||
|
|
||||||
output := newInterfaceAllocation(t, input)
|
|
||||||
|
|
||||||
// ensure global ip with mac
|
// ensure global ip with mac
|
||||||
ip := net.ParseIP(output.Get("GlobalIPv6"))
|
ip := net.ParseIP(networkSettings.GlobalIPv6Address)
|
||||||
if ip.String() != expectedIP.String() {
|
if ip.String() != expectedIP {
|
||||||
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP.String())
|
t.Fatalf("Error ip %s should be %s", ip.String(), expectedIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// retry -> fails for duplicated address
|
// retry -> fails for duplicated address
|
||||||
input.SetBool("expectFail", true)
|
_ = newInterfaceAllocation(t, subnet, "", "", expectedIP, true)
|
||||||
output = newInterfaceAllocation(t, input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMacAddrGeneration(t *testing.T) {
|
func TestMacAddrGeneration(t *testing.T) {
|
||||||
|
@ -239,40 +166,27 @@ func TestMacAddrGeneration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkContainers(t *testing.T) {
|
func TestLinkContainers(t *testing.T) {
|
||||||
eng := engine.New()
|
|
||||||
eng.Logging = false
|
|
||||||
|
|
||||||
// Init driver
|
// Init driver
|
||||||
job := eng.Job("initdriver")
|
if err := InitDriver(new(Config)); err != nil {
|
||||||
if res := InitDriver(job); res != nil {
|
|
||||||
t.Fatal("Failed to initialize network driver")
|
t.Fatal("Failed to initialize network driver")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate interface
|
// Allocate interface
|
||||||
job = eng.Job("allocate_interface", "container_id")
|
if _, err := Allocate("container_id", "", "", ""); err != nil {
|
||||||
if res := Allocate(job); res != nil {
|
|
||||||
t.Fatal("Failed to allocate network interface")
|
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"
|
bridgeIface = "lo"
|
||||||
_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
|
if _, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res := LinkContainers(job); res != nil {
|
if err := LinkContainers("-I", "172.17.0.1", "172.17.0.2", []nat.Port{nat.Port("1234")}, false); err != nil {
|
||||||
t.Fatalf("LinkContainers failed")
|
t.Fatal("LinkContainers failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush rules
|
// flush rules
|
||||||
if _, err = iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
|
if _, err := iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/builtins"
|
"github.com/docker/docker/builtins"
|
||||||
"github.com/docker/docker/daemon"
|
"github.com/docker/docker/daemon"
|
||||||
|
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||||
"github.com/docker/docker/engine"
|
"github.com/docker/docker/engine"
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
flag "github.com/docker/docker/pkg/mflag"
|
||||||
"github.com/docker/docker/registry"
|
"github.com/docker/docker/registry"
|
||||||
|
@ -185,9 +186,11 @@ func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine {
|
||||||
ExecDriver: "native",
|
ExecDriver: "native",
|
||||||
// Either InterContainerCommunication or EnableIptables must be set,
|
// Either InterContainerCommunication or EnableIptables must be set,
|
||||||
// otherwise NewDaemon will fail because of conflicting settings.
|
// otherwise NewDaemon will fail because of conflicting settings.
|
||||||
InterContainerCommunication: true,
|
Bridge: bridge.Config{
|
||||||
TrustKeyPath: filepath.Join(root, "key.json"),
|
InterContainerCommunication: true,
|
||||||
LogConfig: runconfig.LogConfig{Type: "json-file"},
|
},
|
||||||
|
TrustKeyPath: filepath.Join(root, "key.json"),
|
||||||
|
LogConfig: runconfig.LogConfig{Type: "json-file"},
|
||||||
}
|
}
|
||||||
d, err := daemon.NewDaemon(cfg, eng, registry.NewService(nil))
|
d, err := daemon.NewDaemon(cfg, eng, registry.NewService(nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,10 +2,12 @@ package links
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/docker/docker/engine"
|
|
||||||
"github.com/docker/docker/nat"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/daemon/networkdriver/bridge"
|
||||||
|
"github.com/docker/docker/engine"
|
||||||
|
"github.com/docker/docker/nat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Link struct {
|
type Link struct {
|
||||||
|
@ -158,21 +160,5 @@ func (l *Link) Disable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Link) toggle(action string, ignoreErrors bool) error {
|
func (l *Link) toggle(action string, ignoreErrors bool) error {
|
||||||
job := l.eng.Job("link", action)
|
return bridge.LinkContainers(action, l.ParentIP, l.ChildIP, l.Ports, ignoreErrors)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ func NewPort(proto, port string) Port {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParsePort(rawPort string) (int, error) {
|
func ParsePort(rawPort string) (int, error) {
|
||||||
|
if len(rawPort) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
port, err := strconv.ParseUint(rawPort, 10, 16)
|
port, err := strconv.ParseUint(rawPort, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue