From b3cda39b0bc4dcca88eafe172ed517f7c174b0aa Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 2 Nov 2015 18:01:40 +0000 Subject: [PATCH] Let IPAM pick any peer we know about to transfer ownership to, when shutting down --- ipam/allocator.go | 16 ++++++++++++++-- ipam/testutils_test.go | 2 +- prog/weaver/main.go | 3 ++- test/165_reset_2_test.sh | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100755 test/165_reset_2_test.sh diff --git a/ipam/allocator.go b/ipam/allocator.go index 04ad0cd9..958788cf 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -56,10 +56,11 @@ type Allocator struct { paxosTicker *time.Ticker shuttingDown bool // to avoid doing any requests while trying to shut down now func() time.Time + namesFunc func() map[router.PeerName]struct{} } // NewAllocator creates and initialises a new Allocator -func NewAllocator(ourName router.PeerName, ourUID router.PeerUID, ourNickname string, universe address.Range, quorum uint) *Allocator { +func NewAllocator(ourName router.PeerName, ourUID router.PeerUID, ourNickname string, universe address.Range, quorum uint, names func() map[router.PeerName]struct{}) *Allocator { return &Allocator{ ourName: ourName, universe: universe, @@ -68,6 +69,7 @@ func NewAllocator(ourName router.PeerName, ourUID router.PeerUID, ourNickname st paxos: paxos.NewNode(ourName, ourUID, quorum), nicknames: map[router.PeerName]string{ourName: ourNickname}, now: time.Now, + namesFunc: names, } } @@ -282,7 +284,17 @@ func (alloc *Allocator) Shutdown() { alloc.shuttingDown = true alloc.cancelOps(&alloc.pendingClaims) alloc.cancelOps(&alloc.pendingAllocates) - if heir := alloc.ring.PickPeerForTransfer(); heir != router.UnknownPeerName { + heir := alloc.ring.PickPeerForTransfer() + if heir == router.UnknownPeerName && alloc.namesFunc != nil { + // No peers in the ring; pick one via the function we were given at init + for peerName := range alloc.namesFunc() { + if peerName != alloc.ourName { + heir = peerName + break + } + } + } + if heir != router.UnknownPeerName { alloc.ring.Transfer(alloc.ourName, heir) alloc.space.Clear() alloc.gossip.GossipBroadcast(alloc.Gossip()) diff --git a/ipam/testutils_test.go b/ipam/testutils_test.go index 95f6407a..ea954aa0 100644 --- a/ipam/testutils_test.go +++ b/ipam/testutils_test.go @@ -135,7 +135,7 @@ func makeAllocator(name string, cidrStr string, quorum uint) (*Allocator, addres } alloc := NewAllocator(peername, router.PeerUID(rand.Int63()), - "nick-"+name, cidr.Range(), quorum) + "nick-"+name, cidr.Range(), quorum, nil) return alloc, cidr.HostRange() } diff --git a/prog/weaver/main.go b/prog/weaver/main.go index bf85b916..5444f2f4 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -368,7 +368,8 @@ func createAllocator(router *weave.Router, ipRangeStr string, defaultSubnetStr s Log.Fatalf("IP address allocation default subnet %s does not overlap with allocation range %s", defaultSubnet, ipRange) } } - allocator := ipam.NewAllocator(router.Ourself.Peer.Name, router.Ourself.Peer.UID, router.Ourself.Peer.NickName, ipRange.Range(), quorum) + namesFunc := func() map[weave.PeerName]struct{} { return router.Peers.Names() } + allocator := ipam.NewAllocator(router.Ourself.Peer.Name, router.Ourself.Peer.UID, router.Ourself.Peer.NickName, ipRange.Range(), quorum, namesFunc) allocator.SetInterfaces(router.NewGossip("IPallocation", allocator)) allocator.Start() diff --git a/test/165_reset_2_test.sh b/test/165_reset_2_test.sh new file mode 100755 index 00000000..cc4cdaed --- /dev/null +++ b/test/165_reset_2_test.sh @@ -0,0 +1,22 @@ +#! /bin/bash + +. ./config.sh + +start_suite "Claiming addresses" + +weave_on $HOST1 launch-router +weave_on $HOST2 launch-router $HOST1 + +start_container $HOST1 --name=c1 +start_container $HOST2 --name=c2 + +# Now reset the routers so they should give their space away, and restart +weave_on $HOST1 reset +weave_on $HOST1 launch-router $HOST2 +weave_on $HOST2 reset +weave_on $HOST2 launch-router $HOST1 + +# And try to start a container +assert_raises "timeout 10 cat <( start_container $HOST1 )" + +end_suite