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"
)
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
}

View file

@ -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{}
}

View file

@ -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,

View file

@ -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(),

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.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
}