diff --git a/ipam/allocator.go b/ipam/allocator.go index fa8cfd30..71b21309 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -77,8 +77,9 @@ type Allocator struct { } type PreClaim struct { - Ident string - Cidr address.CIDR + Ident string + IsContainer bool + Cidr address.CIDR } type Config struct { diff --git a/ipam/allocator_test.go b/ipam/allocator_test.go index 64addc3f..273d7cb1 100644 --- a/ipam/allocator_test.go +++ b/ipam/allocator_test.go @@ -174,7 +174,7 @@ func TestAllocatorClaim(t *testing.T) { ) preAddr, _ := address.ParseCIDR(testPre) - allocs, router, subnet := makeNetworkOfAllocators(2, universe, []PreClaim{{container1, preAddr}}) + allocs, router, subnet := makeNetworkOfAllocators(2, universe, []PreClaim{{container1, true, preAddr}}) defer stopNetworkOfAllocators(allocs, router) alloc := allocs[1] addr1, _ := address.ParseCIDR(testAddr1) diff --git a/prog/weaver/main.go b/prog/weaver/main.go index b4f7fcc6..f2666188 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -306,15 +306,16 @@ func main() { } trackerName = "awsvpc" } - preClaims, err := findExistingAddresses(weavenet.WeaveBridgeName) + var allContainerIDs []string + if dockerCli != nil { + allContainerIDs, err = dockerCli.AllContainerIDs() + checkFatal(err) + } + preClaims, err := findExistingAddresses(dockerCli, allContainerIDs, weavenet.WeaveBridgeName) checkFatal(err) allocator, defaultSubnet = createAllocator(router, ipamConfig, preClaims, db, t, isKnownPeer) observeContainers(allocator) - if dockerCli != nil { - ids, err := dockerCli.AllContainerIDs() - checkFatal(err) - allocator.PruneOwned(ids) - } + allocator.PruneOwned(allContainerIDs) } var ( diff --git a/prog/weaver/reclaim.go b/prog/weaver/reclaim.go index 8678fe8d..5ccae97b 100644 --- a/prog/weaver/reclaim.go +++ b/prog/weaver/reclaim.go @@ -3,8 +3,11 @@ package main import ( "net" + docker "github.com/fsouza/go-dockerclient" + "github.com/weaveworks/weave/api" "github.com/weaveworks/weave/common" + weavedocker "github.com/weaveworks/weave/common/docker" "github.com/weaveworks/weave/ipam" weavenet "github.com/weaveworks/weave/net" "github.com/weaveworks/weave/net/address" @@ -17,38 +20,64 @@ func a(cidr *net.IPNet) address.CIDR { // Get all the existing Weave IPs at startup, so we can stop IPAM // giving out any as duplicates -func findExistingAddresses(bridgeName string) (addrs []ipam.PreClaim, err error) { +func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string, bridgeName string) (addrs []ipam.PreClaim, err error) { + Log.Infof("Checking for pre-existing addresses on %s bridge", bridgeName) // First get the address for the bridge bridgeNetDev, err := weavenet.GetBridgeNetDev(bridgeName) if err != nil { return nil, err } for _, cidr := range bridgeNetDev.CIDRs { + Log.Infof("%s bridge has address %v", bridgeName, cidr) addrs = append(addrs, ipam.PreClaim{Ident: "weave:expose", Cidr: a(cidr)}) } + add := func(cid string, isContainer bool, netDevs []weavenet.Dev) { + for _, netDev := range netDevs { + for _, cidr := range netDev.CIDRs { + Log.Infof("Found address %v for ID %s", cidr, cid) + addrs = append(addrs, ipam.PreClaim{Ident: cid, IsContainer: isContainer, Cidr: a(cidr)}) + } + } + } + // Then find all veths connected to the bridge peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName) if err != nil { return nil, err } - pids, err := common.AllPids("/proc") - if err != nil { - return nil, err - } - - // Now iterate over all processes to see if they have a network namespace with an attached interface - for _, pid := range pids { - netDevs, err := weavenet.GetNetDevsByVethPeerIds(pid, peerIDs) + // Now iterate over all containers to see if they have a network + // namespace with an attached interface + if dockerCli != nil { + for _, cid := range containerIDs { + container, err := dockerCli.InspectContainer(cid) + if err != nil { + if _, ok := err.(*docker.NoSuchContainer); ok { + continue + } + return nil, err + } + if container.State.Pid != 0 { + netDevs, err := weavenet.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs) + if err != nil { + return nil, err + } + add(cid, true, netDevs) + } + } + } else { + // If we don't have a Docker connection, iterate over all processes + pids, err := common.AllPids("/proc") if err != nil { return nil, err } - for _, netDev := range netDevs { - for _, cidr := range netDev.CIDRs { - // We don't know the container ID, so use special magic string - addrs = append(addrs, ipam.PreClaim{Ident: api.NoContainerID, Cidr: a(cidr)}) + for _, pid := range pids { + netDevs, err := weavenet.GetNetDevsByVethPeerIds(pid, peerIDs) + if err != nil { + return nil, err } + add(api.NoContainerID, false, netDevs) } } return addrs, nil