Merge pull request #2165 from weaveworks/issues/2164-less-deleting
Store 'checkAlive' flag in IPAM, so we don't delete non-container IDs
This commit is contained in:
commit
6ad9dac71a
7 files changed
+123
-74
No files matched your search
+2
-1
@@ -15,6 +15,7 @@ type allocate struct {
|
||||
resultChan chan<- allocateResult
|
||||
ident string
|
||||
r address.CIDR // Subnet we are trying to allocate within
|
||||
isContainer bool
|
||||
hasBeenCancelled func() bool
|
||||
}
|
||||
|
||||
@@ -46,7 +47,7 @@ func (g *allocate) Try(alloc *Allocator) bool {
|
||||
g.ident = addr.String()
|
||||
}
|
||||
alloc.debugln("Allocated", addr, "for", g.ident, "in", g.r)
|
||||
alloc.addOwned(g.ident, address.MakeCIDR(g.r, addr))
|
||||
alloc.addOwned(g.ident, address.MakeCIDR(g.r, addr), g.isContainer)
|
||||
g.resultChan <- allocateResult{addr, nil}
|
||||
return true
|
||||
}
|
||||
|
||||
+57
-31
@@ -41,6 +41,12 @@ type operation interface {
|
||||
ForContainer(ident string) bool
|
||||
}
|
||||
|
||||
// This type is persisted hence all fields exported
|
||||
type ownedData struct {
|
||||
IsContainer bool
|
||||
Cidrs []address.CIDR
|
||||
}
|
||||
|
||||
// Allocator brings together Ring and space.Set, and does the
|
||||
// necessary plumbing. Runs as a single-threaded Actor, so no locks
|
||||
// are used around data structures.
|
||||
@@ -48,18 +54,18 @@ type Allocator struct {
|
||||
actionChan chan<- func()
|
||||
stopChan chan<- struct{}
|
||||
ourName mesh.PeerName
|
||||
seed []mesh.PeerName // optional user supplied ring seed
|
||||
universe address.Range // superset of all ranges
|
||||
ring *ring.Ring // information on ranges owned by all peers
|
||||
space space.Space // more detail on ranges owned by us
|
||||
owned map[string][]address.CIDR // who owns what addresses, indexed by container-ID
|
||||
nicknames map[mesh.PeerName]string // so we can map nicknames for rmpeer
|
||||
pendingAllocates []operation // held until we get some free space
|
||||
pendingClaims []operation // held until we know who owns the space
|
||||
pendingPrimes []operation // held while our ring is empty
|
||||
dead map[string]time.Time // containers we heard were dead, and when
|
||||
db db.DB // persistence
|
||||
gossip mesh.Gossip // our link to the outside world for sending messages
|
||||
seed []mesh.PeerName // optional user supplied ring seed
|
||||
universe address.Range // superset of all ranges
|
||||
ring *ring.Ring // information on ranges owned by all peers
|
||||
space space.Space // more detail on ranges owned by us
|
||||
owned map[string]ownedData // who owns what addresses, indexed by container-ID
|
||||
nicknames map[mesh.PeerName]string // so we can map nicknames for rmpeer
|
||||
pendingAllocates []operation // held until we get some free space
|
||||
pendingClaims []operation // held until we know who owns the space
|
||||
pendingPrimes []operation // held while our ring is empty
|
||||
dead map[string]time.Time // containers we heard were dead, and when
|
||||
db db.DB // persistence
|
||||
gossip mesh.Gossip // our link to the outside world for sending messages
|
||||
paxos paxos.Participant
|
||||
awaitingConsensus bool
|
||||
ticker *time.Ticker
|
||||
@@ -94,7 +100,7 @@ func NewAllocator(config Config) *Allocator {
|
||||
seed: config.Seed,
|
||||
universe: config.Universe,
|
||||
ring: ring.New(config.Universe.Start, config.Universe.End, config.OurName),
|
||||
owned: make(map[string][]address.CIDR),
|
||||
owned: make(map[string]ownedData),
|
||||
db: config.Db,
|
||||
paxos: participant,
|
||||
nicknames: map[mesh.PeerName]string{config.OurName: config.OurNickname},
|
||||
@@ -233,9 +239,15 @@ func (alloc *Allocator) Prime() {
|
||||
|
||||
// Allocate (Sync) - get new IP address for container with given name in range
|
||||
// if there isn't any space in that range we block indefinitely
|
||||
func (alloc *Allocator) Allocate(ident string, r address.CIDR, hasBeenCancelled func() bool) (address.Address, error) {
|
||||
func (alloc *Allocator) Allocate(ident string, r address.CIDR, isContainer bool, hasBeenCancelled func() bool) (address.Address, error) {
|
||||
resultChan := make(chan allocateResult)
|
||||
op := &allocate{resultChan: resultChan, ident: ident, r: r, hasBeenCancelled: hasBeenCancelled}
|
||||
op := &allocate{
|
||||
resultChan: resultChan,
|
||||
ident: ident,
|
||||
r: r,
|
||||
isContainer: isContainer,
|
||||
hasBeenCancelled: hasBeenCancelled,
|
||||
}
|
||||
alloc.doOperation(op, &alloc.pendingAllocates)
|
||||
result := <-resultChan
|
||||
return result.addr, result.err
|
||||
@@ -251,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
|
||||
}
|
||||
@@ -876,8 +894,8 @@ func (alloc *Allocator) loadPersistedData() {
|
||||
alloc.space.UpdateRanges(alloc.ring.OwnedRanges())
|
||||
}
|
||||
if ownedFound {
|
||||
for _, cidrs := range alloc.owned {
|
||||
for _, cidr := range cidrs {
|
||||
for _, d := range alloc.owned {
|
||||
for _, cidr := range d.Cidrs {
|
||||
alloc.space.Claim(cidr.Addr)
|
||||
}
|
||||
}
|
||||
@@ -914,8 +932,11 @@ func (alloc *Allocator) hasOwned(ident string) bool {
|
||||
}
|
||||
|
||||
// NB: addr must not be owned by ident already
|
||||
func (alloc *Allocator) addOwned(ident string, cidr address.CIDR) {
|
||||
alloc.owned[ident] = append(alloc.owned[ident], cidr)
|
||||
func (alloc *Allocator) addOwned(ident string, cidr address.CIDR, isContainer bool) {
|
||||
d := alloc.owned[ident]
|
||||
d.IsContainer = isContainer
|
||||
d.Cidrs = append(d.Cidrs, cidr)
|
||||
alloc.owned[ident] = d
|
||||
alloc.persistOwned()
|
||||
}
|
||||
|
||||
@@ -923,17 +944,18 @@ func (alloc *Allocator) removeAllOwned(ident string) []address.CIDR {
|
||||
a := alloc.owned[ident]
|
||||
delete(alloc.owned, ident)
|
||||
alloc.persistOwned()
|
||||
return a
|
||||
return a.Cidrs
|
||||
}
|
||||
|
||||
func (alloc *Allocator) removeOwned(ident string, addrToFree address.Address) bool {
|
||||
cidrs, _ := alloc.owned[ident]
|
||||
for i, ownedCidr := range cidrs {
|
||||
d := alloc.owned[ident]
|
||||
for i, ownedCidr := range d.Cidrs {
|
||||
if ownedCidr.Addr == addrToFree {
|
||||
if len(cidrs) == 1 {
|
||||
if len(d.Cidrs) == 1 {
|
||||
delete(alloc.owned, ident)
|
||||
} else {
|
||||
alloc.owned[ident] = append(cidrs[:i], cidrs[i+1:]...)
|
||||
d.Cidrs = append(d.Cidrs[:i], d.Cidrs[i+1:]...)
|
||||
alloc.owned[ident] = d
|
||||
}
|
||||
alloc.persistOwned()
|
||||
return true
|
||||
@@ -944,7 +966,7 @@ func (alloc *Allocator) removeOwned(ident string, addrToFree address.Address) bo
|
||||
|
||||
func (alloc *Allocator) ownedInRange(ident string, r address.Range) []address.CIDR {
|
||||
var c []address.CIDR
|
||||
for _, cidr := range alloc.owned[ident] {
|
||||
for _, cidr := range alloc.owned[ident].Cidrs {
|
||||
if r.Contains(cidr.Addr) {
|
||||
c = append(c, cidr)
|
||||
}
|
||||
@@ -953,8 +975,8 @@ func (alloc *Allocator) ownedInRange(ident string, r address.Range) []address.CI
|
||||
}
|
||||
|
||||
func (alloc *Allocator) findOwner(addr address.Address) string {
|
||||
for ident, cidrs := range alloc.owned {
|
||||
for _, candidate := range cidrs {
|
||||
for ident, d := range alloc.owned {
|
||||
for _, candidate := range d.Cidrs {
|
||||
if candidate.Addr == addr {
|
||||
return ident
|
||||
}
|
||||
@@ -966,11 +988,15 @@ func (alloc *Allocator) findOwner(addr address.Address) string {
|
||||
// For each ID in the 'owned' map, remove the entry if it isn't in the map
|
||||
func (alloc *Allocator) syncOwned(ids map[string]struct{}) {
|
||||
changed := false
|
||||
for ident, cidrs := range alloc.owned {
|
||||
for ident, d := range alloc.owned {
|
||||
if !d.IsContainer {
|
||||
continue
|
||||
}
|
||||
if _, found := ids[ident]; !found {
|
||||
for _, cidr := range cidrs {
|
||||
for _, cidr := range d.Cidrs {
|
||||
alloc.space.Free(cidr.Addr)
|
||||
}
|
||||
alloc.debugf("Deleting old entry %s: %v", ident, d.Cidrs)
|
||||
delete(alloc.owned, ident)
|
||||
changed = true
|
||||
}
|
||||
|
||||
+34
-35
@@ -41,11 +41,11 @@ func TestAllocFree(t *testing.T) {
|
||||
cidr2, _ := address.ParseCIDR(subnet2)
|
||||
|
||||
alloc.claimRingForTesting()
|
||||
addr1, err := alloc.Allocate(container1, cidr1, returnFalse)
|
||||
addr1, err := alloc.Allocate(container1, cidr1, true, returnFalse)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testAddr1, addr1.String(), "address")
|
||||
|
||||
addr2, err := alloc.Allocate(container1, cidr2, returnFalse)
|
||||
addr2, err := alloc.Allocate(container1, cidr2, true, returnFalse)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testAddr2, addr2.String(), "address")
|
||||
|
||||
@@ -54,28 +54,28 @@ func TestAllocFree(t *testing.T) {
|
||||
require.Equal(t, []address.CIDR{address.MakeCIDR(cidr1, addr1), address.MakeCIDR(cidr2, addr2)}, addrs)
|
||||
|
||||
// Ask for another address for a different container and check it's different
|
||||
addr1b, _ := alloc.Allocate(container2, cidr1, returnFalse)
|
||||
addr1b, _ := alloc.Allocate(container2, cidr1, true, returnFalse)
|
||||
if addr1b.String() == testAddr1 {
|
||||
t.Fatalf("Expected different address but got %s", addr1b.String())
|
||||
}
|
||||
|
||||
// Ask for the first container again and we should get the same addresses again
|
||||
addr1a, _ := alloc.Allocate(container1, cidr1, returnFalse)
|
||||
addr1a, _ := alloc.Allocate(container1, cidr1, true, returnFalse)
|
||||
require.Equal(t, testAddr1, addr1a.String(), "address")
|
||||
addr2a, _ := alloc.Allocate(container1, cidr2, returnFalse)
|
||||
addr2a, _ := alloc.Allocate(container1, cidr2, true, returnFalse)
|
||||
require.Equal(t, testAddr2, addr2a.String(), "address")
|
||||
|
||||
// Now delete the first container, and we should get its addresses back
|
||||
require.NoError(t, alloc.Delete(container1))
|
||||
addr3, _ := alloc.Allocate(container3, cidr1, returnFalse)
|
||||
addr3, _ := alloc.Allocate(container3, cidr1, true, returnFalse)
|
||||
require.Equal(t, testAddr1, addr3.String(), "address")
|
||||
addr4, _ := alloc.Allocate(container3, cidr2, returnFalse)
|
||||
addr4, _ := alloc.Allocate(container3, cidr2, true, returnFalse)
|
||||
require.Equal(t, testAddr2, addr4.String(), "address")
|
||||
|
||||
alloc.ContainerDied(container2)
|
||||
|
||||
// Resurrect
|
||||
addr1c, err := alloc.Allocate(container2, cidr1, returnFalse)
|
||||
addr1c, err := alloc.Allocate(container2, cidr1, true, returnFalse)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, addr1b, addr1c, "address")
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestBootstrap(t *testing.T) {
|
||||
ExpectBroadcastMessage(alloc1, nil) // alloc1 will try to form consensus
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
alloc1.Allocate("somecontainer", subnet, returnFalse)
|
||||
alloc1.Allocate("somecontainer", subnet, true, returnFalse)
|
||||
done <- true
|
||||
}()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
@@ -170,32 +170,31 @@ 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)
|
||||
|
||||
// Do one allocate to ensure paxos is all done
|
||||
alloc.Allocate("unused", subnet, returnFalse)
|
||||
alloc.Prime()
|
||||
// Do an allocate on the other peer, which we will try to claim later
|
||||
addrx, err := allocs[0].Allocate(container1, subnet, returnFalse)
|
||||
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, returnFalse)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -230,9 +229,9 @@ func TestCancel(t *testing.T) {
|
||||
alloc1.OnGossipBroadcast(alloc2.ourName, alloc2.Encode())
|
||||
|
||||
// Get some IPs, so each allocator has some space
|
||||
res1, _ := alloc1.Allocate("foo", subnet, returnFalse)
|
||||
res1, _ := alloc1.Allocate("foo", subnet, true, returnFalse)
|
||||
common.Log.Debugf("res1 = %s", res1.String())
|
||||
res2, _ := alloc2.Allocate("bar", subnet, returnFalse)
|
||||
res2, _ := alloc2.Allocate("bar", subnet, true, returnFalse)
|
||||
common.Log.Debugf("res2 = %s", res2.String())
|
||||
if res1 == res2 {
|
||||
require.FailNow(t, "Error: got same ips!")
|
||||
@@ -244,12 +243,12 @@ func TestCancel(t *testing.T) {
|
||||
|
||||
// Use up all the IPs that alloc1 owns, so the allocation after this will prompt a request to alloc2
|
||||
for i := 0; alloc1.NumFreeAddresses(subnet.HostRange()) > 0; i++ {
|
||||
alloc1.Allocate(fmt.Sprintf("tmp%d", i), subnet, returnFalse)
|
||||
alloc1.Allocate(fmt.Sprintf("tmp%d", i), subnet, true, returnFalse)
|
||||
}
|
||||
cancelChan := make(chan bool, 1)
|
||||
doneChan := make(chan bool)
|
||||
go func() {
|
||||
_, ok := alloc1.Allocate("baz", subnet,
|
||||
_, ok := alloc1.Allocate("baz", subnet, true,
|
||||
func() bool {
|
||||
select {
|
||||
case <-cancelChan:
|
||||
@@ -284,7 +283,7 @@ func TestCancelOnDied(t *testing.T) {
|
||||
|
||||
doneChan := make(chan bool)
|
||||
f := func() {
|
||||
_, ok := alloc1.Allocate(container1, subnet, returnFalse)
|
||||
_, ok := alloc1.Allocate(container1, subnet, true, returnFalse)
|
||||
doneChan <- ok == nil
|
||||
}
|
||||
|
||||
@@ -315,11 +314,11 @@ func TestGossipShutdown(t *testing.T) {
|
||||
defer alloc.Stop()
|
||||
|
||||
alloc.claimRingForTesting()
|
||||
alloc.Allocate(container1, subnet, returnFalse)
|
||||
alloc.Allocate(container1, subnet, true, returnFalse)
|
||||
|
||||
alloc.Shutdown()
|
||||
|
||||
_, err := alloc.Allocate(container2, subnet, returnFalse) // trying to allocate after shutdown should fail
|
||||
_, err := alloc.Allocate(container2, subnet, true, returnFalse) // trying to allocate after shutdown should fail
|
||||
require.False(t, err == nil, "no address")
|
||||
|
||||
CheckAllExpectedMessagesSent(alloc)
|
||||
@@ -333,10 +332,10 @@ func TestTransfer(t *testing.T) {
|
||||
alloc1 := allocs[1]
|
||||
alloc2 := allocs[2]
|
||||
|
||||
_, err := alloc1.Allocate("foo", subnet, returnFalse)
|
||||
_, err := alloc1.Allocate("foo", subnet, true, returnFalse)
|
||||
require.True(t, err == nil, "Failed to get address")
|
||||
|
||||
_, err = alloc2.Allocate("bar", subnet, returnFalse)
|
||||
_, err = alloc2.Allocate("bar", subnet, true, returnFalse)
|
||||
require.True(t, err == nil, "Failed to get address")
|
||||
|
||||
// simulation of periodic gossip
|
||||
@@ -360,7 +359,7 @@ func TestTransfer(t *testing.T) {
|
||||
|
||||
require.Equal(t, address.Count(1024), alloc0.NumFreeAddresses(subnet.Range()))
|
||||
|
||||
_, err = alloc0.Allocate("foo", subnet, returnFalse)
|
||||
_, err = alloc0.Allocate("foo", subnet, true, returnFalse)
|
||||
require.True(t, err == nil, "Failed to get address")
|
||||
alloc0.Stop()
|
||||
}
|
||||
@@ -373,7 +372,7 @@ func TestFakeRouterSimple(t *testing.T) {
|
||||
alloc1 := allocs[0]
|
||||
//alloc2 := allocs[1]
|
||||
|
||||
_, err := alloc1.Allocate("foo", subnet, returnFalse)
|
||||
_, err := alloc1.Allocate("foo", subnet, true, returnFalse)
|
||||
require.NoError(t, err, "Failed to get address")
|
||||
}
|
||||
|
||||
@@ -454,7 +453,7 @@ func TestAllocatorFuzz(t *testing.T) {
|
||||
allocIndex := rand.Int31n(nodes)
|
||||
alloc := allocs[allocIndex]
|
||||
//common.Log.Infof("Allocate: asking allocator %d", allocIndex)
|
||||
addr, err := alloc.Allocate(name, subnet, returnFalse)
|
||||
addr, err := alloc.Allocate(name, subnet, true, returnFalse)
|
||||
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Could not allocate addr"))
|
||||
@@ -511,7 +510,7 @@ func TestAllocatorFuzz(t *testing.T) {
|
||||
|
||||
//common.Log.Infof("Asking for %s (%s) on allocator %d again", res.name, addr, res.alloc)
|
||||
|
||||
newAddr, _ := alloc.Allocate(res.name, subnet, returnFalse)
|
||||
newAddr, _ := alloc.Allocate(res.name, subnet, true, returnFalse)
|
||||
oldAddr, _ := address.ParseIP(addr)
|
||||
if newAddr != oldAddr {
|
||||
panic(fmt.Sprintf("Got different address for repeat request for %s: %s != %s", res.name, newAddr, oldAddr))
|
||||
@@ -532,7 +531,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)
|
||||
}
|
||||
@@ -598,7 +597,7 @@ func TestSpaceRequest(t *testing.T) {
|
||||
defer stopNetworkOfAllocators(allocs, router)
|
||||
alloc1 := allocs[0]
|
||||
|
||||
addr, err := alloc1.Allocate(container1, subnet, returnFalse)
|
||||
addr, err := alloc1.Allocate(container1, subnet, true, returnFalse)
|
||||
require.Nil(t, err, "")
|
||||
// free it again so the donation splits the range neatly
|
||||
err = alloc1.Free(container1, addr)
|
||||
@@ -610,7 +609,7 @@ func TestSpaceRequest(t *testing.T) {
|
||||
alloc2.SetInterfaces(router.Connect(alloc2.ourName, alloc2))
|
||||
alloc2.Start()
|
||||
defer alloc2.Stop()
|
||||
alloc2.Allocate(container2, subnet, returnFalse)
|
||||
alloc2.Allocate(container2, subnet, true, returnFalse)
|
||||
|
||||
// Test whether the universe has been split into two equal halves (GH #2009)
|
||||
require.Equal(t, cidrRanges("10.32.0.0/13"), alloc1.OwnedRanges(), "")
|
||||
|
||||
+3
-2
@@ -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)
|
||||
|
||||
+3
-2
@@ -40,7 +40,7 @@ func writeAddresses(w http.ResponseWriter, cidrs []address.CIDR) {
|
||||
|
||||
func (alloc *Allocator) handleHTTPAllocate(dockerCli *docker.Client, w http.ResponseWriter, ident string, checkAlive bool, subnet address.CIDR) {
|
||||
closedChan := w.(http.CloseNotifier).CloseNotify()
|
||||
addr, err := alloc.Allocate(ident, subnet,
|
||||
addr, err := alloc.Allocate(ident, subnet, checkAlive,
|
||||
func() bool {
|
||||
select {
|
||||
case <-closedChan:
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -13,19 +13,26 @@ launch_router_with_db() {
|
||||
launch_router_with_db $HOST1 $HOST2
|
||||
launch_router_with_db $HOST2 $HOST1
|
||||
|
||||
EXPOSE=$(weave_on $HOST1 expose)
|
||||
start_container $HOST1 --name=c1
|
||||
C1=$(container_ip $HOST1 c1)
|
||||
start_container $HOST2 --name=c2
|
||||
assert_raises "exec_on $HOST2 c2 $PING $C1"
|
||||
start_container $HOST2 --name=c3a
|
||||
C3a=$(container_ip $HOST2 c3a)
|
||||
|
||||
stop_weave_on $HOST1
|
||||
stop_weave_on $HOST2
|
||||
|
||||
# Stop one container while weave is down; the address should be freed on launch
|
||||
docker_on $HOST2 rm -f c3a
|
||||
|
||||
# Start just HOST2; if nothing persisted it would form its own ring
|
||||
launch_router_with_db $HOST2
|
||||
start_container $HOST2 --name=c3
|
||||
C3=$(container_ip $HOST2 c3)
|
||||
assert_raises "[ $C3 != $C1 ]"
|
||||
assert_raises "[ $C3 = $C3a ]"
|
||||
|
||||
# Restart HOST1 and see if it remembers to connect to HOST2
|
||||
#
|
||||
@@ -34,4 +41,11 @@ assert_raises "[ $C3 != $C1 ]"
|
||||
# launch_router_with_db $HOST1
|
||||
# assert_raises "exec_on $HOST2 c2 $PING $C1"
|
||||
|
||||
# Restart the router without going through the reclaim procedure on launch
|
||||
docker_on $HOST1 restart weave
|
||||
# Check that weave:expose address hasn't been lost
|
||||
start_container $HOST1 --name=c4
|
||||
C4=$(container_ip $HOST1 c4)
|
||||
assert_raises "[ $C4 != $EXPOSE ]"
|
||||
|
||||
end_suite
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user