diff --git a/container.go b/container.go index a9bf32ac6d..707872187a 100644 --- a/container.go +++ b/container.go @@ -670,39 +670,34 @@ func (container *Container) Start() (err error) { } if len(children) > 0 { - panic("todo crosbymichael") - /* - linking is specific to iptables and the bridge we need to move this to a job + container.activeLinks = make(map[string]*Link, len(children)) - container.activeLinks = make(map[string]*Link, len(children)) + // 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 + } - // 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 - } + for p, child := range children { + link, err := NewLink(container, child, p, runtime.eng) + if 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 - } + container.activeLinks[link.Alias()] = link + if err := link.Enable(); err != nil { + rollback() + return err + } - container.activeLinks[link.Alias()] = link - if err := link.Enable(); err != nil { - rollback() - return err - } - - for _, envVar := range link.ToEnv() { - env = append(env, envVar) - } - } - */ + for _, envVar := range link.ToEnv() { + env = append(env, envVar) + } + } } for _, elem := range container.Config.Env { diff --git a/links.go b/links.go index cd96b56629..aa1c08374b 100644 --- a/links.go +++ b/links.go @@ -2,7 +2,7 @@ package docker import ( "fmt" - "github.com/dotcloud/docker/pkg/iptables" + "github.com/dotcloud/docker/engine" "path" "strings" ) @@ -11,13 +11,13 @@ type Link struct { ParentIP string ChildIP string Name string - BridgeInterface string ChildEnvironment []string Ports []Port IsEnabled bool + eng *engine.Engine } -func NewLink(parent, child *Container, name, bridgeInterface string) (*Link, error) { +func NewLink(parent, child *Container, name string, eng *engine.Engine) (*Link, error) { if parent.ID == child.ID { return nil, fmt.Errorf("Cannot link to self: %s == %s", parent.ID, child.ID) } @@ -33,12 +33,12 @@ func NewLink(parent, child *Container, name, bridgeInterface string) (*Link, err } l := &Link{ - BridgeInterface: bridgeInterface, Name: name, ChildIP: child.NetworkSettings.IPAddress, ParentIP: parent.NetworkSettings.IPAddress, ChildEnvironment: child.Config.Env, Ports: ports, + eng: eng, } return l, nil @@ -119,18 +119,21 @@ func (l *Link) Disable() { } func (l *Link) toggle(action string, ignoreErrors bool) error { - for _, p := range l.Ports { - if output, err := iptables.Raw(action, "FORWARD", - "-i", l.BridgeInterface, "-o", l.BridgeInterface, - "-p", p.Proto(), - "-s", l.ParentIP, - "--dport", p.Port(), - "-d", l.ChildIP, - "-j", "ACCEPT"); !ignoreErrors && err != nil { - return err - } else if len(output) != 0 { - return fmt.Errorf("Error toggle iptables forward: %s", output) - } + job := l.eng.Job("link", action) + + job.Setenv("ParentIP", l.ParentIP) + job.Setenv("ChildIP", l.ChildIP) + job.SetenvBool("IgnoreErrors", ignoreErrors) + + out := make([]string, len(l.Ports)) + for i, p := range l.Ports { + out[i] = fmt.Sprintf("%s/%s", p.Port(), p.Proto()) + } + job.SetenvList("Ports", out) + + if err := job.Run(); err != nil { + // TODO: get ouput from job + return err } return nil } diff --git a/networkdriver/lxc/driver.go b/networkdriver/lxc/driver.go index 0401e2de9d..84e7b3ef95 100644 --- a/networkdriver/lxc/driver.go +++ b/networkdriver/lxc/driver.go @@ -13,6 +13,7 @@ import ( "io/ioutil" "log" "net" + "strings" "syscall" "unsafe" ) @@ -137,6 +138,7 @@ func InitDriver(job *engine.Job) engine.Status { "allocate_interface": Allocate, "release_interface": Release, "allocate_port": AllocatePort, + "link": LinkContainers, } { if err := job.Eng.Register(name, f); err != nil { job.Error(err) @@ -423,3 +425,35 @@ func AllocatePort(job *engine.Job) engine.Status { return engine.StatusOK } + +func LinkContainers(job *engine.Job) engine.Status { + var ( + action = job.Args[0] + childIP = job.Getenv("ChildIP") + parentIP = job.Getenv("ParentIP") + ignoreErrors = job.GetenvBool("IgnoreErrors") + ports = job.GetenvList("Ports") + ) + split := func(p string) (string, string) { + parts := strings.Split(p, "/") + return parts[0], parts[1] + } + + for _, p := range ports { + port, proto := split(p) + if output, err := iptables.Raw(action, "FORWARD", + "-i", bridgeIface, "-o", bridgeIface, + "-p", proto, + "-s", parentIP, + "--dport", port, + "-d", childIP, + "-j", "ACCEPT"); !ignoreErrors && err != nil { + job.Error(err) + return engine.StatusErr + } else if len(output) != 0 { + job.Errorf("Error toggle iptables forward: %s", output) + return engine.StatusErr + } + } + return engine.StatusOK +}