From ec3de1a07294cc1ea1c1b72196903cedde85ee69 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 26 Nov 2015 17:17:51 +0000 Subject: [PATCH] Introduce ipam plugin --- Makefile | 2 +- ipam/allocate.go | 5 +++ plugin/ipam/driver.go | 74 +++++++++++++++++++++++++++++++++++++++++++ plugin/net/driver.go | 9 ++---- prog/plugin/main.go | 19 ++++++++--- 5 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 plugin/ipam/driver.go diff --git a/Makefile b/Makefile index 5e52cb37..7680e1a7 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,7 @@ $(NETCHECK_EXE): prog/netcheck/netcheck.go $(SIGPROXY_EXE): prog/sigproxy/main.go $(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go $(DOCKERTLSARGS_EXE): prog/docker_tls_args/*.go -$(DOCKERPLUGIN_EXE): prog/plugin/*.go plugin/net/*.go plugin/skel/*.go api/*.go common/docker/*.go +$(DOCKERPLUGIN_EXE): prog/plugin/*.go plugin/net/*.go plugin/ipam/*.go plugin/skel/*.go api/*.go common/docker/*.go $(TEST_TLS_EXE): test/tls/*.go $(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(DOCKERTLSARGS_EXE) $(DOCKERPLUGIN_EXE) $(TEST_TLS_EXE): diff --git a/ipam/allocate.go b/ipam/allocate.go index e8950e37..d6dd2f10 100644 --- a/ipam/allocate.go +++ b/ipam/allocate.go @@ -38,6 +38,11 @@ func (g *allocate) Try(alloc *Allocator) bool { alloc.establishRing() if ok, addr := alloc.space.Allocate(g.r); ok { + // If caller hasn't supplied a unique ID, file it under the IP address + // which lets the caller then release the address using DELETE /ip/address + if g.ident == "_" { + g.ident = addr.String() + } alloc.debugln("Allocated", addr, "for", g.ident, "in", g.r) alloc.addOwned(g.ident, addr) g.resultChan <- allocateResult{addr, nil} diff --git a/plugin/ipam/driver.go b/plugin/ipam/driver.go new file mode 100644 index 00000000..a81de6f5 --- /dev/null +++ b/plugin/ipam/driver.go @@ -0,0 +1,74 @@ +package ipamplugin + +import ( + "fmt" + "net" + + "github.com/docker/libnetwork/ipamapi" + "github.com/weaveworks/weave/api" + . "github.com/weaveworks/weave/common" + "github.com/weaveworks/weave/common/docker" +) + +const ( + WeaveContainer = "weave" +) + +type ipam struct { + client *docker.Client + weave *api.Client +} + +func NewIpam(client *docker.Client, version string) (ipamapi.Ipam, error) { + return &ipam{client: client}, nil +} + +func (i *ipam) configureWeaveClient() error { + if i.weave != nil { + return nil + } + ip, err := i.client.GetContainerIP(WeaveContainer) + if err != nil { + Log.Warningf("weave ipam not available: %s", err) + return fmt.Errorf("weave ipam not available: %s", err) + } + i.weave = api.NewClient(ip) + return nil +} + +func (i *ipam) GetDefaultAddressSpaces() (string, string, error) { + Log.Debugln("GetDefaultAddressSpaces") + return "weavelocal", "weaveglobal", nil +} + +func (i *ipam) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) { + Log.Debugln("RequestPool", addressSpace, pool, subPool, options) + _, cidr, _ := net.ParseCIDR("10.32.0.0/12") + return "weavepool", cidr, nil, nil +} + +func (i *ipam) ReleasePool(poolID string) error { + Log.Debugln("ReleasePool", poolID) + return nil +} + +func (i *ipam) RequestAddress(poolID string, address net.IP, options map[string]string) (*net.IPNet, map[string]string, error) { + Log.Debugln("RequestAddress", poolID, address, options) + // Pass magic string to weave IPAM, which then stores the address under its own string + if err := i.configureWeaveClient(); err == nil { + ip, err := i.weave.AllocateIP("_") + Log.Debugln("allocateIP returned", ip, err) + return ip, nil, err + } else { + return nil, nil, err + } +} + +func (i *ipam) ReleaseAddress(poolID string, address net.IP) error { + Log.Debugln("ReleaseAddress", poolID, address) + if err := i.configureWeaveClient(); err == nil { + return i.weave.ReleaseIP(address.String()) + } else { + return err + } +} diff --git a/plugin/net/driver.go b/plugin/net/driver.go index e5b1e413..5eb5c984 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -27,19 +27,14 @@ type driver struct { endpoints map[string]struct{} } -func New(version string, nameserver string) (skel.Driver, error) { - client, err := docker.NewClient("unix:///var/run/docker.sock") - if err != nil { - return nil, errorf("could not connect to docker: %s", err) - } - +func New(client *docker.Client, version string, nameserver string) (skel.Driver, error) { driver := &driver{ nameserver: nameserver, version: version, endpoints: make(map[string]struct{}), } - _, err = NewWatcher(client, driver) + _, err := NewWatcher(client, driver) if err != nil { return nil, err } diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 09315cd6..4ae75164 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -9,7 +9,9 @@ import ( "syscall" . "github.com/weaveworks/weave/common" - "github.com/weaveworks/weave/plugin/net" + "github.com/weaveworks/weave/common/docker" + ipamplugin "github.com/weaveworks/weave/plugin/ipam" + netplugin "github.com/weaveworks/weave/plugin/net" "github.com/weaveworks/weave/plugin/skel" ) @@ -39,8 +41,17 @@ func main() { Log.Println("Weave plugin", version, "Command line options:", os.Args) - var d skel.Driver - d, err := plugin.New(version, nameserver) + dockerClient, err := docker.NewClient("unix:///var/run/docker.sock") + if err != nil { + Log.Fatalf("unable to connect to docker: %s", err) + } + + d, err := netplugin.New(dockerClient, version, nameserver) + if err != nil { + Log.Fatalf("unable to create driver: %s", err) + } + + i, err := ipamplugin.NewIpam(dockerClient, version) if err != nil { Log.Fatalf("unable to create driver: %s", err) } @@ -62,7 +73,7 @@ func main() { endChan := make(chan error, 1) go func() { - endChan <- skel.Listen(listener, d, nil) + endChan <- skel.Listen(listener, d, i) }() select {