diff --git a/ipam/allocator.go b/ipam/allocator.go index 976156d9..741390fa 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -263,9 +263,15 @@ func (alloc *Allocator) Lookup(ident string, r address.Range) ([]address.CIDR, e } // Claim an address that we think we should own (Sync) -func (alloc *Allocator) Claim(ident string, cidr address.CIDR, noErrorOnUnknown bool) error { +func (alloc *Allocator) Claim(ident string, cidr address.CIDR, isContainer, noErrorOnUnknown bool) error { resultChan := make(chan error) - op := &claim{resultChan: resultChan, ident: ident, cidr: cidr, noErrorOnUnknown: noErrorOnUnknown} + op := &claim{ + resultChan: resultChan, + ident: ident, + cidr: cidr, + isContainer: isContainer, + noErrorOnUnknown: noErrorOnUnknown, + } alloc.doOperation(op, &alloc.pendingClaims) return <-resultChan } diff --git a/ipam/allocator_test.go b/ipam/allocator_test.go index f554d536..4ee44d2e 100644 --- a/ipam/allocator_test.go +++ b/ipam/allocator_test.go @@ -170,7 +170,7 @@ func TestAllocatorClaim(t *testing.T) { addr1, _ := address.ParseCIDR(testAddr1) // First claim should trigger "dunno, I'm going to wait" - err := alloc.Claim(container3, addr1, true) + err := alloc.Claim(container3, addr1, true, true) require.NoError(t, err) alloc.Prime() @@ -178,23 +178,23 @@ func TestAllocatorClaim(t *testing.T) { addrx, err := allocs[0].Allocate(container1, subnet, true, returnFalse) // Now try the claim again - err = alloc.Claim(container3, addr1, true) + err = alloc.Claim(container3, addr1, true, true) require.NoError(t, err) // Check we get this address back if we try an allocate addr3, _ := alloc.Allocate(container3, subnet, true, returnFalse) require.Equal(t, testAddr1, address.MakeCIDR(subnet, addr3).String(), "address") // one more claim should still work - err = alloc.Claim(container3, addr1, true) + err = alloc.Claim(container3, addr1, true, true) require.NoError(t, err) // claim for a different container should fail - err = alloc.Claim(container1, addr1, true) + err = alloc.Claim(container1, addr1, true, true) require.Error(t, err) // claiming the address allocated on the other peer should fail - err = alloc.Claim(container1, address.MakeCIDR(subnet, addrx), true) + err = alloc.Claim(container1, address.MakeCIDR(subnet, addrx), true, true) require.Error(t, err, "claiming address allocated on other peer should fail") // Check an address outside of our universe addr2, _ := address.ParseCIDR(testAddr2) - err = alloc.Claim(container1, addr2, true) + err = alloc.Claim(container1, addr2, true, true) require.NoError(t, err) } @@ -530,7 +530,7 @@ func TestAllocatorFuzz(t *testing.T) { addressIndex := rand.Int31n(int32(subnet.Size())) alloc := allocs[allocIndex] addr := address.Add(subnet.Addr, address.Offset(addressIndex)) - err := alloc.Claim(name, address.MakeCIDR(subnet, addr), true) + err := alloc.Claim(name, address.MakeCIDR(subnet, addr), true, true) if err == nil { noteAllocation(allocIndex, name, addr) } diff --git a/ipam/claim.go b/ipam/claim.go index 8dc208f8..467a182e 100644 --- a/ipam/claim.go +++ b/ipam/claim.go @@ -13,6 +13,7 @@ type claim struct { resultChan chan<- error ident string cidr address.CIDR + isContainer bool noErrorOnUnknown bool } @@ -35,7 +36,7 @@ func (c *claim) Try(alloc *Allocator) bool { if !alloc.ring.Contains(c.cidr.Addr) { // Address not within our universe; assume user knows what they are doing alloc.infof("Address %s claimed by %s - not in our range", c.cidr, c.ident) - alloc.addOwned(c.ident, c.cidr) + alloc.addOwned(c.ident, c.cidr, c.isContainer) c.sendResult(nil) return true } @@ -79,7 +80,7 @@ func (c *claim) Try(alloc *Allocator) bool { if c.ident == "_" { // Special "I don't have a unique ID" identifier c.ident = c.cidr.String() } - alloc.addOwned(c.ident, c.cidr) + alloc.addOwned(c.ident, c.cidr, c.isContainer) c.sendResult(nil) } else { c.sendResult(err) diff --git a/ipam/http.go b/ipam/http.go index 2661c540..a4baf30e 100644 --- a/ipam/http.go +++ b/ipam/http.go @@ -74,7 +74,8 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID vars := mux.Vars(r) if cidr, ok := parseCIDR(w, vars["ip"]+"/"+vars["prefixlen"], false); ok { noErrorOnUnknown := r.FormValue("noErrorOnUnknown") == "true" - if err := alloc.Claim(vars["id"], cidr, noErrorOnUnknown); err != nil { + checkAlive := r.FormValue("check-alive") == "true" + if err := alloc.Claim(vars["id"], cidr, checkAlive, noErrorOnUnknown); err != nil { badRequest(w, fmt.Errorf("Unable to claim: %s", err)) return } diff --git a/weave b/weave index 0e39e2fa..1080d0a4 100755 --- a/weave +++ b/weave @@ -1379,6 +1379,12 @@ check_overlap() { # Claim addresses for a container in IPAM. Expects to be called from # with_container_addresses. ipam_reclaim() { + for CIDR in $3 ; do + http_call $HTTP_ADDR PUT "/ip/$1/$CIDR?noErrorOnUnknown=true&?check-alive=true" || true + done +} + +ipam_reclaim_no_check_alive() { for CIDR in $3 ; do http_call $HTTP_ADDR PUT /ip/$1/$CIDR?noErrorOnUnknown=true || true done @@ -1433,7 +1439,7 @@ ipam_cidrs() { # Assignment of a plain IP address; warn if it clashes but carry on check_overlap $arg || true # Abort on failure, but not 4 (=404), which means IPAM is disabled - when_weave_running http_call $HTTP_ADDR PUT /ip/$CONTAINER_ID/$arg || [ $? -eq 4 ] || return 1 + when_weave_running http_call $HTTP_ADDR PUT /ip/$CONTAINER_ID/$arg$CHECK_ALIVE || [ $? -eq 4 ] || return 1 fi ALL_CIDRS="$ALL_CIDRS $arg" fi @@ -1740,7 +1746,8 @@ fetch_router_args() { populate_router() { if [ -n "$IPRANGE" ] ; then # Tell the newly-started weave IP allocator about existing weave IPs - with_container_addresses ipam_reclaim weave:expose $(docker ps -q --no-trunc) + with_container_addresses ipam_reclaim_no_check_alive weave:expose + with_container_addresses ipam_reclaim $(docker ps -q --no-trunc) fi if [ -z "$NO_DNS_OPT" ] ; then # Tell the newly-started weaveDNS about existing weave IPs @@ -2170,7 +2177,7 @@ EOF RES=$(docker restart $1) CONTAINER=$(container_id $1) for CIDR in $ALL_CIDRS ; do - call_weave PUT /ip/$CONTAINER/$CIDR + call_weave PUT /ip/$CONTAINER/$CIDR?check-alive=true done with_container_netns_or_die $1 attach $ALL_CIDRS when_weave_running with_container_fqdn $1 put_dns_fqdn $ALL_CIDRS