diff --git a/ipam/allocator.go b/ipam/allocator.go index b3951db0..625646ff 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -115,7 +115,20 @@ func NewAllocator(config Config) *Allocator { // Start runs the allocator goroutine func (alloc *Allocator) Start() { - alloc.loadPersistedData() + loadedPersistedData := alloc.loadPersistedData() + switch { + case loadedPersistedData && len(alloc.seed) != 0: + alloc.infof("Found persisted IPAM data, ignoring supplied IPAM seed") + case loadedPersistedData: + alloc.infof("Initialising with persisted data") + case len(alloc.seed) != 0: + alloc.infof("Initialising with supplied IPAM seed") + alloc.createRing(alloc.seed) + case alloc.paxos.IsElector(): + alloc.infof("Initialising via deferred consensus") + default: + alloc.infof("Initialising as observer - awaiting IPAM data from another peer") + } actionChan := make(chan func(), mesh.ChannelSize) stopChan := make(chan struct{}) alloc.actionChan = actionChan @@ -890,52 +903,57 @@ func (alloc *Allocator) persistRing() { } } -func (alloc *Allocator) loadPersistedData() { +// Returns true if persisted data is to be used, otherwise false +func (alloc *Allocator) loadPersistedData() bool { var checkPeerName mesh.PeerName nameFound, err := alloc.db.Load(nameIdent, &checkPeerName) if err != nil { alloc.fatalf("Error loading persisted peer name: %s", err) } - ringFound, err := alloc.db.Load(ringIdent, &alloc.ring) + var persistedRing *ring.Ring + ringFound, err := alloc.db.Load(ringIdent, &persistedRing) if err != nil { alloc.fatalf("Error loading persisted IPAM data: %s", err) } - ownedFound, err := alloc.db.Load(ownedIdent, &alloc.owned) + var persistedOwned map[string]ownedData + ownedFound, err := alloc.db.Load(ownedIdent, &persistedOwned) if err != nil { alloc.fatalf("Error loading persisted address data: %s", err) } - if nameFound { - if checkPeerName == alloc.ourName { - if ringFound { - if len(alloc.seed) != 0 { - alloc.infof("Found persisted IPAM data, ignoring supplied IPAM seed") - } - alloc.space.UpdateRanges(alloc.ring.OwnedRanges()) - } - if ownedFound { - for _, d := range alloc.owned { - for _, cidr := range d.Cidrs { - alloc.space.Claim(cidr.Addr) - } - } - } - return - } - alloc.infof("Deleting persisted data for peername %s", checkPeerName) + overwritePersisted := func(fmt string, args ...interface{}) { + alloc.infof(fmt, args...) alloc.persistRing() alloc.persistOwned() } - if len(alloc.seed) != 0 { - alloc.infof("Initialising with supplied IPAM seed") - alloc.createRing(alloc.seed) - } else if alloc.paxos.IsElector() { - alloc.infof("Initialising via deferred consensus") - } else { - alloc.infof("Initialising as observer - awaiting IPAM data from another peer") + if !nameFound || !ringFound { + overwritePersisted("No valid persisted data") + return false } + if checkPeerName != alloc.ourName { + overwritePersisted("Deleting persisted data for peername %s", checkPeerName) + return false + } + + if persistedRing.Range() != alloc.universe { + overwritePersisted("Deleting persisted data for IPAM range %s; our range is %s", persistedRing.Range(), alloc.universe) + return false + } + + alloc.ring = persistedRing + alloc.space.UpdateRanges(alloc.ring.OwnedRanges()) + + if ownedFound { + alloc.owned = persistedOwned + for _, d := range alloc.owned { + for _, cidr := range d.Cidrs { + alloc.space.Claim(cidr.Addr) + } + } + } + return true } func (alloc *Allocator) persistOwned() { diff --git a/test/362_ipalloc_range_change.sh b/test/362_ipalloc_range_change.sh new file mode 100755 index 00000000..d7fab65a --- /dev/null +++ b/test/362_ipalloc_range_change.sh @@ -0,0 +1,14 @@ +#! /bin/bash + +. ./config.sh + +start_suite "IPAM alloc range change" + +weave_on $HOST1 launch --ipalloc-range 10.2.0.0/16 +weave_on $HOST1 prime +weave_on $HOST1 stop +weave_on $HOST1 launch --ipalloc-range 10.3.0.0/16 +# Ensure allocations can proceed +assert_raises "timeout 10 cat <( start_container $HOST1 )" + +end_suite diff --git a/test/380_ipam_seed_2_test.sh b/test/380_ipam_seed_2_test.sh index 3f18b41b..82184a8e 100755 --- a/test/380_ipam_seed_2_test.sh +++ b/test/380_ipam_seed_2_test.sh @@ -19,4 +19,12 @@ weave_on $HOST2 connect $HOST1 assert_raises "exec_on $HOST1 c1 $PING c2" assert_raises "exec_on $HOST2 c2 $PING c1" +# Now restart one router with a different peername +docker_on $HOST2 rm -f c2 >/dev/null +weave_on $HOST2 forget $HOST1 +weave_on $HOST2 stop +weave_on $HOST2 launch --name ::3 +# Check that this host has not retained the previous IPAM data +assert "weave_on $HOST2 status ipam" "" + end_suite