From b1917d909a6308afa3aec76cea2ecd74bad50553 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Tue, 9 May 2017 18:10:59 +0000 Subject: [PATCH] Move proxy attach from shell to Go Note we don't need to propagate shell-script env vars now --- prog/weaver/main.go | 1 + proxy/common.go | 38 ------------------ proxy/proxy.go | 93 ++++++++++++++++++++++++++++----------------- weave | 2 - 4 files changed, 60 insertions(+), 74 deletions(-) diff --git a/prog/weaver/main.go b/prog/weaver/main.go index ed0fb5a9..3154266d 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -220,6 +220,7 @@ func main() { proxyConfig := configureProxy(version, defaultDockerHost) if bridgeConfig.AWSVPC { proxyConfig.NoMulticastRoute = true + proxyConfig.KeepTXOn = true } // crude way of detecting that we probably have been started in a diff --git a/proxy/common.go b/proxy/common.go index e94a8565..b54816dc 100644 --- a/proxy/common.go +++ b/proxy/common.go @@ -6,8 +6,6 @@ import ( "fmt" "io/ioutil" "net/http" - "os" - "os/exec" "regexp" "strings" @@ -25,42 +23,6 @@ var ( Log = common.Log ) -func callWeave(args ...string) ([]byte, []byte, error) { - args = append([]string{"--local"}, args...) - cmd := exec.Command("./weave", args...) - cmd.Env = []string{ - "PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - } - - propagateEnv := func(key string) { - if val := os.Getenv(key); val != "" { - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, val)) - } - } - - propagateEnv("DOCKER_HOST") - - // Propagate WEAVE_DEBUG, to make debugging easier. - propagateEnv("WEAVE_DEBUG") - - // This prevents the code coverage contortions in our - // integration test suite breaking things. - propagateEnv("COVERAGE") - - // In case the router control endpoint address is non-standard. - propagateEnv("WEAVE_HTTP_ADDR") - - Log.Debug("Calling weave args: ", args, "env: ", cmd.Env) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - if err != nil { - Log.Debug("weave returned error: ", err) - } - return stdout.Bytes(), stderr.Bytes(), err -} - func unmarshalRequestBody(r *http.Request, target interface{}) error { body, err := ioutil.ReadAll(r.Body) if err != nil { diff --git a/proxy/proxy.go b/proxy/proxy.go index 3e0dce0d..02c9896c 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -3,7 +3,6 @@ package proxy import ( "bytes" "crypto/tls" - "errors" "fmt" "net" "net/http" @@ -16,10 +15,11 @@ import ( "time" docker "github.com/fsouza/go-dockerclient" + "github.com/pkg/errors" + weaveapi "github.com/weaveworks/weave/api" weavedocker "github.com/weaveworks/weave/common/docker" weavenet "github.com/weaveworks/weave/net" - "github.com/weaveworks/weave/net/address" ) const ( @@ -63,6 +63,7 @@ type Config struct { Version string WithoutDNS bool NoMulticastRoute bool + KeepTXOn bool DockerBridge string DockerHost string } @@ -509,53 +510,77 @@ func (proxy *Proxy) attach(containerID string) error { return nil } Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " ")) - if err := validateCIDRs(cidrs); err != nil { + ips, err := proxy.allocateCIDRs(container.ID, cidrs) + if err != nil { return err } - args := []string{"attach"} - args = append(args, cidrs...) + fqdn := container.Config.Hostname + "." + container.Config.Domainname if !proxy.NoRewriteHosts { - args = append(args, "--rewrite-hosts") - + var extraHosts []string if container.HostConfig != nil { - for _, eh := range container.HostConfig.ExtraHosts { - args = append(args, fmt.Sprintf("--add-host=%s", eh)) + extraHosts = container.HostConfig.ExtraHosts + } + proxy.RewriteEtcHosts(container.HostsPath, fqdn, ips, extraHosts) + } + + pid := container.State.Pid + // Passing 0 for mtu means it will be taken from the bridge + err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn) + if err != nil { + return err + } + + if !proxy.WithoutDNS { + for _, ip := range ips { + if err := proxy.weave.RegisterWithDNS(container.ID, fqdn, ip.IP.String()); err != nil { + return errors.Wrapf(err, "unable to register %s with weaveDNS: %s", container.ID, err) } } } - if proxy.NoMulticastRoute { - args = append(args, "--no-multicast-route") - } - args = append(args, container.ID) - return callWeaveAttach(container, args) + + return err } -func callWeaveAttach(container *docker.Container, args []string) error { - if _, stderr, err := callWeave(args...); err != nil { - Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr)) - return errors.New(string(stderr)) - } else if len(stderr) > 0 { - Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr)) +func (proxy *Proxy) allocateCIDRs(containerID string, cidrs []string) ([]*net.IPNet, error) { + if len(cidrs) == 0 { + cidrs = []string{"net:default"} } - return nil -} - -func validateCIDRs(cidrs []string) error { + var ipnet *net.IPNet + var err error + var ipnets []*net.IPNet for _, cidr := range cidrs { - if cidr == "net:default" { - continue - } - for _, prefix := range []string{"ip:", "net:", ""} { - if strings.HasPrefix(cidr, prefix) { - if _, err := address.ParseCIDR(strings.TrimPrefix(cidr, prefix)); err == nil { - break - } - return fmt.Errorf("invalid WEAVE_CIDR: %s", cidr) + switch { + case cidr == "net:default": + ipnet, err = proxy.weave.AllocateIP(containerID) + case strings.HasPrefix(cidr, "net:"): + var subnet *net.IPNet + _, subnet, err = net.ParseCIDR(strings.TrimPrefix(cidr, "net:")) + if err != nil { + break } + ipnet, err = proxy.weave.AllocateIPInSubnet(containerID, subnet) + case strings.HasPrefix(cidr, "ip:"): + ipnet, err = proxy.claimCIDR(containerID, strings.TrimPrefix(cidr, "ip:")) + default: + ipnet, err = proxy.claimCIDR(containerID, cidr) } + if err != nil { + return nil, errors.Wrapf(err, "for %q", cidr) + } + ipnets = append(ipnets, ipnet) } - return nil + return ipnets, nil +} + +func (proxy *Proxy) claimCIDR(containerID, cidr string) (*net.IPNet, error) { + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + return nil, err + } + ipnet.IP = ip // we want the specific IP plus the mask + err = proxy.weave.ClaimIP(containerID, ipnet) + return ipnet, err } func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) { diff --git a/weave b/weave index 95a81d01..39911739 100755 --- a/weave +++ b/weave @@ -1322,9 +1322,7 @@ launch() { -v /etc:/host/etc -v /var/lib/dbus:/host/var/lib/dbus \ -e DOCKER_BRIDGE \ -e WEAVE_DEBUG \ - -e COVERAGE \ -e WEAVE_HTTP_ADDR \ - -e EXEC_IMAGE=$EXEC_IMAGE \ -e WEAVE_PASSWORD \ -e CHECKPOINT_DISABLE \ $WEAVE_DOCKER_ARGS \