From d6424a088dacc902b674f402e6a62aa8f5f4a803 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Thu, 2 Aug 2018 14:24:34 -0700 Subject: [PATCH] builder: setup code for a bridge networking Signed-off-by: Tonis Tiigi --- builder/builder-next/builder.go | 8 +- builder/builder-next/controller.go | 2 +- builder/builder-next/executor_unix.go | 97 +++++++++++++++++++++++- builder/builder-next/executor_windows.go | 3 +- cmd/dockerd/daemon.go | 7 +- daemon/network.go | 5 ++ 6 files changed, 112 insertions(+), 10 deletions(-) diff --git a/builder/builder-next/builder.go b/builder/builder-next/builder.go index 6876f8f0c0..0a06d27010 100644 --- a/builder/builder-next/builder.go +++ b/builder/builder-next/builder.go @@ -15,6 +15,7 @@ import ( "github.com/docker/docker/daemon/images" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/system" + "github.com/docker/libnetwork" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/control" "github.com/moby/buildkit/identity" @@ -27,9 +28,10 @@ import ( // Opt is option struct required for creating the builder type Opt struct { - SessionManager *session.Manager - Root string - Dist images.DistributionServices + SessionManager *session.Manager + Root string + Dist images.DistributionServices + NetworkController libnetwork.NetworkController } // Builder can build using BuildKit backend diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go index c97f941bad..9794f5f5c7 100644 --- a/builder/builder-next/controller.go +++ b/builder/builder-next/controller.go @@ -90,7 +90,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) { return nil, err } - exec, err := newExecutor(root) + exec, err := newExecutor(root, opt.NetworkController) if err != nil { return nil, err } diff --git a/builder/builder-next/executor_unix.go b/builder/builder-next/executor_unix.go index da54473dd1..010e8e475d 100644 --- a/builder/builder-next/executor_unix.go +++ b/builder/builder-next/executor_unix.go @@ -3,15 +3,108 @@ package buildkit import ( + "fmt" "path/filepath" + "sync" + "github.com/docker/libnetwork" "github.com/moby/buildkit/executor" "github.com/moby/buildkit/executor/runcexecutor" + "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/util/network" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) -func newExecutor(root string) (executor.Executor, error) { +const networkName = "bridge" + +func newExecutor(root string, net libnetwork.NetworkController) (executor.Executor, error) { return runcexecutor.New(runcexecutor.Opt{ Root: filepath.Join(root, "executor"), CommandCandidates: []string{"docker-runc", "runc"}, - }) + }, &bridgeProvider{NetworkController: net}) +} + +type bridgeProvider struct { + libnetwork.NetworkController +} + +func (p *bridgeProvider) NewInterface() (network.Interface, error) { + n, err := p.NetworkByName(networkName) + if err != nil { + return nil, err + } + + iface := &lnInterface{ready: make(chan struct{})} + iface.Once.Do(func() { + go iface.init(p.NetworkController, n) + }) + + return iface, nil +} + +func (p *bridgeProvider) Release(iface network.Interface) error { + go func() { + if err := p.release(iface); err != nil { + logrus.Errorf("%s", err) + } + }() + return nil +} + +func (p *bridgeProvider) release(iface network.Interface) error { + li, ok := iface.(*lnInterface) + if !ok { + return errors.Errorf("invalid interface %T", iface) + } + err := li.sbx.Delete() + if err1 := li.ep.Delete(true); err1 != nil && err == nil { + err = err1 + } + return err +} + +type lnInterface struct { + ep libnetwork.Endpoint + sbx libnetwork.Sandbox + sync.Once + err error + ready chan struct{} +} + +func (iface *lnInterface) init(c libnetwork.NetworkController, n libnetwork.Network) { + defer close(iface.ready) + id := identity.NewID() + + ep, err := n.CreateEndpoint(id) + if err != nil { + iface.err = err + return + } + + sbx, err := c.NewSandbox(id) + if err != nil { + iface.err = err + return + } + + if err := ep.Join(sbx); err != nil { + iface.err = err + return + } + + iface.sbx = sbx + iface.ep = ep +} + +func (iface *lnInterface) Set(pid int) error { + <-iface.ready + if iface.err != nil { + return iface.err + } + return iface.sbx.SetKey(fmt.Sprintf("/proc/%d/ns/net", pid)) +} + +func (iface *lnInterface) Remove(pid int) error { + return nil } diff --git a/builder/builder-next/executor_windows.go b/builder/builder-next/executor_windows.go index 7b0c6e64c8..e3b5aba829 100644 --- a/builder/builder-next/executor_windows.go +++ b/builder/builder-next/executor_windows.go @@ -5,11 +5,12 @@ import ( "errors" "io" + "github.com/docker/libnetwork" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/executor" ) -func newExecutor(_ string) (executor.Executor, error) { +func newExecutor(_ string, _ libnetwork.NetworkController) (executor.Executor, error) { return &winExecutor{}, nil } diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 128630cddf..199bba0285 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -286,9 +286,10 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio return opts, err } bk, err := buildkit.New(buildkit.Opt{ - SessionManager: sm, - Root: filepath.Join(config.Root, "buildkit"), - Dist: daemon.DistributionServices(), + SessionManager: sm, + Root: filepath.Join(config.Root, "buildkit"), + Dist: daemon.DistributionServices(), + NetworkController: daemon.NetworkController(), }) if err != nil { return opts, err diff --git a/daemon/network.go b/daemon/network.go index c524f01e7f..f7675a6568 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -49,6 +49,11 @@ func (daemon *Daemon) NetworkControllerEnabled() bool { return daemon.netController != nil } +// NetworkController returns the network controller created by the daemon. +func (daemon *Daemon) NetworkController() libnetwork.NetworkController { + return daemon.netController +} + // FindNetwork returns a network based on: // 1. Full ID // 2. Full Name