Beispiel #1
0
func TestDonateSimple(t *testing.T) {
	const (
		testAddr1 = "10.0.1.0"
		testAddr2 = "10.0.1.32"
		size      = 64
	)

	var (
		ipAddr1 = ip(testAddr1)
	)

	ps1 := makeSpace(ipAddr1, size)

	// Empty space set should split in two and give me the second half
	r, ok := ps1.Donate(address.NewRange(ip(testAddr1), size))
	numGivenUp := r.Size()
	require.True(t, ok, "Donate result")
	require.Equal(t, "10.0.1.32", r.Start.String(), "Invalid start")
	require.Equal(t, address.Count(size/2), numGivenUp)
	require.Equal(t, address.Count(size/2), ps1.NumFreeAddresses())

	// Now check we can give the rest up.
	count := 0 // count to avoid infinite loop
	for ; count < 1000; count++ {
		r, ok := ps1.Donate(address.NewRange(ip(testAddr1), size))
		if !ok {
			break
		}
		numGivenUp += r.Size()
	}
	require.Equal(t, address.Count(0), ps1.NumFreeAddresses())
	require.Equal(t, address.Count(size), numGivenUp)
}
Beispiel #2
0
func TestDonateHard(t *testing.T) {
	//common.InitDefaultLogging(true)
	var (
		start                = ip("10.0.1.0")
		size  address.Offset = 48
	)

	// Fill a fresh space
	spaceset := makeSpace(start, size)
	for i := address.Offset(0); i < size; i++ {
		ok, _ := spaceset.Allocate(address.NewRange(start, size))
		require.True(t, ok, "Failed to get IP!")
	}

	require.Equal(t, address.Count(0), spaceset.NumFreeAddresses())

	// Now free all but the last address
	// this will force us to split the free list
	for i := address.Offset(0); i < size-1; i++ {
		require.NoError(t, spaceset.Free(address.Add(start, i)))
	}

	// Now split
	newRange, ok := spaceset.Donate(address.NewRange(start, size))
	require.True(t, ok, "GiveUpSpace result")
	require.Equal(t, address.NewRange(ip("10.0.1.16"), 16), newRange, "Wrong space")
	require.Equal(t, address.Count(31), spaceset.NumFreeAddresses())

	//Space set should now have 3 spaces
	expected := &Space{
		ours: add(nil, ip("10.0.1.47"), ip("10.0.1.48")),
		free: add(add(nil, ip("10.0.1.0"), ip("10.0.1.16")), ip("10.0.1.32"), ip("10.0.1.47")),
	}
	require.Equal(t, expected, spaceset)
}
Beispiel #3
0
func TestSpaceFree(t *testing.T) {
	const (
		testAddr1   = "10.0.3.16"
		testAddrx   = "10.0.3.19"
		testAddry   = "10.0.9.19"
		containerID = "deadbeef"
		size        = 16
	)

	entireRange := address.NewRange(ip(testAddr1), size)
	space := makeSpace(ip(testAddr1), size)

	// Check we are prepared to give up the entire space
	r := space.biggestFreeRange(entireRange)
	require.Equal(t, address.NewRange(ip(testAddr1), size), r, "Wrong space")

	for i := 0; i < size; i++ {
		ok, _ := space.Allocate(entireRange)
		require.True(t, ok, "Failed to get address")
	}

	// Check we are full
	ok, _ := space.Allocate(entireRange)
	require.True(t, !ok, "Should have failed to get address")
	r, _ = space.Donate(entireRange)
	require.True(t, r.Size() == 0, "Wrong space")

	// Free in the middle
	require.NoError(t, space.Free(ip("10.0.3.23")))
	r = space.biggestFreeRange(entireRange)
	require.True(t, r.Start == ip("10.0.3.23") && r.Size() == 1, "Wrong space")

	// Free one at the end
	require.NoError(t, space.Free(ip("10.0.3.31")))
	r = space.biggestFreeRange(entireRange)
	require.True(t, r.Start == ip("10.0.3.31") && r.Size() == 1, "Wrong space")

	// Now free a few at the end
	require.NoError(t, space.Free(ip("10.0.3.30")))
	require.NoError(t, space.Free(ip("10.0.3.29")))

	require.Equal(t, address.Count(4), space.NumFreeAddresses())

	// Now get the biggest free space; should be 3.30
	r = space.biggestFreeRange(entireRange)
	require.Equal(t, address.NewRange(ip("10.0.3.30"), 2), r, "Wrong space")

	// Now free a few in the middle
	require.NoError(t, space.Free(ip("10.0.3.24")))
	require.NoError(t, space.Free(ip("10.0.3.22")))
	require.NoError(t, space.Free(ip("10.0.3.21")))

	require.Equal(t, address.Count(7), space.NumFreeAddresses())

	// Now get the biggest free space; should be 3.30
	r = space.biggestFreeRange(entireRange)
	require.Equal(t, address.NewRange(ip("10.0.3.30"), 2), r, "Wrong space")

	require.Equal(t, []address.Range{{Start: ip("10.0.3.16"), End: ip("10.0.3.32")}}, space.OwnedRanges())
}
Beispiel #4
0
// AdminTakeoverRanges (Sync) - take over the ranges owned by a given
// peer, and return how much space was transferred in the process.
// Only done on administrator command.
func (alloc *Allocator) AdminTakeoverRanges(peerNameOrNickname string) address.Count {
	resultChan := make(chan address.Count)
	alloc.actionChan <- func() {
		peername, err := alloc.lookupPeername(peerNameOrNickname)
		if err != nil {
			alloc.warnf("attempt to take over range from unknown peer '%s'", peerNameOrNickname)
			resultChan <- address.Count(0)
			return
		}

		alloc.debugln("AdminTakeoverRanges:", peername)
		if peername == alloc.ourName {
			alloc.warnf("attempt to take over range from ourself")
			resultChan <- address.Count(0)
			return
		}

		newRanges := alloc.ring.Transfer(peername, alloc.ourName)

		if len(newRanges) == 0 {
			resultChan <- address.Count(0)
			return
		}

		before := alloc.space.NumFreeAddresses()
		alloc.ringUpdated()
		after := alloc.space.NumFreeAddresses()

		alloc.gossip.GossipBroadcast(alloc.Gossip())

		resultChan <- after - before
	}
	return <-resultChan
}
Beispiel #5
0
// Returns the distance between two tokens on this ring, dealing
// with ranges which cross the origin
func (r *Ring) distance(start, end address.Address) address.Count {
	if end > start {
		return address.Count(end - start)
	}

	return address.Count((r.End - start) + (end - r.Start))
}
Beispiel #6
0
func TestSpaceAllocate(t *testing.T) {
	const (
		testAddr1   = "10.0.3.4"
		testAddr2   = "10.0.3.5"
		testAddrx   = "10.0.3.19"
		testAddry   = "10.0.9.19"
		containerID = "deadbeef"
		size        = 20
	)
	var (
		start = ip(testAddr1)
	)

	space1 := makeSpace(start, size)
	require.Equal(t, address.Count(20), space1.NumFreeAddresses())
	space1.assertInvariants()

	_, addr1 := space1.Allocate(address.NewRange(start, size))
	require.Equal(t, testAddr1, addr1.String(), "address")
	require.Equal(t, address.Count(19), space1.NumFreeAddresses())
	space1.assertInvariants()

	_, addr2 := space1.Allocate(address.NewRange(start, size))
	require.False(t, addr2.String() == testAddr1, "address")
	require.Equal(t, address.Count(18), space1.NumFreeAddresses())
	require.Equal(t, address.Count(13), space1.NumFreeAddressesInRange(address.Range{Start: ip(testAddr1), End: ip(testAddrx)}))
	require.Equal(t, address.Count(18), space1.NumFreeAddressesInRange(address.Range{Start: ip(testAddr1), End: ip(testAddry)}))
	space1.assertInvariants()

	space1.Free(addr2)
	space1.assertInvariants()

	wt.AssertErrorInterface(t, (*error)(nil), space1.Free(addr2), "double free")
	wt.AssertErrorInterface(t, (*error)(nil), space1.Free(ip(testAddrx)), "address not allocated")
	wt.AssertErrorInterface(t, (*error)(nil), space1.Free(ip(testAddry)), "wrong out of range")

	space1.assertInvariants()
}
Beispiel #7
0
// ReportFree is used by the allocator to tell the ring how many free
// ips are in a given range, so that ChoosePeersToAskForSpace can make
// more intelligent decisions.  Returns true if any changes made.
func (r *Ring) ReportFree(freespace map[address.Address]address.Count) (updated bool) {
	r.assertInvariants()
	defer r.assertInvariants()
	defer r.updateExportedVariables()

	common.Assert(!r.Empty())
	entries := r.Entries

	// As OwnedRanges splits around the origin, we need to
	// detect that here and fix up freespace
	if free, found := freespace[r.Start]; found && entries.entry(0).Token != r.Start {
		lastToken := entries.entry(-1).Token
		prevFree, found := freespace[lastToken]
		common.Assert(found)
		freespace[lastToken] = prevFree + free
		delete(freespace, r.Start)
	}

	for start, free := range freespace {
		// Look for entry
		i := sort.Search(len(entries), func(j int) bool {
			return entries[j].Token >= start
		})

		// Are you trying to report free on space I don't own?
		common.Assert(i < len(entries) && entries[i].Token == start && entries[i].Peer == r.Peer)

		// Check we're not reporting more space than the range
		entry, next := entries.entry(i), entries.entry(i+1)
		maxSize := r.distance(entry.Token, next.Token)
		common.Assert(free <= address.Count(maxSize))

		if entries[i].Free == free {
			continue
		}

		entries[i].Free = free
		entries[i].Version++
		updated = true
	}
	return
}
Beispiel #8
0
func TestTransfer(t *testing.T) {
	const cidr = "10.0.4.0/22"
	allocs, router, subnet := makeNetworkOfAllocators(3, cidr)
	defer stopNetworkOfAllocators(allocs, router)
	alloc0 := allocs[0]
	alloc1 := allocs[1]
	alloc2 := allocs[2]

	_, err := alloc1.Allocate("foo", subnet, true, returnFalse)
	require.True(t, err == nil, "Failed to get address")

	_, err = alloc2.Allocate("bar", subnet, true, returnFalse)
	require.True(t, err == nil, "Failed to get address")

	// simulation of periodic gossip
	alloc2.gossip.GossipBroadcast(alloc2.Gossip())
	router.Flush()
	alloc1.gossip.GossipBroadcast(alloc1.Gossip())
	router.Flush()

	free1 := alloc1.NumFreeAddresses(subnet.Range())
	free2 := alloc2.NumFreeAddresses(subnet.Range())

	router.RemovePeer(alloc1.ourName)
	router.RemovePeer(alloc2.ourName)
	alloc1.Stop()
	alloc2.Stop()
	router.Flush()

	require.Equal(t, free1+1, alloc0.AdminTakeoverRanges(alloc1.ourName.String()))
	require.Equal(t, free2+1, alloc0.AdminTakeoverRanges(alloc2.ourName.String()))
	router.Flush()

	require.Equal(t, address.Count(1024), alloc0.NumFreeAddresses(subnet.Range()))

	_, err = alloc0.Allocate("foo", subnet, true, returnFalse)
	require.True(t, err == nil, "Failed to get address")
	alloc0.Stop()
}
Beispiel #9
0
func TestAllocFree(t *testing.T) {
	const (
		container1 = "abcdef"
		container2 = "baddf00d"
		container3 = "b01df00d"
		universe   = "10.0.3.0/26"
		subnet1    = "10.0.3.0/28"
		subnet2    = "10.0.3.32/28"
		testAddr1  = "10.0.3.1"
		testAddr2  = "10.0.3.33"
		spaceSize  = 62 // 64 IP addresses in /26, minus .0 and .63
	)

	alloc, subnet := makeAllocatorWithMockGossip(t, "01:00:00:01:00:00", universe, 1)
	defer alloc.Stop()
	cidr1, _ := address.ParseCIDR(subnet1)
	cidr2, _ := address.ParseCIDR(subnet2)

	alloc.claimRingForTesting()
	addr1, err := alloc.SimplyAllocate(container1, cidr1)
	require.NoError(t, err)
	require.Equal(t, testAddr1, addr1.String(), "address")

	addr2, err := alloc.SimplyAllocate(container1, cidr2)
	require.NoError(t, err)
	require.Equal(t, testAddr2, addr2.String(), "address")

	addrs, err := alloc.Lookup(container1, subnet.Range())
	require.NoError(t, err)
	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.SimplyAllocate(container2, cidr1)
	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.SimplyAllocate(container1, cidr1)
	require.Equal(t, testAddr1, addr1a.String(), "address")
	addr2a, _ := alloc.SimplyAllocate(container1, cidr2)
	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.SimplyAllocate(container3, cidr1)
	require.Equal(t, testAddr1, addr3.String(), "address")
	addr4, _ := alloc.SimplyAllocate(container3, cidr2)
	require.Equal(t, testAddr2, addr4.String(), "address")

	alloc.ContainerDied(container2)

	// Resurrect
	addr1c, err := alloc.SimplyAllocate(container2, cidr1)
	require.NoError(t, err)
	require.Equal(t, addr1b, addr1c, "address")

	alloc.ContainerDied(container3)
	alloc.Encode() // sync up
	// Move the clock forward and clear out the dead container
	alloc.actionChan <- func() { alloc.now = func() time.Time { return time.Now().Add(containerDiedTimeout * 2) } }
	alloc.actionChan <- func() { alloc.removeDeadContainers() }
	require.Equal(t, address.Count(spaceSize+1), alloc.NumFreeAddresses(subnet.Range()))
}
Beispiel #10
0
func TestLowlevel(t *testing.T) {
	a := []address.Address{}
	a = add(a, 100, 200)
	require.Equal(t, []address.Address{100, 200}, a)
	require.True(t, !contains(a, 99), "")
	require.True(t, contains(a, 100), "")
	require.True(t, contains(a, 199), "")
	require.True(t, !contains(a, 200), "")
	a = add(a, 700, 800)
	require.Equal(t, []address.Address{100, 200, 700, 800}, a)
	a = add(a, 300, 400)
	require.Equal(t, []address.Address{100, 200, 300, 400, 700, 800}, a)
	a = add(a, 400, 500)
	require.Equal(t, []address.Address{100, 200, 300, 500, 700, 800}, a)
	a = add(a, 600, 700)
	require.Equal(t, []address.Address{100, 200, 300, 500, 600, 800}, a)
	a = add(a, 500, 600)
	require.Equal(t, []address.Address{100, 200, 300, 800}, a)
	a = subtract(a, 500, 600)
	require.Equal(t, []address.Address{100, 200, 300, 500, 600, 800}, a)
	a = subtract(a, 600, 700)
	require.Equal(t, []address.Address{100, 200, 300, 500, 700, 800}, a)
	a = subtract(a, 400, 500)
	require.Equal(t, []address.Address{100, 200, 300, 400, 700, 800}, a)
	a = subtract(a, 300, 400)
	require.Equal(t, []address.Address{100, 200, 700, 800}, a)
	a = subtract(a, 700, 800)
	require.Equal(t, []address.Address{100, 200}, a)
	a = subtract(a, 100, 200)
	require.Equal(t, []address.Address{}, a)

	s := New()
	require.Equal(t, address.Count(0), s.NumFreeAddresses())
	ok, got := s.Allocate(address.NewRange(0, 1000))
	require.False(t, ok, "allocate in empty space should fail")

	s.Add(100, 100)
	require.Equal(t, address.Count(100), s.NumFreeAddresses())
	ok, got = s.Allocate(address.NewRange(0, 1000))
	require.True(t, ok && got == 100, "allocate")
	require.Equal(t, address.Count(99), s.NumFreeAddresses())
	require.NoError(t, s.Claim(150))
	require.Equal(t, address.Count(98), s.NumFreeAddresses())
	require.NoError(t, s.Free(100))
	require.Equal(t, address.Count(99), s.NumFreeAddresses())
	wt.AssertErrorInterface(t, (*error)(nil), s.Free(0), "free not allocated")
	wt.AssertErrorInterface(t, (*error)(nil), s.Free(100), "double free")

	r, ok := s.Donate(address.NewRange(0, 1000))
	require.Equal(t, address.NewRange(0xa0, 0x20), r, "donate")

	// test Donate when addresses are scarce
	s = New()
	r, ok = s.Donate(address.NewRange(0, 1000))
	require.True(t, !ok, "donate on empty space should fail")
	s.Add(0, 3)
	require.NoError(t, s.Claim(0))
	require.NoError(t, s.Claim(2))
	r, ok = s.Donate(address.NewRange(0, 1000))
	require.Equal(t, address.NewRange(1, 1), r, "donate")
	r, ok = s.Donate(address.NewRange(0, 1000))
	require.True(t, !ok, "donate should fail")
}