libnet/ipam: drop vestiges of custom addrSpaces
Only two address spaces are supported: LocalDefault and GlobalDefault. Support for non-default address spaces in the IPAM Allocator is vestigial, from a time when IPAM state was stored in a persistent shared datastore. There is no way to create non-default address spaces through the IPAM API so there is no need to retain code to support the use of such address spaces. Drop all pretense that more address spaces can exist, to the extent that the IPAM API allows. Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
parent
18ac200efe
commit
9a8b45c133
4 changed files with 65 additions and 115 deletions
|
@ -3,7 +3,6 @@ package ipam
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/libnetwork/bitseq"
|
||||
|
@ -19,12 +18,8 @@ const (
|
|||
|
||||
// Allocator provides per address space ipv4/ipv6 book keeping
|
||||
type Allocator struct {
|
||||
// Predefined pools for default address spaces
|
||||
// Separate from the addrSpace because they should not be serialized
|
||||
predefined map[string][]*net.IPNet
|
||||
predefinedStartIndices map[string]int
|
||||
// The address spaces
|
||||
addrSpaces map[string]*addrSpace
|
||||
local, global *addrSpace
|
||||
// Allocated addresses in each address space's subnet
|
||||
addresses map[SubnetKey]*bitseq.Handle
|
||||
sync.Mutex
|
||||
|
@ -33,26 +28,20 @@ type Allocator struct {
|
|||
// NewAllocator returns an instance of libnetwork ipam
|
||||
func NewAllocator(lcAs, glAs []*net.IPNet) (*Allocator, error) {
|
||||
a := &Allocator{
|
||||
predefined: map[string][]*net.IPNet{
|
||||
localAddressSpace: lcAs,
|
||||
globalAddressSpace: glAs,
|
||||
},
|
||||
predefinedStartIndices: map[string]int{},
|
||||
addresses: map[SubnetKey]*bitseq.Handle{},
|
||||
addresses: map[SubnetKey]*bitseq.Handle{},
|
||||
}
|
||||
|
||||
a.addrSpaces = map[string]*addrSpace{
|
||||
localAddressSpace: a.newAddressSpace(),
|
||||
globalAddressSpace: a.newAddressSpace(),
|
||||
}
|
||||
a.local = newAddrSpace(a, lcAs)
|
||||
a.global = newAddrSpace(a, glAs)
|
||||
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *Allocator) newAddressSpace() *addrSpace {
|
||||
func newAddrSpace(a *Allocator, predefined []*net.IPNet) *addrSpace {
|
||||
return &addrSpace{
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
alloc: a,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
alloc: a,
|
||||
predefined: predefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,11 +110,13 @@ func (a *Allocator) ReleasePool(poolID string) error {
|
|||
func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
aSpace, ok := a.addrSpaces[as]
|
||||
if !ok {
|
||||
return nil, types.BadRequestErrorf("cannot find address space %s", as)
|
||||
switch as {
|
||||
case localAddressSpace:
|
||||
return a.local, nil
|
||||
case globalAddressSpace:
|
||||
return a.global, nil
|
||||
}
|
||||
return aSpace, nil
|
||||
return nil, types.BadRequestErrorf("cannot find address space %s", as)
|
||||
}
|
||||
|
||||
// parsePoolRequest parses and validates a request to create a new pool under addressSpace and returns
|
||||
|
@ -214,27 +205,27 @@ func (a *Allocator) retrieveBitmask(k SubnetKey, n *net.IPNet) (*bitseq.Handle,
|
|||
return bm, nil
|
||||
}
|
||||
|
||||
func (a *Allocator) getPredefineds(as string) []*net.IPNet {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
p := a.predefined[as]
|
||||
i := a.predefinedStartIndices[as]
|
||||
// getPredefineds returns the predefined subnets for the address space.
|
||||
//
|
||||
// It should not be called concurrently with any other method on the addrSpace.
|
||||
func (aSpace *addrSpace) getPredefineds() []*net.IPNet {
|
||||
i := aSpace.predefinedStartIndex
|
||||
// defensive in case the list changed since last update
|
||||
if i >= len(p) {
|
||||
if i >= len(aSpace.predefined) {
|
||||
i = 0
|
||||
}
|
||||
return append(p[i:], p[:i]...)
|
||||
return append(aSpace.predefined[i:], aSpace.predefined[:i]...)
|
||||
}
|
||||
|
||||
func (a *Allocator) updateStartIndex(as string, amt int) {
|
||||
a.Lock()
|
||||
i := a.predefinedStartIndices[as] + amt
|
||||
if i < 0 || i >= len(a.predefined[as]) {
|
||||
// updatePredefinedStartIndex rotates the predefined subnet list by amt.
|
||||
//
|
||||
// It should not be called concurrently with any other method on the addrSpace.
|
||||
func (aSpace *addrSpace) updatePredefinedStartIndex(amt int) {
|
||||
i := aSpace.predefinedStartIndex + amt
|
||||
if i < 0 || i >= len(aSpace.predefined) {
|
||||
i = 0
|
||||
}
|
||||
a.predefinedStartIndices[as] = i
|
||||
a.Unlock()
|
||||
aSpace.predefinedStartIndex = i
|
||||
}
|
||||
|
||||
func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) {
|
||||
|
@ -244,19 +235,15 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
|
|||
v = v6
|
||||
}
|
||||
|
||||
if as != localAddressSpace && as != globalAddressSpace {
|
||||
aSpace, _ := a.getAddrSpace(as)
|
||||
if aSpace == nil {
|
||||
return nil, types.NotImplementedErrorf("no default pool available for non-default address spaces")
|
||||
}
|
||||
|
||||
aSpace, err := a.getAddrSpace(as)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
predefined := a.getPredefineds(as)
|
||||
|
||||
aSpace.Lock()
|
||||
for i, nw := range predefined {
|
||||
defer aSpace.Unlock()
|
||||
|
||||
for i, nw := range aSpace.getPredefineds() {
|
||||
if v != getAddressVersion(nw.IP) {
|
||||
continue
|
||||
}
|
||||
|
@ -267,12 +254,10 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
|
|||
// Shouldn't be necessary, but check prevents IP collisions should
|
||||
// predefined pools overlap for any reason.
|
||||
if !aSpace.contains(as, nw) {
|
||||
aSpace.Unlock()
|
||||
a.updateStartIndex(as, i+1)
|
||||
aSpace.updatePredefinedStartIndex(i + 1)
|
||||
return nw, nil
|
||||
}
|
||||
}
|
||||
aSpace.Unlock()
|
||||
|
||||
return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v)
|
||||
}
|
||||
|
@ -426,18 +411,14 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres
|
|||
// DumpDatabase dumps the internal info
|
||||
func (a *Allocator) DumpDatabase() string {
|
||||
a.Lock()
|
||||
aspaces := make(map[string]*addrSpace, len(a.addrSpaces))
|
||||
orderedAS := make([]string, 0, len(a.addrSpaces))
|
||||
for as, aSpace := range a.addrSpaces {
|
||||
orderedAS = append(orderedAS, as)
|
||||
aspaces[as] = aSpace
|
||||
aspaces := map[string]*addrSpace{
|
||||
localAddressSpace: a.local,
|
||||
globalAddressSpace: a.global,
|
||||
}
|
||||
a.Unlock()
|
||||
|
||||
sort.Strings(orderedAS)
|
||||
|
||||
var s string
|
||||
for _, as := range orderedAS {
|
||||
for _, as := range []string{localAddressSpace, globalAddressSpace} {
|
||||
aSpace := aspaces[as]
|
||||
s = fmt.Sprintf("\n\n%s Config", as)
|
||||
aSpace.Lock()
|
||||
|
|
|
@ -83,14 +83,13 @@ func TestAddSubnets(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.addrSpaces["abc"] = a.addrSpaces[localAddressSpace]
|
||||
|
||||
pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected failure in adding subnet")
|
||||
}
|
||||
|
||||
pid1, _, _, err := a.RequestPool("abc", "10.0.0.0/8", "", nil, false)
|
||||
pid1, _, _, err := a.RequestPool(globalAddressSpace, "10.0.0.0/8", "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected failure in adding overlapping subnets to different address spaces: %v", err)
|
||||
}
|
||||
|
@ -99,21 +98,21 @@ func TestAddSubnets(t *testing.T) {
|
|||
t.Fatal("returned same pool id for same subnets in different namespaces")
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "", nil, false)
|
||||
_, _, _, err = a.RequestPool(globalAddressSpace, "10.0.0.0/8", "", nil, false)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected failure requesting existing subnet")
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("abc", "10.128.0.0/9", "", nil, false)
|
||||
_, _, _, err = a.RequestPool(globalAddressSpace, "10.128.0.0/9", "", nil, false)
|
||||
if err == nil {
|
||||
t.Fatal("Expected failure on adding overlapping base subnet")
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "10.128.0.0/9", nil, false)
|
||||
_, _, _, err = a.RequestPool(globalAddressSpace, "10.0.0.0/8", "10.128.0.0/9", nil, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected failure on adding sub pool: %v", err)
|
||||
}
|
||||
_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "10.128.0.0/9", nil, false)
|
||||
_, _, _, err = a.RequestPool(globalAddressSpace, "10.0.0.0/8", "10.128.0.0/9", nil, false)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected failure on adding overlapping sub pool")
|
||||
}
|
||||
|
@ -317,11 +316,6 @@ func TestRemoveSubnet(t *testing.T) {
|
|||
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
|
||||
assert.NilError(t, err)
|
||||
|
||||
a.addrSpaces["splane"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
input := []struct {
|
||||
addrSpace string
|
||||
subnet string
|
||||
|
@ -331,10 +325,10 @@ func TestRemoveSubnet(t *testing.T) {
|
|||
{localAddressSpace, "172.17.0.0/16", false},
|
||||
{localAddressSpace, "10.0.0.0/8", false},
|
||||
{localAddressSpace, "2001:db8:1:2:3:4:ffff::/112", false},
|
||||
{"splane", "172.17.0.0/16", false},
|
||||
{"splane", "10.0.0.0/8", false},
|
||||
{"splane", "2001:db8:1:2:3:4:5::/112", true},
|
||||
{"splane", "2001:db8:1:2:3:4:ffff::/112", true},
|
||||
{globalAddressSpace, "172.17.0.0/16", false},
|
||||
{globalAddressSpace, "10.0.0.0/8", false},
|
||||
{globalAddressSpace, "2001:db8:1:2:3:4:5::/112", true},
|
||||
{globalAddressSpace, "2001:db8:1:2:3:4:ffff::/112", true},
|
||||
}
|
||||
|
||||
poolIDs := make([]string, len(input))
|
||||
|
@ -356,12 +350,7 @@ func TestGetSameAddress(t *testing.T) {
|
|||
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
|
||||
assert.NilError(t, err)
|
||||
|
||||
a.addrSpaces["giallo"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
pid, _, _, err := a.RequestPool("giallo", "192.168.100.0/24", "", nil, false)
|
||||
pid, _, _, err := a.RequestPool(localAddressSpace, "192.168.100.0/24", "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -435,12 +424,7 @@ func TestRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
|
||||
assert.NilError(t, err)
|
||||
|
||||
a.addrSpaces["rosso"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false)
|
||||
poolID, _, _, err := a.RequestPool(localAddressSpace, "172.28.0.0/16", "172.28.30.0/24", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -470,11 +454,11 @@ func TestRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false)
|
||||
_, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false)
|
||||
poolID, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/16", "10.0.0.0/24", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -507,7 +491,7 @@ func TestRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
dueExp, _ := types.ParseCIDR("10.2.2.2/16")
|
||||
treExp, _ := types.ParseCIDR("10.2.2.1/16")
|
||||
|
||||
if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
|
||||
if poolID, _, _, err = a.RequestPool(localAddressSpace, "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tre, _, err := a.RequestAddress(poolID, treExp.IP, nil)
|
||||
|
@ -563,12 +547,7 @@ func TestSerializeRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
|
||||
assert.NilError(t, err)
|
||||
|
||||
a.addrSpaces["rosso"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false)
|
||||
poolID, _, _, err := a.RequestPool(localAddressSpace, "172.28.0.0/16", "172.28.30.0/24", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -598,11 +577,11 @@ func TestSerializeRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false)
|
||||
_, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false)
|
||||
poolID, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/16", "10.0.0.0/24", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -636,7 +615,7 @@ func TestSerializeRequestReleaseAddressFromSubPool(t *testing.T) {
|
|||
treExp, _ := types.ParseCIDR("10.2.2.1/16")
|
||||
quaExp, _ := types.ParseCIDR("10.2.2.3/16")
|
||||
fivExp, _ := types.ParseCIDR("10.2.2.4/16")
|
||||
if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
|
||||
if poolID, _, _, err = a.RequestPool(localAddressSpace, "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tre, _, err := a.RequestAddress(poolID, treExp.IP, opts)
|
||||
|
@ -702,17 +681,11 @@ func TestRequestSyntaxCheck(t *testing.T) {
|
|||
var (
|
||||
pool = "192.168.0.0/16"
|
||||
subPool = "192.168.0.0/24"
|
||||
as = "green"
|
||||
)
|
||||
|
||||
a, err := NewAllocator(ipamutils.GetLocalScopeDefaultNetworks(), ipamutils.GetGlobalScopeDefaultNetworks())
|
||||
assert.NilError(t, err)
|
||||
|
||||
a.addrSpaces[as] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool("", pool, "", nil, false)
|
||||
if err == nil {
|
||||
t.Fatal("Failed to detect wrong request: empty address space")
|
||||
|
@ -723,12 +696,12 @@ func TestRequestSyntaxCheck(t *testing.T) {
|
|||
t.Fatal("Failed to detect wrong request: empty address space")
|
||||
}
|
||||
|
||||
_, _, _, err = a.RequestPool(as, "", subPool, nil, false)
|
||||
_, _, _, err = a.RequestPool(localAddressSpace, "", subPool, nil, false)
|
||||
if err == nil {
|
||||
t.Fatal("Failed to detect wrong request: subPool specified and no pool")
|
||||
}
|
||||
|
||||
pid, _, _, err := a.RequestPool(as, pool, subPool, nil, false)
|
||||
pid, _, _, err := a.RequestPool(localAddressSpace, pool, subPool, nil, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected failure: %v", err)
|
||||
}
|
||||
|
@ -1234,17 +1207,13 @@ func TestRequestReleaseAddressDuplicate(t *testing.T) {
|
|||
}
|
||||
ips := []IP{}
|
||||
allocatedIPs := []*net.IPNet{}
|
||||
a.addrSpaces["rosso"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
opts := map[string]string{
|
||||
ipamapi.AllocSerialPrefix: "true",
|
||||
}
|
||||
var l sync.Mutex
|
||||
|
||||
poolID, _, _, err := a.RequestPool("rosso", "198.168.0.0/23", "", nil, false)
|
||||
poolID, _, _, err := a.RequestPool(localAddressSpace, "198.168.0.0/23", "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -41,16 +41,11 @@ func newTestContext(t *testing.T, mask int, options map[string]string) *testCont
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.addrSpaces["giallo"] = &addrSpace{
|
||||
alloc: a.addrSpaces[localAddressSpace].alloc,
|
||||
subnets: map[SubnetKey]*PoolData{},
|
||||
}
|
||||
|
||||
network := fmt.Sprintf("192.168.100.0/%d", mask)
|
||||
// total ips 2^(32-mask) - 2 (network and broadcast)
|
||||
totalIps := 1<<uint(32-mask) - 2
|
||||
|
||||
pid, _, _, err := a.RequestPool("giallo", network, "", nil, false)
|
||||
pid, _, _, err := a.RequestPool(localAddressSpace, network, "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,11 @@ type PoolData struct {
|
|||
type addrSpace struct {
|
||||
subnets map[SubnetKey]*PoolData
|
||||
alloc *Allocator
|
||||
|
||||
// Predefined pool for the address space
|
||||
predefined []*net.IPNet
|
||||
predefinedStartIndex int
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue