diff --git a/config.go b/config.go index cb7e985ca2..5b8b4c2499 100644 --- a/config.go +++ b/config.go @@ -5,6 +5,11 @@ import ( "net" ) +const ( + DefaultNetworkMtu = 1500 + DisableNetworkBridge = "none" +) + // FIXME: separate runtime configuration from http api configuration type DaemonConfig struct { Pidfile string @@ -13,12 +18,13 @@ type DaemonConfig struct { Dns []string EnableIptables bool EnableIpForward bool - BridgeIface string - BridgeIp string DefaultIp net.IP + BridgeIface string + BridgeIP string InterContainerCommunication bool GraphDriver string Mtu int + DisableNetwork bool } // ConfigFromJob creates and returns a new DaemonConfig object @@ -30,7 +36,7 @@ func DaemonConfigFromJob(job *engine.Job) *DaemonConfig { AutoRestart: job.GetenvBool("AutoRestart"), EnableIptables: job.GetenvBool("EnableIptables"), EnableIpForward: job.GetenvBool("EnableIpForward"), - BridgeIp: job.Getenv("BridgeIp"), + BridgeIP: job.Getenv("BridgeIp"), DefaultIp: net.ParseIP(job.Getenv("DefaultIp")), InterContainerCommunication: job.GetenvBool("InterContainerCommunication"), GraphDriver: job.Getenv("GraphDriver"), @@ -38,16 +44,12 @@ func DaemonConfigFromJob(job *engine.Job) *DaemonConfig { if dns := job.GetenvList("Dns"); dns != nil { config.Dns = dns } - if br := job.Getenv("BridgeIface"); br != "" { - config.BridgeIface = br - } else { - config.BridgeIface = DefaultNetworkBridge - } if mtu := job.GetenvInt("Mtu"); mtu != 0 { config.Mtu = mtu } else { config.Mtu = DefaultNetworkMtu } + config.DisableNetwork = job.Getenv("BridgeIface") == DisableNetworkBridge return config } diff --git a/container.go b/container.go index c90930a346..0e7fd257af 100644 --- a/container.go +++ b/container.go @@ -8,7 +8,6 @@ import ( "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/graphdriver" - "github.com/dotcloud/docker/networkdriver/ipallocator" "github.com/dotcloud/docker/pkg/mount" "github.com/dotcloud/docker/pkg/term" "github.com/dotcloud/docker/utils" @@ -16,7 +15,6 @@ import ( "io" "io/ioutil" "log" - "net" "os" "path" "path/filepath" @@ -47,7 +45,6 @@ type Container struct { State State Image string - network *NetworkInterface NetworkSettings *NetworkSettings ResolvConfPath string @@ -558,6 +555,7 @@ func populateCommand(c *Container) { en *execdriver.Network driverConfig []string ) + if !c.Config.NetworkDisabled { network := c.NetworkSettings en = &execdriver.Network{ @@ -603,15 +601,18 @@ func (container *Container) Start() (err error) { if container.State.IsRunning() { return fmt.Errorf("The container %s is already running.", container.ID) } + defer func() { if err != nil { container.cleanup() } }() + if err := container.Mount(); err != nil { return err } - if container.runtime.networkManager.disabled { + + if container.runtime.config.DisableNetwork { container.Config.NetworkDisabled = true container.buildHostnameAndHostsFiles("127.0.1.1") } else { @@ -669,34 +670,39 @@ func (container *Container) Start() (err error) { } if len(children) > 0 { - container.activeLinks = make(map[string]*Link, len(children)) + panic("todo crosbymichael") + /* + linking is specific to iptables and the bridge we need to move this to a job - // If we encounter an error make sure that we rollback any network - // config and ip table changes - rollback := func() { - for _, link := range container.activeLinks { - link.Disable() - } - container.activeLinks = nil - } + container.activeLinks = make(map[string]*Link, len(children)) - for p, child := range children { - link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface) - if err != nil { - rollback() - return err - } + // If we encounter an error make sure that we rollback any network + // config and ip table changes + rollback := func() { + for _, link := range container.activeLinks { + link.Disable() + } + container.activeLinks = nil + } - container.activeLinks[link.Alias()] = link - if err := link.Enable(); err != nil { - rollback() - return err - } + for p, child := range children { + link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface) + if err != nil { + rollback() + return err + } - for _, envVar := range link.ToEnv() { - env = append(env, envVar) - } - } + container.activeLinks[link.Alias()] = link + if err := link.Enable(); err != nil { + rollback() + return err + } + + for _, envVar := range link.ToEnv() { + env = append(env, envVar) + } + } + */ } for _, elem := range container.Config.Env { @@ -1102,34 +1108,44 @@ func (container *Container) allocateNetwork() error { } var ( - iface *NetworkInterface - err error + env *engine.Env + eng = container.runtime.srv.Eng ) if container.State.IsGhost() { - if manager := container.runtime.networkManager; manager.disabled { - iface = &NetworkInterface{disabled: true} + if container.runtime.config.DisableNetwork { + env = &engine.Env{} } else { - iface = &NetworkInterface{ - IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask}, - Gateway: manager.bridgeNetwork.IP, - manager: manager, - } - if iface != nil && iface.IPNet.IP != nil { - if _, err := ipallocator.RequestIP(manager.bridgeNetwork, &iface.IPNet.IP); err != nil { - return err + // TODO: @crosbymichael + panic("not implemented") + /* + iface = &NetworkInterface{ + IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask}, + Gateway: manager.bridgeNetwork.IP, } - } else { - iface, err = container.runtime.networkManager.Allocate() - if err != nil { - return err + + // request an existing ip + if iface != nil && iface.IPNet.IP != nil { + if _, err := ipallocator.RequestIP(manager.bridgeNetwork, &iface.IPNet.IP); err != nil { + return err + } + } else { + job = eng.Job("allocate_interface", container.ID) + if err := job.Run(); err != nil { + return err + } } - } + */ } } else { - iface, err = container.runtime.networkManager.Allocate() + job := eng.Job("allocate_interface", container.ID) + var err error + env, err = job.Stdout.AddEnv() if err != nil { return err } + if err := job.Run(); err != nil { + return err + } } if container.Config.PortSpecs != nil { @@ -1171,37 +1187,43 @@ func (container *Container) allocateNetwork() error { if container.hostConfig.PublishAllPorts && len(binding) == 0 { binding = append(binding, PortBinding{}) } + for i := 0; i < len(binding); i++ { b := binding[i] - nat, err := iface.AllocatePort(port, b) - if err != nil { - iface.Release() + + portJob := eng.Job("allocate_port", container.ID) + portJob.Setenv("HostIP", b.HostIp) + portJob.Setenv("HostPort", b.HostPort) + portJob.Setenv("Proto", port.Proto()) + portJob.Setenv("ContainerPort", port.Port()) + + if err := portJob.Run(); err != nil { + eng.Job("release_interface", container.ID).Run() return err } - utils.Debugf("Allocate port: %s:%s->%s", nat.Binding.HostIp, port, nat.Binding.HostPort) - binding[i] = nat.Binding } bindings[port] = binding } container.writeHostConfig() container.NetworkSettings.Ports = bindings - container.network = iface - container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface - container.NetworkSettings.IPAddress = iface.IPNet.IP.String() - container.NetworkSettings.IPPrefixLen, _ = iface.IPNet.Mask.Size() - container.NetworkSettings.Gateway = iface.Gateway.String() + container.NetworkSettings.Bridge = env.Get("Bridge") + container.NetworkSettings.IPAddress = env.Get("IP") + container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen") + container.NetworkSettings.Gateway = env.Get("Gateway") + fmt.Printf("\n-----> %#v\n", container.NetworkSettings) return nil } func (container *Container) releaseNetwork() { - if container.Config.NetworkDisabled || container.network == nil { + if container.Config.NetworkDisabled { return } - container.network.Release() - container.network = nil + eng := container.runtime.srv.Eng + + eng.Job("release_interface", container.ID).Run() container.NetworkSettings = &NetworkSettings{} } diff --git a/networkdriver/lxc/driver.go b/networkdriver/lxc/driver.go index be99d32338..542b4b8504 100644 --- a/networkdriver/lxc/driver.go +++ b/networkdriver/lxc/driver.go @@ -19,8 +19,6 @@ import ( const ( DefaultNetworkBridge = "docker0" - DisableNetworkBridge = "none" - DefaultNetworkMtu = 1500 siocBRADDBR = 0x89a0 ) @@ -70,17 +68,24 @@ func InitDriver(job *engine.Job) engine.Status { enableIPTables = job.GetenvBool("EnableIptables") icc = job.GetenvBool("InterContainerCommunication") ipForward = job.GetenvBool("EnableIpForward") + bridgeIP = job.Getenv("BridgeIP") ) + bridgeIface = job.Getenv("BridgeIface") + if bridgeIface == "" { + bridgeIface = DefaultNetworkBridge + } addr, err := networkdriver.GetIfaceAddr(bridgeIface) if err != nil { // If the iface is not found, try to create it - if err := createBridgeIface(bridgeIface); err != nil { + job.Logf("creating new bridge for %s", bridgeIface) + if err := createBridge(bridgeIP); err != nil { job.Error(err) return engine.StatusErr } + job.Logf("getting iface addr") addr, err = networkdriver.GetIfaceAddr(bridgeIface) if err != nil { job.Error(err) @@ -122,9 +127,14 @@ func InitDriver(job *engine.Job) engine.Status { } bridgeNetwork = network + + // https://github.com/dotcloud/docker/issues/2768 + job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeNetwork.IP) + for name, f := range map[string]engine.Handler{ "allocate_interface": Allocate, "release_interface": Release, + "allocate_port": AllocatePort, } { if err := job.Eng.Register(name, f); err != nil { job.Error(err) @@ -304,6 +314,10 @@ func Allocate(job *engine.Job) engine.Status { out.Set("IP", string(*ip)) out.Set("Mask", string(bridgeNetwork.Mask)) out.Set("Gateway", string(bridgeNetwork.IP)) + out.Set("Bridge", bridgeIface) + + size, _ := bridgeNetwork.Mask.Size() + out.SetInt("IPPrefixLen", size) currentInterfaces[id] = &networkInterface{ IP: *ip, diff --git a/runtime.go b/runtime.go index e9e6802606..475e32ed5f 100644 --- a/runtime.go +++ b/runtime.go @@ -4,6 +4,7 @@ import ( "container/list" "fmt" "github.com/dotcloud/docker/archive" + "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/execdriver/chroot" "github.com/dotcloud/docker/execdriver/lxc" @@ -12,6 +13,7 @@ import ( _ "github.com/dotcloud/docker/graphdriver/btrfs" _ "github.com/dotcloud/docker/graphdriver/devmapper" _ "github.com/dotcloud/docker/graphdriver/vfs" + _ "github.com/dotcloud/docker/networkdriver/lxc" "github.com/dotcloud/docker/networkdriver/portallocator" "github.com/dotcloud/docker/pkg/graphdb" "github.com/dotcloud/docker/pkg/sysinfo" @@ -42,7 +44,6 @@ type Runtime struct { repository string sysInitPath string containers *list.List - networkManager *NetworkManager graph *Graph repositories *TagStore idIndex *utils.TruncIndex @@ -609,15 +610,15 @@ func (runtime *Runtime) RegisterLink(parent, child *Container, alias string) err } // FIXME: harmonize with NewGraph() -func NewRuntime(config *DaemonConfig) (*Runtime, error) { - runtime, err := NewRuntimeFromDirectory(config) +func NewRuntime(config *DaemonConfig, eng *engine.Engine) (*Runtime, error) { + runtime, err := NewRuntimeFromDirectory(config, eng) if err != nil { return nil, err } return runtime, nil } -func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { +func NewRuntimeFromDirectory(config *DaemonConfig, eng *engine.Engine) (*Runtime, error) { // Set the default driver graphdriver.DefaultDriver = config.GraphDriver @@ -664,12 +665,19 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { if err != nil { return nil, fmt.Errorf("Couldn't create Tag store: %s", err) } - if config.BridgeIface == "" { - config.BridgeIface = DefaultNetworkBridge - } - netManager, err := newNetworkManager(config) - if err != nil { - return nil, err + + if !config.DisableNetwork { + job := eng.Job("init_networkdriver") + + job.SetenvBool("EnableIptables", config.EnableIptables) + job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication) + job.SetenvBool("EnableIpForward", config.EnableIpForward) + job.Setenv("BridgeIface", config.BridgeIface) + job.Setenv("BridgeIP", config.BridgeIP) + + if err := job.Run(); err != nil { + return nil, err + } } graphdbPath := path.Join(config.Root, "linkgraph.db") @@ -721,7 +729,6 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { runtime := &Runtime{ repository: runtimeRepo, containers: list.New(), - networkManager: netManager, graph: g, repositories: repositories, idIndex: utils.NewTruncIndex(), diff --git a/server.go b/server.go index d037212ce3..9d38c1486e 100644 --- a/server.go +++ b/server.go @@ -65,10 +65,7 @@ func jobInitApi(job *engine.Job) engine.Status { }() job.Eng.Hack_SetGlobalVar("httpapi.server", srv) job.Eng.Hack_SetGlobalVar("httpapi.runtime", srv.runtime) - // https://github.com/dotcloud/docker/issues/2768 - if srv.runtime.networkManager.bridgeNetwork != nil { - job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", srv.runtime.networkManager.bridgeNetwork.IP) - } + for name, handler := range map[string]engine.Handler{ "export": srv.ContainerExport, "create": srv.ContainerCreate, @@ -2354,7 +2351,7 @@ func (srv *Server) ContainerCopy(job *engine.Job) engine.Status { } func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) { - runtime, err := NewRuntime(config) + runtime, err := NewRuntime(config, eng) if err != nil { return nil, err }