Update core calls to network drivers

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-01-29 18:34:43 -08:00
parent 90494600d3
commit c712e74b45
5 changed files with 128 additions and 86 deletions

View File

@ -5,6 +5,11 @@ import (
"net" "net"
) )
const (
DefaultNetworkMtu = 1500
DisableNetworkBridge = "none"
)
// FIXME: separate runtime configuration from http api configuration // FIXME: separate runtime configuration from http api configuration
type DaemonConfig struct { type DaemonConfig struct {
Pidfile string Pidfile string
@ -13,12 +18,13 @@ type DaemonConfig struct {
Dns []string Dns []string
EnableIptables bool EnableIptables bool
EnableIpForward bool EnableIpForward bool
BridgeIface string
BridgeIp string
DefaultIp net.IP DefaultIp net.IP
BridgeIface string
BridgeIP string
InterContainerCommunication bool InterContainerCommunication bool
GraphDriver string GraphDriver string
Mtu int Mtu int
DisableNetwork bool
} }
// ConfigFromJob creates and returns a new DaemonConfig object // ConfigFromJob creates and returns a new DaemonConfig object
@ -30,7 +36,7 @@ func DaemonConfigFromJob(job *engine.Job) *DaemonConfig {
AutoRestart: job.GetenvBool("AutoRestart"), AutoRestart: job.GetenvBool("AutoRestart"),
EnableIptables: job.GetenvBool("EnableIptables"), EnableIptables: job.GetenvBool("EnableIptables"),
EnableIpForward: job.GetenvBool("EnableIpForward"), EnableIpForward: job.GetenvBool("EnableIpForward"),
BridgeIp: job.Getenv("BridgeIp"), BridgeIP: job.Getenv("BridgeIp"),
DefaultIp: net.ParseIP(job.Getenv("DefaultIp")), DefaultIp: net.ParseIP(job.Getenv("DefaultIp")),
InterContainerCommunication: job.GetenvBool("InterContainerCommunication"), InterContainerCommunication: job.GetenvBool("InterContainerCommunication"),
GraphDriver: job.Getenv("GraphDriver"), GraphDriver: job.Getenv("GraphDriver"),
@ -38,16 +44,12 @@ func DaemonConfigFromJob(job *engine.Job) *DaemonConfig {
if dns := job.GetenvList("Dns"); dns != nil { if dns := job.GetenvList("Dns"); dns != nil {
config.Dns = dns config.Dns = dns
} }
if br := job.Getenv("BridgeIface"); br != "" {
config.BridgeIface = br
} else {
config.BridgeIface = DefaultNetworkBridge
}
if mtu := job.GetenvInt("Mtu"); mtu != 0 { if mtu := job.GetenvInt("Mtu"); mtu != 0 {
config.Mtu = mtu config.Mtu = mtu
} else { } else {
config.Mtu = DefaultNetworkMtu config.Mtu = DefaultNetworkMtu
} }
config.DisableNetwork = job.Getenv("BridgeIface") == DisableNetworkBridge
return config return config
} }

View File

@ -8,7 +8,6 @@ import (
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/execdriver"
"github.com/dotcloud/docker/graphdriver" "github.com/dotcloud/docker/graphdriver"
"github.com/dotcloud/docker/networkdriver/ipallocator"
"github.com/dotcloud/docker/pkg/mount" "github.com/dotcloud/docker/pkg/mount"
"github.com/dotcloud/docker/pkg/term" "github.com/dotcloud/docker/pkg/term"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
@ -16,7 +15,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"net"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -47,7 +45,6 @@ type Container struct {
State State State State
Image string Image string
network *NetworkInterface
NetworkSettings *NetworkSettings NetworkSettings *NetworkSettings
ResolvConfPath string ResolvConfPath string
@ -558,6 +555,7 @@ func populateCommand(c *Container) {
en *execdriver.Network en *execdriver.Network
driverConfig []string driverConfig []string
) )
if !c.Config.NetworkDisabled { if !c.Config.NetworkDisabled {
network := c.NetworkSettings network := c.NetworkSettings
en = &execdriver.Network{ en = &execdriver.Network{
@ -603,15 +601,18 @@ func (container *Container) Start() (err error) {
if container.State.IsRunning() { if container.State.IsRunning() {
return fmt.Errorf("The container %s is already running.", container.ID) return fmt.Errorf("The container %s is already running.", container.ID)
} }
defer func() { defer func() {
if err != nil { if err != nil {
container.cleanup() container.cleanup()
} }
}() }()
if err := container.Mount(); err != nil { if err := container.Mount(); err != nil {
return err return err
} }
if container.runtime.networkManager.disabled {
if container.runtime.config.DisableNetwork {
container.Config.NetworkDisabled = true container.Config.NetworkDisabled = true
container.buildHostnameAndHostsFiles("127.0.1.1") container.buildHostnameAndHostsFiles("127.0.1.1")
} else { } else {
@ -669,34 +670,39 @@ func (container *Container) Start() (err error) {
} }
if len(children) > 0 { 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 container.activeLinks = make(map[string]*Link, len(children))
// config and ip table changes
rollback := func() {
for _, link := range container.activeLinks {
link.Disable()
}
container.activeLinks = nil
}
for p, child := range children { // If we encounter an error make sure that we rollback any network
link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface) // config and ip table changes
if err != nil { rollback := func() {
rollback() for _, link := range container.activeLinks {
return err link.Disable()
} }
container.activeLinks = nil
}
container.activeLinks[link.Alias()] = link for p, child := range children {
if err := link.Enable(); err != nil { link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface)
rollback() if err != nil {
return err rollback()
} return err
}
for _, envVar := range link.ToEnv() { container.activeLinks[link.Alias()] = link
env = append(env, envVar) if err := link.Enable(); err != nil {
} rollback()
} return err
}
for _, envVar := range link.ToEnv() {
env = append(env, envVar)
}
}
*/
} }
for _, elem := range container.Config.Env { for _, elem := range container.Config.Env {
@ -1102,34 +1108,44 @@ func (container *Container) allocateNetwork() error {
} }
var ( var (
iface *NetworkInterface env *engine.Env
err error eng = container.runtime.srv.Eng
) )
if container.State.IsGhost() { if container.State.IsGhost() {
if manager := container.runtime.networkManager; manager.disabled { if container.runtime.config.DisableNetwork {
iface = &NetworkInterface{disabled: true} env = &engine.Env{}
} else { } else {
iface = &NetworkInterface{ // TODO: @crosbymichael
IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask}, panic("not implemented")
Gateway: manager.bridgeNetwork.IP, /*
manager: manager, iface = &NetworkInterface{
} IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask},
if iface != nil && iface.IPNet.IP != nil { Gateway: manager.bridgeNetwork.IP,
if _, err := ipallocator.RequestIP(manager.bridgeNetwork, &iface.IPNet.IP); err != nil {
return err
} }
} else {
iface, err = container.runtime.networkManager.Allocate() // request an existing ip
if err != nil { if iface != nil && iface.IPNet.IP != nil {
return err 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 { } 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 { if err != nil {
return err return err
} }
if err := job.Run(); err != nil {
return err
}
} }
if container.Config.PortSpecs != nil { if container.Config.PortSpecs != nil {
@ -1171,37 +1187,43 @@ func (container *Container) allocateNetwork() error {
if container.hostConfig.PublishAllPorts && len(binding) == 0 { if container.hostConfig.PublishAllPorts && len(binding) == 0 {
binding = append(binding, PortBinding{}) binding = append(binding, PortBinding{})
} }
for i := 0; i < len(binding); i++ { for i := 0; i < len(binding); i++ {
b := binding[i] b := binding[i]
nat, err := iface.AllocatePort(port, b)
if err != nil { portJob := eng.Job("allocate_port", container.ID)
iface.Release() 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 return err
} }
utils.Debugf("Allocate port: %s:%s->%s", nat.Binding.HostIp, port, nat.Binding.HostPort)
binding[i] = nat.Binding
} }
bindings[port] = binding bindings[port] = binding
} }
container.writeHostConfig() container.writeHostConfig()
container.NetworkSettings.Ports = bindings container.NetworkSettings.Ports = bindings
container.network = iface
container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface container.NetworkSettings.Bridge = env.Get("Bridge")
container.NetworkSettings.IPAddress = iface.IPNet.IP.String() container.NetworkSettings.IPAddress = env.Get("IP")
container.NetworkSettings.IPPrefixLen, _ = iface.IPNet.Mask.Size() container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
container.NetworkSettings.Gateway = iface.Gateway.String() container.NetworkSettings.Gateway = env.Get("Gateway")
fmt.Printf("\n-----> %#v\n", container.NetworkSettings)
return nil return nil
} }
func (container *Container) releaseNetwork() { func (container *Container) releaseNetwork() {
if container.Config.NetworkDisabled || container.network == nil { if container.Config.NetworkDisabled {
return return
} }
container.network.Release() eng := container.runtime.srv.Eng
container.network = nil
eng.Job("release_interface", container.ID).Run()
container.NetworkSettings = &NetworkSettings{} container.NetworkSettings = &NetworkSettings{}
} }

View File

@ -19,8 +19,6 @@ import (
const ( const (
DefaultNetworkBridge = "docker0" DefaultNetworkBridge = "docker0"
DisableNetworkBridge = "none"
DefaultNetworkMtu = 1500
siocBRADDBR = 0x89a0 siocBRADDBR = 0x89a0
) )
@ -70,17 +68,24 @@ func InitDriver(job *engine.Job) engine.Status {
enableIPTables = job.GetenvBool("EnableIptables") enableIPTables = job.GetenvBool("EnableIptables")
icc = job.GetenvBool("InterContainerCommunication") icc = job.GetenvBool("InterContainerCommunication")
ipForward = job.GetenvBool("EnableIpForward") ipForward = job.GetenvBool("EnableIpForward")
bridgeIP = job.Getenv("BridgeIP")
) )
bridgeIface = job.Getenv("BridgeIface") bridgeIface = job.Getenv("BridgeIface")
if bridgeIface == "" {
bridgeIface = DefaultNetworkBridge
}
addr, err := networkdriver.GetIfaceAddr(bridgeIface) addr, err := networkdriver.GetIfaceAddr(bridgeIface)
if err != nil { if err != nil {
// If the iface is not found, try to create it // 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) job.Error(err)
return engine.StatusErr return engine.StatusErr
} }
job.Logf("getting iface addr")
addr, err = networkdriver.GetIfaceAddr(bridgeIface) addr, err = networkdriver.GetIfaceAddr(bridgeIface)
if err != nil { if err != nil {
job.Error(err) job.Error(err)
@ -122,9 +127,14 @@ func InitDriver(job *engine.Job) engine.Status {
} }
bridgeNetwork = network 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{ for name, f := range map[string]engine.Handler{
"allocate_interface": Allocate, "allocate_interface": Allocate,
"release_interface": Release, "release_interface": Release,
"allocate_port": AllocatePort,
} { } {
if err := job.Eng.Register(name, f); err != nil { if err := job.Eng.Register(name, f); err != nil {
job.Error(err) job.Error(err)
@ -304,6 +314,10 @@ func Allocate(job *engine.Job) engine.Status {
out.Set("IP", string(*ip)) out.Set("IP", string(*ip))
out.Set("Mask", string(bridgeNetwork.Mask)) out.Set("Mask", string(bridgeNetwork.Mask))
out.Set("Gateway", string(bridgeNetwork.IP)) out.Set("Gateway", string(bridgeNetwork.IP))
out.Set("Bridge", bridgeIface)
size, _ := bridgeNetwork.Mask.Size()
out.SetInt("IPPrefixLen", size)
currentInterfaces[id] = &networkInterface{ currentInterfaces[id] = &networkInterface{
IP: *ip, IP: *ip,

View File

@ -4,6 +4,7 @@ import (
"container/list" "container/list"
"fmt" "fmt"
"github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/execdriver"
"github.com/dotcloud/docker/execdriver/chroot" "github.com/dotcloud/docker/execdriver/chroot"
"github.com/dotcloud/docker/execdriver/lxc" "github.com/dotcloud/docker/execdriver/lxc"
@ -12,6 +13,7 @@ import (
_ "github.com/dotcloud/docker/graphdriver/btrfs" _ "github.com/dotcloud/docker/graphdriver/btrfs"
_ "github.com/dotcloud/docker/graphdriver/devmapper" _ "github.com/dotcloud/docker/graphdriver/devmapper"
_ "github.com/dotcloud/docker/graphdriver/vfs" _ "github.com/dotcloud/docker/graphdriver/vfs"
_ "github.com/dotcloud/docker/networkdriver/lxc"
"github.com/dotcloud/docker/networkdriver/portallocator" "github.com/dotcloud/docker/networkdriver/portallocator"
"github.com/dotcloud/docker/pkg/graphdb" "github.com/dotcloud/docker/pkg/graphdb"
"github.com/dotcloud/docker/pkg/sysinfo" "github.com/dotcloud/docker/pkg/sysinfo"
@ -42,7 +44,6 @@ type Runtime struct {
repository string repository string
sysInitPath string sysInitPath string
containers *list.List containers *list.List
networkManager *NetworkManager
graph *Graph graph *Graph
repositories *TagStore repositories *TagStore
idIndex *utils.TruncIndex idIndex *utils.TruncIndex
@ -609,15 +610,15 @@ func (runtime *Runtime) RegisterLink(parent, child *Container, alias string) err
} }
// FIXME: harmonize with NewGraph() // FIXME: harmonize with NewGraph()
func NewRuntime(config *DaemonConfig) (*Runtime, error) { func NewRuntime(config *DaemonConfig, eng *engine.Engine) (*Runtime, error) {
runtime, err := NewRuntimeFromDirectory(config) runtime, err := NewRuntimeFromDirectory(config, eng)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return runtime, nil return runtime, nil
} }
func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { func NewRuntimeFromDirectory(config *DaemonConfig, eng *engine.Engine) (*Runtime, error) {
// Set the default driver // Set the default driver
graphdriver.DefaultDriver = config.GraphDriver graphdriver.DefaultDriver = config.GraphDriver
@ -664,12 +665,19 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("Couldn't create Tag store: %s", err) return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
} }
if config.BridgeIface == "" {
config.BridgeIface = DefaultNetworkBridge if !config.DisableNetwork {
} job := eng.Job("init_networkdriver")
netManager, err := newNetworkManager(config)
if err != nil { job.SetenvBool("EnableIptables", config.EnableIptables)
return nil, err 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") graphdbPath := path.Join(config.Root, "linkgraph.db")
@ -721,7 +729,6 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) {
runtime := &Runtime{ runtime := &Runtime{
repository: runtimeRepo, repository: runtimeRepo,
containers: list.New(), containers: list.New(),
networkManager: netManager,
graph: g, graph: g,
repositories: repositories, repositories: repositories,
idIndex: utils.NewTruncIndex(), idIndex: utils.NewTruncIndex(),

View File

@ -65,10 +65,7 @@ func jobInitApi(job *engine.Job) engine.Status {
}() }()
job.Eng.Hack_SetGlobalVar("httpapi.server", srv) job.Eng.Hack_SetGlobalVar("httpapi.server", srv)
job.Eng.Hack_SetGlobalVar("httpapi.runtime", srv.runtime) 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{ for name, handler := range map[string]engine.Handler{
"export": srv.ContainerExport, "export": srv.ContainerExport,
"create": srv.ContainerCreate, "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) { func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
runtime, err := NewRuntime(config) runtime, err := NewRuntime(config, eng)
if err != nil { if err != nil {
return nil, err return nil, err
} }