From 081b95dfd02428bfe582e5583a3389485963a5a5 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 8 Aug 2016 15:00:31 +0100 Subject: [PATCH] CNI plugin assigns an IP to the bridge by itself No need to call `weave expose` before use. --- plugin/net/cni.go | 52 ++++++++++++++++++++++++++++--------- site/cni-plugin.md | 10 +++---- test/830_cni_plugin_test.sh | 1 - 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/plugin/net/cni.go b/plugin/net/cni.go index 566675a7..ff75e8cc 100644 --- a/plugin/net/cni.go +++ b/plugin/net/cni.go @@ -40,6 +40,19 @@ func loadNetConf(bytes []byte) (*NetConf, error) { return n, nil } +func (c *CNIPlugin) getIP(ipamType string, args *skel.CmdArgs) (result *types.Result, err error) { + // Default IPAM is Weave's own + if ipamType == "" { + result, err = ipamplugin.NewIpam(c.weave).Allocate(args) + } else { + result, err = ipam.ExecAdd(ipamType, args.StdinData) + } + if err == nil && result.IP4 == nil { + return nil, fmt.Errorf("IPAM plugin failed to allocate IP address") + } + return result, err +} + func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { conf, err := loadNetConf(args.StdinData) if err != nil { @@ -53,24 +66,26 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { return fmt.Errorf("IP Masquerading functionality not supported") } - var result *types.Result - // Default IPAM is Weave's own - if conf.IPAM.Type == "" { - result, err = ipamplugin.NewIpam(c.weave).Allocate(args) - } else { - result, err = ipam.ExecAdd(conf.IPAM.Type, args.StdinData) - } + result, err := c.getIP(conf.IPAM.Type, args) if err != nil { return fmt.Errorf("unable to allocate IP address: %s", err) } - if result.IP4 == nil { - return fmt.Errorf("IPAM plugin failed to allocate IP address") - } // If config says nothing about routes or gateway, default one will be via the bridge if result.IP4.Routes == nil && result.IP4.Gateway == nil { bridgeIP, err := findBridgeIP(conf.BrName, result.IP4.IP) - if err != nil { + if err == errBridgeNoIP { + bridgeArgs := *args + bridgeArgs.ContainerID = "weave:expose" + bridgeIPResult, err := c.getIP(conf.IPAM.Type, &bridgeArgs) + if err != nil { + return fmt.Errorf("unable to allocate IP address for bridge: %s", err) + } + if err := assignBridgeIP(conf.BrName, bridgeIPResult.IP4.IP); err != nil { + return fmt.Errorf("unable to assign IP address to bridge: %s", err) + } + bridgeIP = bridgeIPResult.IP4.IP.IP + } else if err != nil { return err } result.IP4.Gateway = bridgeIP @@ -130,13 +145,26 @@ func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, rou return nil } +func assignBridgeIP(bridgeName string, ipnet net.IPNet) error { + link, err := netlink.LinkByName(bridgeName) + if err != nil { + return err + } + if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: &ipnet}); err != nil { + return fmt.Errorf("failed to add IP address to %q: %v", bridgeName, err) + } + return nil +} + +var errBridgeNoIP = fmt.Errorf("Bridge has no IP address") + func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) { netdev, err := common.GetBridgeNetDev(bridgeName) if err != nil { return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err) } if len(netdev.CIDRs) == 0 { - return nil, fmt.Errorf("Bridge %q has no IP addresses; did you forget to run 'weave expose'?", bridgeName) + return nil, errBridgeNoIP } for _, cidr := range netdev.CIDRs { if subnet.Contains(cidr.IP) { diff --git a/site/cni-plugin.md b/site/cni-plugin.md index 1a3b5265..9440a1e4 100644 --- a/site/cni-plugin.md +++ b/site/cni-plugin.md @@ -35,11 +35,6 @@ for a discussion on peer connections. weave launch -Next, assign an IP address to the Weave bridge and [enable access to containers from the host](/site/using-weave/host-network-integration.md), -which is required by Kubernetes, by running the following: - - weave expose - ####Using the CNI network configuration file All CNI plugins are configured by a JSON file in the directory @@ -49,7 +44,10 @@ file named `10-weave.conf`, which you can alter to suit your needs. See the [CNI Spec](https://github.com/appc/cni/blob/master/SPEC.md#network-configuration) for details on the format and contents of this file. -By default, the Weave CNI plugin adds a default route out via the Weave bridge, so your containers can access resources on the internet. If you do not want this, add a section to the config file that specifies no routes: +By default, the Weave CNI plugin adds a default route out via an IP +address on the Weave bridge, so your containers can access resources +on the internet. If you do not want this, add a section to the config +file that specifies no routes: "ipam": { "routes": [ ] diff --git a/test/830_cni_plugin_test.sh b/test/830_cni_plugin_test.sh index fa8ad8d1..3db8e203 100755 --- a/test/830_cni_plugin_test.sh +++ b/test/830_cni_plugin_test.sh @@ -15,7 +15,6 @@ run_on $HOST1 sudo mkdir -p /opt/cni/bin # setup-cni is a subset of 'weave setup', without doing any 'docker pull's weave_on $HOST1 setup-cni weave_on $HOST1 launch -weave_on $HOST1 expose C1=$(docker_on $HOST1 run --net=none --name=c1 -dt $SMALL_IMAGE /bin/sh) C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)