Browse code

Default IPAM to handle local ds

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2015/10/04 10:51:53
Showing 5 changed files
... ...
@@ -1,14 +1,11 @@
1 1
 package ipam
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"fmt"
6 5
 	"net"
7
-	"strings"
8 6
 	"sync"
9 7
 
10 8
 	log "github.com/Sirupsen/logrus"
11
-
12 9
 	"github.com/docker/libkv/store"
13 10
 	"github.com/docker/libnetwork/bitseq"
14 11
 	"github.com/docker/libnetwork/datastore"
... ...
@@ -34,209 +31,86 @@ type Allocator struct {
34 34
 	// Predefined pools for default address spaces
35 35
 	predefined map[string][]*net.IPNet
36 36
 	// Static subnet information
37
-	subnets map[SubnetKey]*PoolData
37
+	localSubnets  *PoolsConfig
38
+	globalSubnets *PoolsConfig
38 39
 	// Allocated addresses in each address space's subnet
39 40
 	addresses map[SubnetKey]*bitseq.Handle
40 41
 	// Datastore
41
-	store    datastore.DataStore
42
-	dbIndex  uint64
43
-	dbExists bool
42
+	addrSpace2Configs map[string]*PoolsConfig
44 43
 	sync.Mutex
45 44
 }
46 45
 
47 46
 // NewAllocator returns an instance of libnetwork ipam
48 47
 func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
49 48
 	a := &Allocator{}
50
-	a.subnets = make(map[SubnetKey]*PoolData)
51
-	a.addresses = make(map[SubnetKey]*bitseq.Handle)
52
-	a.predefined = make(map[string][]*net.IPNet, 2)
53
-	a.predefined[localAddressSpace] = initLocalPredefinedPools()
54
-	a.predefined[globalAddressSpace] = initGlobalPredefinedPools()
55
-	a.store = glDs
56
-
57
-	if a.store == nil {
58
-		return a, nil
59
-	}
60
-
61
-	// Register for status changes
62
-	a.watchForChanges()
63
-
64
-	// Get the initial subnet configs status from the ds if present.
65
-	kvPair, err := a.store.KVStore().Get(datastore.Key(a.Key()...))
66
-	if err != nil {
67
-		if err != store.ErrKeyNotFound {
68
-			return nil, fmt.Errorf("failed to retrieve the ipam subnet configs from datastore: %v", err)
69
-		}
70
-		return a, nil
71
-	}
72
-	a.subnetConfigFromStore(kvPair)
73
-
74
-	// Now retrieve the bitmasks for the master pools
75
-	var inserterList []func() error
76
-	a.Lock()
77
-	for k, v := range a.subnets {
78
-		if v.Range == nil {
79
-			inserterList = append(inserterList, func() error { return a.insertBitMask(k, v.Pool) })
80
-		}
81
-	}
82
-	a.Unlock()
83
-
84
-	// Add the bitmasks, data could come from datastore
85
-	for _, f := range inserterList {
86
-		if err := f(); err != nil {
87
-			return nil, err
88
-		}
89
-	}
90
-
91
-	return a, nil
92
-}
93
-
94
-func (a *Allocator) subnetConfigFromStore(kvPair *store.KVPair) {
95
-	a.Lock()
96
-	if a.dbIndex < kvPair.LastIndex {
97
-		a.SetValue(kvPair.Value)
98
-		a.dbIndex = kvPair.LastIndex
99
-		a.dbExists = true
100
-	}
101
-	a.Unlock()
102
-}
103
-
104
-// SubnetKey is the pointer to the configured pools in each address space
105
-type SubnetKey struct {
106
-	AddressSpace string
107
-	Subnet       string
108
-	ChildSubnet  string
109
-}
110
-
111
-// String returns the string form of the SubnetKey object
112
-func (s *SubnetKey) String() string {
113
-	k := fmt.Sprintf("%s/%s", s.AddressSpace, s.Subnet)
114
-	if s.ChildSubnet != "" {
115
-		k = fmt.Sprintf("%s/%s", k, s.ChildSubnet)
116
-	}
117
-	return k
118
-}
119 49
 
120
-// FromString populate the SubnetKey object reading it from string
121
-func (s *SubnetKey) FromString(str string) error {
122
-	if str == "" || !strings.Contains(str, "/") {
123
-		return fmt.Errorf("invalid string form for subnetkey: %s", str)
50
+	a.localSubnets = &PoolsConfig{
51
+		subnets: map[SubnetKey]*PoolData{},
52
+		id:      dsConfigKey + "/Pools",
53
+		scope:   datastore.LocalScope,
54
+		ds:      lcDs,
55
+		alloc:   a,
124 56
 	}
125 57
 
126
-	p := strings.Split(str, "/")
127
-	if len(p) != 3 && len(p) != 5 {
128
-		return fmt.Errorf("invalid string form for subnetkey: %s", str)
129
-	}
130
-	s.AddressSpace = p[0]
131
-	s.Subnet = fmt.Sprintf("%s/%s", p[1], p[2])
132
-	if len(p) == 5 {
133
-		s.ChildSubnet = fmt.Sprintf("%s/%s", p[3], p[4])
58
+	a.globalSubnets = &PoolsConfig{
59
+		subnets: map[SubnetKey]*PoolData{},
60
+		id:      dsConfigKey + "/Pools",
61
+		scope:   datastore.GlobalScope,
62
+		ds:      glDs,
63
+		alloc:   a,
134 64
 	}
135 65
 
136
-	return nil
137
-}
138
-
139
-// AddressRange specifies first and last ip ordinal which
140
-// identify a range in a a pool of addresses
141
-type AddressRange struct {
142
-	Sub        *net.IPNet
143
-	Start, End uint32
144
-}
145
-
146
-// String returns the string form of the AddressRange object
147
-func (r *AddressRange) String() string {
148
-	return fmt.Sprintf("Sub: %s, range [%d, %d]", r.Sub, r.Start, r.End)
149
-}
150
-
151
-// MarshalJSON returns the JSON encoding of the Range object
152
-func (r *AddressRange) MarshalJSON() ([]byte, error) {
153
-	m := map[string]interface{}{
154
-		"Sub":   r.Sub.String(),
155
-		"Start": r.Start,
156
-		"End":   r.End,
66
+	a.predefined = map[string][]*net.IPNet{
67
+		localAddressSpace:  initLocalPredefinedPools(),
68
+		globalAddressSpace: initGlobalPredefinedPools(),
157 69
 	}
158
-	return json.Marshal(m)
159
-}
160 70
 
161
-// UnmarshalJSON decodes data into the Range object
162
-func (r *AddressRange) UnmarshalJSON(data []byte) error {
163
-	m := map[string]interface{}{}
164
-	err := json.Unmarshal(data, &m)
165
-	if err != nil {
166
-		return err
71
+	a.addrSpace2Configs = map[string]*PoolsConfig{
72
+		localAddressSpace:  a.localSubnets,
73
+		globalAddressSpace: a.globalSubnets,
167 74
 	}
168
-	if r.Sub, err = types.ParseCIDR(m["Sub"].(string)); err != nil {
169
-		return err
170
-	}
171
-	r.Start = uint32(m["Start"].(float64))
172
-	r.End = uint32(m["End"].(float64))
173
-	return nil
174
-}
175
-
176
-// PoolData contains the configured pool data
177
-type PoolData struct {
178
-	ParentKey SubnetKey
179
-	Pool      *net.IPNet
180
-	Range     *AddressRange `json:",omitempty"`
181
-	RefCount  int
182
-}
183 75
 
184
-// String returns the string form of the PoolData object
185
-func (p *PoolData) String() string {
186
-	return fmt.Sprintf("ParentKey: %s, Pool: %s, Range: %s, RefCount: %d",
187
-		p.ParentKey.String(), p.Pool.String(), p.Range, p.RefCount)
188
-}
76
+	a.addresses = make(map[SubnetKey]*bitseq.Handle)
189 77
 
190
-// MarshalJSON returns the JSON encoding of the PoolData object
191
-func (p *PoolData) MarshalJSON() ([]byte, error) {
192
-	m := map[string]interface{}{
193
-		"ParentKey": p.ParentKey,
194
-		"RefCount":  p.RefCount,
195
-	}
196
-	if p.Pool != nil {
197
-		m["Pool"] = p.Pool.String()
78
+	cfgs := []struct {
79
+		cfg *PoolsConfig
80
+		dsc string
81
+	}{
82
+		{a.localSubnets, "local"},
83
+		{a.globalSubnets, "global"},
198 84
 	}
199
-	if p.Range != nil {
200
-		m["Range"] = p.Range
201
-	}
202
-	return json.Marshal(m)
203
-}
204
-
205
-// UnmarshalJSON decodes data into the PoolData object
206
-func (p *PoolData) UnmarshalJSON(data []byte) error {
207
-	var (
208
-		err error
209
-		t   struct {
210
-			ParentKey SubnetKey
211
-			Pool      string
212
-			Range     *AddressRange `json:",omitempty"`
213
-			RefCount  int
85
+	// Get the initial local/global pools configfrom the datastores
86
+	var inserterList []func() error
87
+	for _, e := range cfgs {
88
+		if e.cfg.ds == nil {
89
+			continue
214 90
 		}
215
-	)
216
-
217
-	if err = json.Unmarshal(data, &t); err != nil {
218
-		return err
91
+		if err := e.cfg.watchForChanges(); err != nil {
92
+			log.Warnf("Error on registering watch for %s datastore: %v", e.dsc, err)
93
+		}
94
+		if err := e.cfg.readFromStore(); err != nil && err != store.ErrKeyNotFound {
95
+			return nil, fmt.Errorf("failed to retrieve the ipam %s pools config from datastore: %v", e.dsc, err)
96
+		}
97
+		e.cfg.Lock()
98
+		for k, v := range e.cfg.subnets {
99
+			if v.Range == nil {
100
+				inserterList = append(inserterList, func() error { return a.insertBitMask(e.cfg.ds, k, v.Pool) })
101
+			}
102
+		}
103
+		e.cfg.Unlock()
219 104
 	}
220
-
221
-	p.ParentKey = t.ParentKey
222
-	p.Range = t.Range
223
-	p.RefCount = t.RefCount
224
-	if t.Pool != "" {
225
-		if p.Pool, err = types.ParseCIDR(t.Pool); err != nil {
226
-			return err
105
+	// Add the bitmasks (data could come from datastore)
106
+	if inserterList != nil {
107
+		for _, f := range inserterList {
108
+			if err := f(); err != nil {
109
+				return nil, err
110
+			}
227 111
 		}
228 112
 	}
229 113
 
230
-	return nil
114
+	return a, nil
231 115
 }
232 116
 
233
-type ipVersion int
234
-
235
-const (
236
-	v4 = 4
237
-	v6 = 6
238
-)
239
-
240 117
 // GetDefaultAddressSpaces returns the local and global default address spaces
241 118
 func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
242 119
 	return localAddressSpace, globalAddressSpace, nil
... ...
@@ -248,16 +122,22 @@ func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[
248 248
 	if err != nil {
249 249
 		return "", nil, nil, ipamapi.ErrInvalidPool
250 250
 	}
251
+
252
+	cfg, err := a.getPoolsConfig(addressSpace)
253
+	if err != nil {
254
+		return "", nil, nil, err
255
+	}
256
+
251 257
 retry:
252
-	insert, err := a.updatePoolDBOnAdd(*k, nw, ipr)
258
+	insert, err := cfg.updatePoolDBOnAdd(*k, nw, ipr)
253 259
 	if err != nil {
254 260
 		return "", nil, nil, err
255 261
 	}
256
-	if err := a.writeToStore(); err != nil {
262
+	if err := cfg.writeToStore(); err != nil {
257 263
 		if _, ok := err.(types.RetryError); !ok {
258 264
 			return "", nil, nil, types.InternalErrorf("pool configuration failed because of %s", err.Error())
259 265
 		}
260
-		if erru := a.readFromStore(); erru != nil {
266
+		if erru := cfg.readFromStore(); erru != nil {
261 267
 			return "", nil, nil, fmt.Errorf("failed to get updated pool config from datastore (%v) after (%v)", erru, err)
262 268
 		}
263 269
 		goto retry
... ...
@@ -272,16 +152,21 @@ func (a *Allocator) ReleasePool(poolID string) error {
272 272
 		return types.BadRequestErrorf("invalid pool id: %s", poolID)
273 273
 	}
274 274
 
275
+	cfg, err := a.getPoolsConfig(k.AddressSpace)
276
+	if err != nil {
277
+		return err
278
+	}
279
+
275 280
 retry:
276
-	remove, err := a.updatePoolDBOnRemoval(k)
281
+	remove, err := cfg.updatePoolDBOnRemoval(k)
277 282
 	if err != nil {
278 283
 		return err
279 284
 	}
280
-	if err = a.writeToStore(); err != nil {
285
+	if err = cfg.writeToStore(); err != nil {
281 286
 		if _, ok := err.(types.RetryError); !ok {
282 287
 			return types.InternalErrorf("pool (%s) removal failed because of %v", poolID, err)
283 288
 		}
284
-		if erru := a.readFromStore(); erru != nil {
289
+		if erru := cfg.readFromStore(); erru != nil {
285 290
 			return fmt.Errorf("failed to get updated pool config from datastore (%v) after (%v)", erru, err)
286 291
 		}
287 292
 		goto retry
... ...
@@ -290,6 +175,18 @@ retry:
290 290
 	return remove()
291 291
 }
292 292
 
293
+// Given the address space, returns the local or global PoolConfig based on the
294
+// address space is local or global. AddressSpace locality is being registered with IPAM out of band.
295
+func (a *Allocator) getPoolsConfig(addrSpace string) (*PoolsConfig, error) {
296
+	a.Lock()
297
+	defer a.Unlock()
298
+	cfg, ok := a.addrSpace2Configs[addrSpace]
299
+	if !ok {
300
+		return nil, types.BadRequestErrorf("cannot find locality of address space: %s", addrSpace)
301
+	}
302
+	return cfg, nil
303
+}
304
+
293 305
 func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *net.IPNet, *AddressRange, error) {
294 306
 	var (
295 307
 		nw, aw *net.IPNet
... ...
@@ -327,89 +224,7 @@ func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool
327 327
 	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, aw, ipr, nil
328 328
 }
329 329
 
330
-func (a *Allocator) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange) (func() error, error) {
331
-	a.Lock()
332
-	defer a.Unlock()
333
-
334
-	// Check if already allocated
335
-	if p, ok := a.subnets[k]; ok {
336
-		a.incRefCount(p, 1)
337
-		return func() error { return nil }, nil
338
-	}
339
-
340
-	// If master pool, check for overlap
341
-	if ipr == nil {
342
-		if a.contains(k.AddressSpace, nw) {
343
-			return nil, ipamapi.ErrPoolOverlap
344
-		}
345
-		// This is a new master pool, add it along with corresponding bitmask
346
-		a.subnets[k] = &PoolData{Pool: nw, RefCount: 1}
347
-		return func() error { return a.insertBitMask(k, nw) }, nil
348
-	}
349
-
350
-	// This is a new non-master pool
351
-	p := &PoolData{
352
-		ParentKey: SubnetKey{AddressSpace: k.AddressSpace, Subnet: k.Subnet},
353
-		Pool:      nw,
354
-		Range:     ipr,
355
-		RefCount:  1,
356
-	}
357
-	a.subnets[k] = p
358
-
359
-	// Look for parent pool
360
-	pp, ok := a.subnets[p.ParentKey]
361
-	if ok {
362
-		a.incRefCount(pp, 1)
363
-		return func() error { return nil }, nil
364
-	}
365
-
366
-	// Parent pool does not exist, add it along with corresponding bitmask
367
-	a.subnets[p.ParentKey] = &PoolData{Pool: nw, RefCount: 1}
368
-	return func() error { return a.insertBitMask(p.ParentKey, nw) }, nil
369
-}
370
-
371
-func (a *Allocator) updatePoolDBOnRemoval(k SubnetKey) (func() error, error) {
372
-	a.Lock()
373
-	defer a.Unlock()
374
-
375
-	p, ok := a.subnets[k]
376
-	if !ok {
377
-		return nil, ipamapi.ErrBadPool
378
-	}
379
-
380
-	a.incRefCount(p, -1)
381
-
382
-	c := p
383
-	for ok {
384
-		if c.RefCount == 0 {
385
-			delete(a.subnets, k)
386
-			if c.Range == nil {
387
-				return func() error {
388
-					bm, err := a.retrieveBitmask(k, c.Pool)
389
-					if err != nil {
390
-						return fmt.Errorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err)
391
-					}
392
-					return bm.Destroy()
393
-				}, nil
394
-			}
395
-		}
396
-		k = c.ParentKey
397
-		c, ok = a.subnets[k]
398
-	}
399
-
400
-	return func() error { return nil }, nil
401
-}
402
-
403
-func (a *Allocator) incRefCount(p *PoolData, delta int) {
404
-	c := p
405
-	ok := true
406
-	for ok {
407
-		c.RefCount += delta
408
-		c, ok = a.subnets[c.ParentKey]
409
-	}
410
-}
411
-
412
-func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
330
+func (a *Allocator) insertBitMask(store datastore.DataStore, key SubnetKey, pool *net.IPNet) error {
413 331
 	log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String())
414 332
 	ipVer := getAddressVersion(pool.IP)
415 333
 	ones, bits := pool.Mask.Size()
... ...
@@ -421,7 +236,7 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
421 421
 	}
422 422
 
423 423
 	// Generate the new address masks. AddressMask content may come from datastore
424
-	h, err := bitseq.NewHandle(dsDataKey, a.store, key.String(), numAddresses)
424
+	h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses)
425 425
 	if err != nil {
426 426
 		return err
427 427
 	}
... ...
@@ -434,17 +249,16 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
434 434
 	a.Lock()
435 435
 	a.addresses[key] = h
436 436
 	a.Unlock()
437
-
438 437
 	return nil
439 438
 }
440 439
 
441
-func (a *Allocator) retrieveBitmask(k SubnetKey, n *net.IPNet) (*bitseq.Handle, error) {
440
+func (a *Allocator) retrieveBitmask(ds datastore.DataStore, k SubnetKey, n *net.IPNet) (*bitseq.Handle, error) {
442 441
 	a.Lock()
443 442
 	bm, ok := a.addresses[k]
444 443
 	a.Unlock()
445 444
 	if !ok {
446 445
 		log.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String())
447
-		if err := a.insertBitMask(k, n); err != nil {
446
+		if err := a.insertBitMask(ds, k, n); err != nil {
448 447
 			return nil, fmt.Errorf("could not find bitmask in datastore for %s", k.String())
449 448
 		}
450 449
 		a.Lock()
... ...
@@ -475,18 +289,23 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
475 475
 		return nil, fmt.Errorf("no default pool availbale for non-default addresss spaces")
476 476
 	}
477 477
 
478
+	cfg, err := a.getPoolsConfig(as)
479
+	if err != nil {
480
+		return nil, err
481
+	}
482
+
478 483
 	for _, nw := range a.getPredefineds(as) {
479 484
 		if v != getAddressVersion(nw.IP) {
480 485
 			continue
481 486
 		}
482
-		a.Lock()
483
-		_, ok := a.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}]
484
-		a.Unlock()
487
+		cfg.Lock()
488
+		_, ok := cfg.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}]
489
+		cfg.Unlock()
485 490
 		if ok {
486 491
 			continue
487 492
 		}
488 493
 
489
-		if !a.contains(as, nw) {
494
+		if !cfg.contains(as, nw) {
490 495
 			if as == localAddressSpace {
491 496
 				if err := netutils.CheckRouteOverlaps(nw); err == nil {
492 497
 					return nw, nil
... ...
@@ -500,38 +319,6 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
500 500
 	return nil, types.NotFoundErrorf("could not find an available predefined network")
501 501
 }
502 502
 
503
-// Check subnets size. In case configured subnet is v6 and host size is
504
-// greater than 32 bits, adjust subnet to /96.
505
-func adjustAndCheckSubnetSize(subnet *net.IPNet) (*net.IPNet, error) {
506
-	ones, bits := subnet.Mask.Size()
507
-	if v6 == getAddressVersion(subnet.IP) {
508
-		if ones < minNetSizeV6 {
509
-			return nil, ipamapi.ErrInvalidPool
510
-		}
511
-		if ones < minNetSizeV6Eff {
512
-			newMask := net.CIDRMask(minNetSizeV6Eff, bits)
513
-			return &net.IPNet{IP: subnet.IP, Mask: newMask}, nil
514
-		}
515
-	} else {
516
-		if ones < minNetSize {
517
-			return nil, ipamapi.ErrInvalidPool
518
-		}
519
-	}
520
-	return subnet, nil
521
-}
522
-
523
-// Checks whether the passed subnet is a superset or subset of any of the subset in the db
524
-func (a *Allocator) contains(space string, nw *net.IPNet) bool {
525
-	for k, v := range a.subnets {
526
-		if space == k.AddressSpace && k.ChildSubnet == "" {
527
-			if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) {
528
-				return true
529
-			}
530
-		}
531
-	}
532
-	return false
533
-}
534
-
535 503
 // RequestAddress returns an address from the specified pool ID
536 504
 func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
537 505
 	k := SubnetKey{}
... ...
@@ -539,26 +326,31 @@ func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s
539 539
 		return nil, nil, types.BadRequestErrorf("invalid pool id: %s", poolID)
540 540
 	}
541 541
 
542
-	a.Lock()
543
-	p, ok := a.subnets[k]
542
+	cfg, err := a.getPoolsConfig(k.AddressSpace)
543
+	if err != nil {
544
+		return nil, nil, err
545
+	}
546
+
547
+	cfg.Lock()
548
+	p, ok := cfg.subnets[k]
544 549
 	if !ok {
545
-		a.Unlock()
550
+		cfg.Unlock()
546 551
 		return nil, nil, types.NotFoundErrorf("cannot find address pool for poolID:%s", poolID)
547 552
 	}
548 553
 
549 554
 	if prefAddress != nil && !p.Pool.Contains(prefAddress) {
550
-		a.Unlock()
555
+		cfg.Unlock()
551 556
 		return nil, nil, ipamapi.ErrIPOutOfRange
552 557
 	}
553 558
 
554 559
 	c := p
555 560
 	for c.Range != nil {
556 561
 		k = c.ParentKey
557
-		c, ok = a.subnets[k]
562
+		c, ok = cfg.subnets[k]
558 563
 	}
559
-	a.Unlock()
564
+	cfg.Unlock()
560 565
 
561
-	bm, err := a.retrieveBitmask(k, c.Pool)
566
+	bm, err := a.retrieveBitmask(cfg.ds, k, c.Pool)
562 567
 	if err != nil {
563 568
 		return nil, nil, fmt.Errorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v",
564 569
 			k.String(), prefAddress, poolID, err)
... ...
@@ -578,24 +370,29 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
578 578
 		return types.BadRequestErrorf("invalid pool id: %s", poolID)
579 579
 	}
580 580
 
581
-	a.Lock()
582
-	p, ok := a.subnets[k]
581
+	cfg, err := a.getPoolsConfig(k.AddressSpace)
582
+	if err != nil {
583
+		return err
584
+	}
585
+
586
+	cfg.Lock()
587
+	p, ok := cfg.subnets[k]
583 588
 	if !ok {
584
-		a.Unlock()
589
+		cfg.Unlock()
585 590
 		return ipamapi.ErrBadPool
586 591
 	}
587 592
 
588 593
 	if address == nil || !p.Pool.Contains(address) {
589
-		a.Unlock()
594
+		cfg.Unlock()
590 595
 		return ipamapi.ErrInvalidRequest
591 596
 	}
592 597
 
593 598
 	c := p
594 599
 	for c.Range != nil {
595 600
 		k = c.ParentKey
596
-		c = a.subnets[k]
601
+		c = cfg.subnets[k]
597 602
 	}
598
-	a.Unlock()
603
+	cfg.Unlock()
599 604
 
600 605
 	mask := p.Pool.Mask
601 606
 	if p.Range != nil {
... ...
@@ -606,7 +403,7 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
606 606
 		return fmt.Errorf("failed to release address %s: %v", address.String(), err)
607 607
 	}
608 608
 
609
-	bm, err := a.retrieveBitmask(k, c.Pool)
609
+	bm, err := cfg.alloc.retrieveBitmask(cfg.ds, k, c.Pool)
610 610
 	if err != nil {
611 611
 		return fmt.Errorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v",
612 612
 			k.String(), address, poolID, err)
... ...
@@ -652,10 +449,19 @@ func (a *Allocator) DumpDatabase() string {
652 652
 	a.Lock()
653 653
 	defer a.Unlock()
654 654
 
655
-	s := fmt.Sprintf("\n\nPoolData")
656
-	for k, config := range a.subnets {
655
+	s := fmt.Sprintf("\n\nLocal Pool Config")
656
+	a.localSubnets.Lock()
657
+	for k, config := range a.localSubnets.subnets {
657 658
 		s = fmt.Sprintf("%s%s", s, fmt.Sprintf("\n%v: %v", k, config))
658 659
 	}
660
+	a.localSubnets.Unlock()
661
+
662
+	s = fmt.Sprintf("%s\n\nGlobal Pool Config", s)
663
+	a.globalSubnets.Lock()
664
+	for k, config := range a.globalSubnets.subnets {
665
+		s = fmt.Sprintf("%s%s", s, fmt.Sprintf("\n%v: %v", k, config))
666
+	}
667
+	a.globalSubnets.Unlock()
659 668
 
660 669
 	s = fmt.Sprintf("%s\n\nBitmasks", s)
661 670
 	for k, bm := range a.addresses {
... ...
@@ -663,95 +469,3 @@ func (a *Allocator) DumpDatabase() string {
663 663
 	}
664 664
 	return s
665 665
 }
666
-
667
-// It generates the ip address in the passed subnet specified by
668
-// the passed host address ordinal
669
-func generateAddress(ordinal uint32, network *net.IPNet) net.IP {
670
-	var address [16]byte
671
-
672
-	// Get network portion of IP
673
-	if getAddressVersion(network.IP) == v4 {
674
-		copy(address[:], network.IP.To4())
675
-	} else {
676
-		copy(address[:], network.IP)
677
-	}
678
-
679
-	end := len(network.Mask)
680
-	addIntToIP(address[:end], ordinal)
681
-
682
-	return net.IP(address[:end])
683
-}
684
-
685
-func getAddressVersion(ip net.IP) ipVersion {
686
-	if ip.To4() == nil {
687
-		return v6
688
-	}
689
-	return v4
690
-}
691
-
692
-// Adds the ordinal IP to the current array
693
-// 192.168.0.0 + 53 => 192.168.53
694
-func addIntToIP(array []byte, ordinal uint32) {
695
-	for i := len(array) - 1; i >= 0; i-- {
696
-		array[i] |= (byte)(ordinal & 0xff)
697
-		ordinal >>= 8
698
-	}
699
-}
700
-
701
-// Convert an ordinal to the respective IP address
702
-func ipToUint32(ip []byte) uint32 {
703
-	value := uint32(0)
704
-	for i := 0; i < len(ip); i++ {
705
-		j := len(ip) - 1 - i
706
-		value += uint32(ip[i]) << uint(j*8)
707
-	}
708
-	return value
709
-}
710
-
711
-func initLocalPredefinedPools() []*net.IPNet {
712
-	pl := make([]*net.IPNet, 0, 274)
713
-	mask := []byte{255, 255, 0, 0}
714
-	for i := 17; i < 32; i++ {
715
-		pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
716
-	}
717
-	for i := 0; i < 256; i++ {
718
-		pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), 0, 0}, Mask: mask})
719
-	}
720
-	mask24 := []byte{255, 255, 255, 0}
721
-	for i := 42; i < 45; i++ {
722
-		pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i), 0}, Mask: mask24})
723
-	}
724
-	return pl
725
-}
726
-
727
-func initGlobalPredefinedPools() []*net.IPNet {
728
-	pl := make([]*net.IPNet, 0, 256*256)
729
-	mask := []byte{255, 255, 255, 0}
730
-	for i := 0; i < 256; i++ {
731
-		for j := 0; j < 256; j++ {
732
-			pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
733
-		}
734
-	}
735
-	return pl
736
-}
737
-
738
-func getAddressRange(pool string) (*AddressRange, error) {
739
-	ip, nw, err := net.ParseCIDR(pool)
740
-	if err != nil {
741
-		return nil, ipamapi.ErrInvalidSubPool
742
-	}
743
-	lIP, e := types.GetHostPartIP(nw.IP, nw.Mask)
744
-	if e != nil {
745
-		return nil, fmt.Errorf("failed to compute range's lowest ip address: %v", e)
746
-	}
747
-	bIP, e := types.GetBroadcastIP(nw.IP, nw.Mask)
748
-	if e != nil {
749
-		return nil, fmt.Errorf("failed to compute range's broadcast ip address: %v", e)
750
-	}
751
-	hIP, e := types.GetHostPartIP(bIP, nw.Mask)
752
-	if e != nil {
753
-		return nil, fmt.Errorf("failed to compute range's highest ip address: %v", e)
754
-	}
755
-	nw.IP = ip
756
-	return &AddressRange{nw, ipToUint32(types.GetMinimalIP(lIP)), ipToUint32(types.GetMinimalIP(hIP))}, nil
757
-}
... ...
@@ -1,14 +1,15 @@
1 1
 package ipam
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"fmt"
6
+	"io/ioutil"
5 7
 	"net"
6 8
 	"os"
7 9
 	"testing"
8 10
 	"time"
9 11
 
10
-	"encoding/json"
11
-
12
+	"github.com/docker/libkv/store"
12 13
 	"github.com/docker/libnetwork/bitseq"
13 14
 	"github.com/docker/libnetwork/config"
14 15
 	"github.com/docker/libnetwork/datastore"
... ...
@@ -18,12 +19,35 @@ import (
18 18
 	"github.com/docker/libnetwork/types"
19 19
 )
20 20
 
21
-var ds datastore.DataStore
21
+const (
22
+	defaultPrefix = "/tmp/libnetwork/test/ipam"
23
+)
24
+
25
+// OptionBoltdbWithRandomDBFile function returns a random dir for local store backend
26
+func randomLocalStore() (datastore.DataStore, error) {
27
+	tmp, err := ioutil.TempFile("", "libnetwork-")
28
+	if err != nil {
29
+		return nil, fmt.Errorf("Error creating temp file: %v", err)
30
+	}
31
+	if err := tmp.Close(); err != nil {
32
+		return nil, fmt.Errorf("Error closing temp file: %v", err)
33
+	}
34
+	return datastore.NewDataStore(&config.DatastoreCfg{
35
+		Embedded: true,
36
+		Client: config.DatastoreClientCfg{
37
+			Provider: "boltdb",
38
+			Address:  defaultPrefix + tmp.Name(),
39
+			Config: &store.Config{
40
+				Bucket:            "libnetwork",
41
+				ConnectionTimeout: 3 * time.Second,
42
+			},
43
+		},
44
+	})
45
+}
22 46
 
23 47
 // enable w/ upper case
24
-func testMain(m *testing.M) {
48
+func TestMain(m *testing.M) {
25 49
 	var err error
26
-	ds, err = datastore.NewDataStore(&config.DatastoreCfg{Embedded: false, Client: config.DatastoreClientCfg{Provider: "consul", Address: "127.0.0.1:8500"}})
27 50
 	if err != nil {
28 51
 		fmt.Println(err)
29 52
 	}
... ...
@@ -31,16 +55,16 @@ func testMain(m *testing.M) {
31 31
 	os.Exit(m.Run())
32 32
 }
33 33
 
34
-func getAllocator(t *testing.T, subnet string) (*Allocator, string) {
35
-	a, err := NewAllocator(nil, ds)
34
+func getAllocator() (*Allocator, error) {
35
+	ds, err := randomLocalStore()
36 36
 	if err != nil {
37
-		t.Fatal(err)
37
+		return nil, err
38 38
 	}
39
-	poolID, _, _, err := a.RequestPool("default", subnet, "", nil, false)
39
+	a, err := NewAllocator(ds, nil)
40 40
 	if err != nil {
41
-		t.Fatal(err)
41
+		return nil, err
42 42
 	}
43
-	return a, poolID
43
+	return a, nil
44 44
 }
45 45
 
46 46
 func TestInt2IP2IntConversion(t *testing.T) {
... ...
@@ -70,7 +94,6 @@ func TestGetAddressVersion(t *testing.T) {
70 70
 }
71 71
 
72 72
 func TestKeyString(t *testing.T) {
73
-
74 73
 	k := &SubnetKey{AddressSpace: "default", Subnet: "172.27.0.0/16"}
75 74
 	expected := "default/172.27.0.0/16"
76 75
 	if expected != k.String() {
... ...
@@ -151,8 +174,10 @@ func TestPoolDataMarshal(t *testing.T) {
151 151
 }
152 152
 
153 153
 func TestSubnetsMarshal(t *testing.T) {
154
-	a, _ := NewAllocator(nil, nil)
155
-
154
+	a, err := getAllocator()
155
+	if err != nil {
156
+		t.Fatal(err)
157
+	}
156 158
 	pid0, _, _, err := a.RequestPool(localAddressSpace, "192.168.0.0/16", "", nil, false)
157 159
 	if err != nil {
158 160
 		t.Fatal(err)
... ...
@@ -166,9 +191,9 @@ func TestSubnetsMarshal(t *testing.T) {
166 166
 		t.Fatal(err)
167 167
 	}
168 168
 
169
-	ba := a.Value()
170
-	a.subnets = make(map[SubnetKey]*PoolData, 0)
171
-	if err := a.SetValue(ba); err != nil {
169
+	cfg := a.localSubnets
170
+	ba := cfg.Value()
171
+	if err := cfg.SetValue(ba); err != nil {
172 172
 		t.Fatal(err)
173 173
 	}
174 174
 
... ...
@@ -192,12 +217,13 @@ func TestSubnetsMarshal(t *testing.T) {
192 192
 }
193 193
 
194 194
 func TestAddSubnets(t *testing.T) {
195
-	a, err := NewAllocator(nil, nil)
195
+	a, err := getAllocator()
196 196
 	if err != nil {
197 197
 		t.Fatal(err)
198 198
 	}
199
+	a.addrSpace2Configs["abc"] = a.addrSpace2Configs[localAddressSpace]
199 200
 
200
-	pid0, _, _, err := a.RequestPool("default", "10.0.0.0/8", "", nil, false)
201
+	pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
201 202
 	if err != nil {
202 203
 		t.Fatalf("Unexpected failure in adding subnet")
203 204
 	}
... ...
@@ -236,22 +262,22 @@ func TestAddSubnets(t *testing.T) {
236 236
 		t.Fatalf("returned different pool id for same sub pool requests")
237 237
 	}
238 238
 
239
-	pid, _, _, err = a.RequestPool("default", "10.20.2.0/24", "", nil, false)
239
+	pid, _, _, err = a.RequestPool(localAddressSpace, "10.20.2.0/24", "", nil, false)
240 240
 	if err == nil {
241 241
 		t.Fatalf("Failed to detect overlapping subnets")
242 242
 	}
243 243
 
244
-	_, _, _, err = a.RequestPool("default", "10.128.0.0/9", "", nil, false)
244
+	_, _, _, err = a.RequestPool(localAddressSpace, "10.128.0.0/9", "", nil, false)
245 245
 	if err == nil {
246 246
 		t.Fatalf("Failed to detect overlapping subnets")
247 247
 	}
248 248
 
249
-	_, _, _, err = a.RequestPool("default", "1003:1:2:3:4:5:6::/112", "", nil, false)
249
+	_, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3:4:5:6::/112", "", nil, false)
250 250
 	if err != nil {
251 251
 		t.Fatalf("Failed to add v6 subnet: %s", err.Error())
252 252
 	}
253 253
 
254
-	_, _, _, err = a.RequestPool("default", "1003:1:2:3::/64", "", nil, false)
254
+	_, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3::/64", "", nil, false)
255 255
 	if err == nil {
256 256
 		t.Fatalf("Failed to detect overlapping v6 subnet")
257 257
 	}
... ...
@@ -259,34 +285,35 @@ func TestAddSubnets(t *testing.T) {
259 259
 
260 260
 func TestAddReleasePoolID(t *testing.T) {
261 261
 	var k0, k1, k2 SubnetKey
262
-	a, err := NewAllocator(nil, nil)
262
+
263
+	a, err := getAllocator()
263 264
 	if err != nil {
264 265
 		t.Fatal(err)
265 266
 	}
266
-
267
-	pid0, _, _, err := a.RequestPool("default", "10.0.0.0/8", "", nil, false)
267
+	subnets := a.localSubnets.subnets
268
+	pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
268 269
 	if err != nil {
269 270
 		t.Fatalf("Unexpected failure in adding pool")
270 271
 	}
271 272
 	if err := k0.FromString(pid0); err != nil {
272 273
 		t.Fatal(err)
273 274
 	}
274
-	if a.subnets[k0].RefCount != 1 {
275
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
275
+	if subnets[k0].RefCount != 1 {
276
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
276 277
 	}
277 278
 
278
-	pid1, _, _, err := a.RequestPool("default", "10.0.0.0/8", "10.0.0.0/16", nil, false)
279
+	pid1, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
279 280
 	if err != nil {
280 281
 		t.Fatalf("Unexpected failure in adding sub pool")
281 282
 	}
282 283
 	if err := k1.FromString(pid1); err != nil {
283 284
 		t.Fatal(err)
284 285
 	}
285
-	if a.subnets[k1].RefCount != 1 {
286
-		t.Fatalf("Unexpected ref count for %s: %d", k1, a.subnets[k1].RefCount)
286
+	if subnets[k1].RefCount != 1 {
287
+		t.Fatalf("Unexpected ref count for %s: %d", k1, subnets[k1].RefCount)
287 288
 	}
288 289
 
289
-	pid2, _, _, err := a.RequestPool("default", "10.0.0.0/8", "10.0.0.0/16", nil, false)
290
+	pid2, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
290 291
 	if err != nil {
291 292
 		t.Fatalf("Unexpected failure in adding sub pool")
292 293
 	}
... ...
@@ -296,63 +323,63 @@ func TestAddReleasePoolID(t *testing.T) {
296 296
 	if err := k2.FromString(pid2); err != nil {
297 297
 		t.Fatal(err)
298 298
 	}
299
-	if a.subnets[k2].RefCount != 2 {
300
-		t.Fatalf("Unexpected ref count for %s: %d", k2, a.subnets[k2].RefCount)
299
+	if subnets[k2].RefCount != 2 {
300
+		t.Fatalf("Unexpected ref count for %s: %d", k2, subnets[k2].RefCount)
301 301
 	}
302 302
 
303
-	if a.subnets[k0].RefCount != 3 {
304
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
303
+	if subnets[k0].RefCount != 3 {
304
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
305 305
 	}
306 306
 
307 307
 	if err := a.ReleasePool(pid1); err != nil {
308 308
 		t.Fatal(err)
309 309
 	}
310
-	if a.subnets[k0].RefCount != 2 {
311
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
310
+	if subnets[k0].RefCount != 2 {
311
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
312 312
 	}
313 313
 	if err := a.ReleasePool(pid0); err != nil {
314 314
 		t.Fatal(err)
315 315
 	}
316
-	if a.subnets[k0].RefCount != 1 {
317
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
316
+	if subnets[k0].RefCount != 1 {
317
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
318 318
 	}
319 319
 
320
-	pid00, _, _, err := a.RequestPool("default", "10.0.0.0/8", "", nil, false)
320
+	pid00, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
321 321
 	if err != nil {
322 322
 		t.Fatalf("Unexpected failure in adding pool")
323 323
 	}
324 324
 	if pid00 != pid0 {
325 325
 		t.Fatalf("main pool should still exist")
326 326
 	}
327
-	if a.subnets[k0].RefCount != 2 {
328
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
327
+	if subnets[k0].RefCount != 2 {
328
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
329 329
 	}
330 330
 
331 331
 	if err := a.ReleasePool(pid2); err != nil {
332 332
 		t.Fatal(err)
333 333
 	}
334
-	if a.subnets[k0].RefCount != 1 {
335
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
334
+	if subnets[k0].RefCount != 1 {
335
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
336 336
 	}
337 337
 
338 338
 	if err := a.ReleasePool(pid00); err != nil {
339 339
 		t.Fatal(err)
340 340
 	}
341
-	if bp, ok := a.subnets[k0]; ok {
341
+	if bp, ok := subnets[k0]; ok {
342 342
 		t.Fatalf("Base pool %s is still present: %v", k0, bp)
343 343
 	}
344 344
 
345
-	_, _, _, err = a.RequestPool("default", "10.0.0.0/8", "", nil, false)
345
+	_, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
346 346
 	if err != nil {
347 347
 		t.Fatalf("Unexpected failure in adding pool")
348 348
 	}
349
-	if a.subnets[k0].RefCount != 1 {
350
-		t.Fatalf("Unexpected ref count for %s: %d", k0, a.subnets[k0].RefCount)
349
+	if subnets[k0].RefCount != 1 {
350
+		t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
351 351
 	}
352 352
 }
353 353
 
354 354
 func TestPredefinedPool(t *testing.T) {
355
-	a, err := NewAllocator(nil, nil)
355
+	a, err := getAllocator()
356 356
 	if err != nil {
357 357
 		t.Fatal(err)
358 358
 	}
... ...
@@ -444,29 +471,31 @@ func TestAdjustAndCheckSubnet(t *testing.T) {
444 444
 }
445 445
 
446 446
 func TestRemoveSubnet(t *testing.T) {
447
-	a, err := NewAllocator(nil, nil)
447
+	a, err := getAllocator()
448 448
 	if err != nil {
449 449
 		t.Fatal(err)
450 450
 	}
451
+	a.addrSpace2Configs["splane"] = a.addrSpace2Configs[localAddressSpace]
451 452
 
452 453
 	input := []struct {
453 454
 		addrSpace string
454 455
 		subnet    string
456
+		v6        bool
455 457
 	}{
456
-		{"default", "192.168.0.0/16"},
457
-		{"default", "172.17.0.0/16"},
458
-		{"default", "10.0.0.0/8"},
459
-		{"default", "2002:1:2:3:4:5:ffff::/112"},
460
-		{"splane", "172.17.0.0/16"},
461
-		{"splane", "10.0.0.0/8"},
462
-		{"splane", "2002:1:2:3:4:5:6::/112"},
463
-		{"splane", "2002:1:2:3:4:5:ffff::/112"},
458
+		{localAddressSpace, "192.168.0.0/16", false},
459
+		{localAddressSpace, "172.17.0.0/16", false},
460
+		{localAddressSpace, "10.0.0.0/8", false},
461
+		{localAddressSpace, "2002:1:2:3:4:5:ffff::/112", false},
462
+		{"splane", "172.17.0.0/16", false},
463
+		{"splane", "10.0.0.0/8", false},
464
+		{"splane", "2002:1:2:3:4:5:6::/112", true},
465
+		{"splane", "2002:1:2:3:4:5:ffff::/112", true},
464 466
 	}
465 467
 
466 468
 	poolIDs := make([]string, len(input))
467 469
 
468 470
 	for ind, i := range input {
469
-		if poolIDs[ind], _, _, err = a.RequestPool(i.addrSpace, i.subnet, "", nil, false); err != nil {
471
+		if poolIDs[ind], _, _, err = a.RequestPool(i.addrSpace, i.subnet, "", nil, i.v6); err != nil {
470 472
 			t.Fatalf("Failed to apply input. Can't proceed: %s", err.Error())
471 473
 		}
472 474
 	}
... ...
@@ -479,10 +508,11 @@ func TestRemoveSubnet(t *testing.T) {
479 479
 }
480 480
 
481 481
 func TestGetSameAddress(t *testing.T) {
482
-	a, err := NewAllocator(nil, nil)
482
+	a, err := getAllocator()
483 483
 	if err != nil {
484 484
 		t.Fatal(err)
485 485
 	}
486
+	a.addrSpace2Configs["giallo"] = a.addrSpace2Configs[localAddressSpace]
486 487
 
487 488
 	pid, _, _, err := a.RequestPool("giallo", "192.168.100.0/24", "", nil, false)
488 489
 	if err != nil {
... ...
@@ -502,10 +532,11 @@ func TestGetSameAddress(t *testing.T) {
502 502
 }
503 503
 
504 504
 func TestRequestReleaseAddressFromSubPool(t *testing.T) {
505
-	a, err := NewAllocator(nil, nil)
505
+	a, err := getAllocator()
506 506
 	if err != nil {
507 507
 		t.Fatal(err)
508 508
 	}
509
+	a.addrSpace2Configs["rosso"] = a.addrSpace2Configs[localAddressSpace]
509 510
 
510 511
 	poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false)
511 512
 	if err != nil {
... ...
@@ -587,11 +618,16 @@ func TestRequestSyntaxCheck(t *testing.T) {
587 587
 		pool      = "192.168.0.0/16"
588 588
 		subPool   = "192.168.0.0/24"
589 589
 		addrSpace = "green"
590
+		err       error
590 591
 	)
591 592
 
592
-	a, _ := NewAllocator(nil, nil)
593
+	a, err := getAllocator()
594
+	if err != nil {
595
+		t.Fatal(err)
596
+	}
597
+	a.addrSpace2Configs[addrSpace] = a.addrSpace2Configs[localAddressSpace]
593 598
 
594
-	_, _, _, err := a.RequestPool("", pool, "", nil, false)
599
+	_, _, _, err = a.RequestPool("", pool, "", nil, false)
595 600
 	if err == nil {
596 601
 		t.Fatalf("Failed to detect wrong request: empty address space")
597 602
 	}
... ...
@@ -661,12 +697,14 @@ func TestRequest(t *testing.T) {
661 661
 		{"10.0.0.0/8", 256, "10.0.1.0"},
662 662
 
663 663
 		{"192.168.128.0/18", 4*256 - 1, "192.168.131.255"},
664
-		{"192.168.240.0/20", 16*256 - 2, "192.168.255.254"},
664
+		/*
665
+			{"192.168.240.0/20", 16*256 - 2, "192.168.255.254"},
665 666
 
666
-		{"192.168.0.0/16", 256*256 - 2, "192.168.255.254"},
667
-		{"10.0.0.0/8", 2 * 256, "10.0.2.0"},
668
-		{"10.0.0.0/8", 5 * 256, "10.0.5.0"},
669
-		//{"10.0.0.0/8", 100 * 256 * 254, "10.99.255.254"},
667
+			{"192.168.0.0/16", 256*256 - 2, "192.168.255.254"},
668
+			{"10.0.0.0/8", 2 * 256, "10.0.2.0"},
669
+			{"10.0.0.0/8", 5 * 256, "10.0.5.0"},
670
+			{"10.0.0.0/8", 100 * 256 * 254, "10.99.255.254"},
671
+		*/
670 672
 	}
671 673
 
672 674
 	for _, d := range input {
... ...
@@ -676,12 +714,19 @@ func TestRequest(t *testing.T) {
676 676
 
677 677
 func TestRelease(t *testing.T) {
678 678
 	var (
679
-		err    error
680
-		subnet = "192.168.0.0/16"
679
+		subnet = "192.168.0.0/23"
681 680
 	)
682 681
 
683
-	a, pid := getAllocator(t, subnet)
684
-	bm := a.addresses[SubnetKey{"default", subnet, ""}]
682
+	a, err := getAllocator()
683
+	if err != nil {
684
+		t.Fatal(err)
685
+	}
686
+	pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
687
+	if err != nil {
688
+		t.Fatal(err)
689
+	}
690
+
691
+	bm := a.addresses[SubnetKey{localAddressSpace, subnet, ""}]
685 692
 
686 693
 	// Allocate all addresses
687 694
 	for err != ipamapi.ErrNoAvailableIPs {
... ...
@@ -711,8 +756,8 @@ func TestRelease(t *testing.T) {
711 711
 
712 712
 		{"192.168.1.3"},
713 713
 
714
-		{"192.168.255.253"},
715
-		{"192.168.255.254"},
714
+		{"192.168.1.253"},
715
+		{"192.168.1.254"},
716 716
 	}
717 717
 
718 718
 	// One by one, relase the address and request again. We should get the same IP
... ...
@@ -773,13 +818,19 @@ func assertGetAddress(t *testing.T, subnet string) {
773 773
 
774 774
 func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP string) {
775 775
 	var (
776
-		err       error
777 776
 		nw        *net.IPNet
778 777
 		printTime = false
779 778
 	)
780 779
 
781 780
 	lastIP := net.ParseIP(lastExpectedIP)
782
-	a, pid := getAllocator(t, subnet)
781
+	a, err := getAllocator()
782
+	if err != nil {
783
+		t.Fatal(err)
784
+	}
785
+	pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
786
+	if err != nil {
787
+		t.Fatal(err)
788
+	}
783 789
 
784 790
 	i := 0
785 791
 	start := time.Now()
... ...
@@ -795,31 +846,31 @@ func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP str
795 795
 	}
796 796
 }
797 797
 
798
-func benchmarkRequest(subnet string) {
799
-	var err error
800
-
801
-	a, _ := NewAllocator(nil, nil)
802
-	pid, _, _, _ := a.RequestPool("default", subnet, "", nil, false)
803
-
798
+func benchmarkRequest(b *testing.B, a *Allocator, subnet string) {
799
+	pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
804 800
 	for err != ipamapi.ErrNoAvailableIPs {
805 801
 		_, _, err = a.RequestAddress(pid, nil, nil)
806 802
 	}
807 803
 }
808 804
 
809 805
 func benchMarkRequest(subnet string, b *testing.B) {
806
+	a, _ := getAllocator()
810 807
 	for n := 0; n < b.N; n++ {
811
-		benchmarkRequest(subnet)
808
+		benchmarkRequest(b, a, subnet)
812 809
 	}
813 810
 }
814 811
 
815 812
 func BenchmarkRequest_24(b *testing.B) {
816
-	benchmarkRequest("10.0.0.0/24")
813
+	a, _ := getAllocator()
814
+	benchmarkRequest(b, a, "10.0.0.0/24")
817 815
 }
818 816
 
819 817
 func BenchmarkRequest_16(b *testing.B) {
820
-	benchmarkRequest("10.0.0.0/16")
818
+	a, _ := getAllocator()
819
+	benchmarkRequest(b, a, "10.0.0.0/16")
821 820
 }
822 821
 
823 822
 func BenchmarkRequest_8(b *testing.B) {
824
-	benchmarkRequest("10.0.0.0/8")
823
+	a, _ := getAllocator()
824
+	benchmarkRequest(b, a, "10.0.0.0/8")
825 825
 }
... ...
@@ -4,95 +4,77 @@ import (
4 4
 	"encoding/json"
5 5
 
6 6
 	log "github.com/Sirupsen/logrus"
7
+	"github.com/docker/libkv/store"
7 8
 	"github.com/docker/libnetwork/datastore"
8 9
 	"github.com/docker/libnetwork/types"
9 10
 )
10 11
 
11 12
 // Key provides the Key to be used in KV Store
12
-func (a *Allocator) Key() []string {
13
-	a.Lock()
14
-	defer a.Unlock()
15
-	return []string{dsConfigKey}
13
+func (cfg *PoolsConfig) Key() []string {
14
+	cfg.Lock()
15
+	defer cfg.Unlock()
16
+	return []string{cfg.id}
16 17
 }
17 18
 
18 19
 // KeyPrefix returns the immediate parent key that can be used for tree walk
19
-func (a *Allocator) KeyPrefix() []string {
20
-	a.Lock()
21
-	defer a.Unlock()
20
+func (cfg *PoolsConfig) KeyPrefix() []string {
21
+	cfg.Lock()
22
+	defer cfg.Unlock()
22 23
 	return []string{dsConfigKey}
23 24
 }
24 25
 
25 26
 // Value marshals the data to be stored in the KV store
26
-func (a *Allocator) Value() []byte {
27
-	a.Lock()
28
-	defer a.Unlock()
29
-
30
-	if a.subnets == nil {
31
-		return []byte{}
32
-	}
33
-	m := map[string]interface{}{}
34
-	for k, v := range a.subnets {
35
-		m[k.String()] = v
36
-	}
37
-
38
-	b, err := json.Marshal(m)
27
+func (cfg *PoolsConfig) Value() []byte {
28
+	b, err := json.Marshal(cfg)
39 29
 	if err != nil {
40
-		log.Warnf("Failed to marshal ipam configured subnets")
30
+		log.Warnf("Failed to marshal ipam configured pools: %v", err)
41 31
 		return nil
42 32
 	}
43 33
 	return b
44 34
 }
45 35
 
46 36
 // SetValue unmarshalls the data from the KV store.
47
-func (a *Allocator) SetValue(value []byte) error {
48
-	var m map[string]*PoolData
49
-	err := json.Unmarshal(value, &m)
50
-	if err != nil {
37
+func (cfg *PoolsConfig) SetValue(value []byte) error {
38
+	rc := &PoolsConfig{subnets: make(map[SubnetKey]*PoolData)}
39
+	if err := json.Unmarshal(value, rc); err != nil {
51 40
 		return err
52 41
 	}
53
-	for ks, d := range m {
54
-		k := SubnetKey{}
55
-		if err := k.FromString(ks); err != nil {
56
-			return err
57
-		}
58
-		a.subnets[k] = d
59
-	}
42
+	cfg.subnets = rc.subnets
60 43
 	return nil
61 44
 }
62 45
 
63 46
 // Index returns the latest DB Index as seen by this object
64
-func (a *Allocator) Index() uint64 {
65
-	a.Lock()
66
-	defer a.Unlock()
67
-	return a.dbIndex
47
+func (cfg *PoolsConfig) Index() uint64 {
48
+	cfg.Lock()
49
+	defer cfg.Unlock()
50
+	return cfg.dbIndex
68 51
 }
69 52
 
70 53
 // SetIndex method allows the datastore to store the latest DB Index into this object
71
-func (a *Allocator) SetIndex(index uint64) {
72
-	a.Lock()
73
-	a.dbIndex = index
74
-	a.dbExists = true
75
-	a.Unlock()
54
+func (cfg *PoolsConfig) SetIndex(index uint64) {
55
+	cfg.Lock()
56
+	cfg.dbIndex = index
57
+	cfg.dbExists = true
58
+	cfg.Unlock()
76 59
 }
77 60
 
78 61
 // Exists method is true if this object has been stored in the DB.
79
-func (a *Allocator) Exists() bool {
80
-	a.Lock()
81
-	defer a.Unlock()
82
-	return a.dbExists
62
+func (cfg *PoolsConfig) Exists() bool {
63
+	cfg.Lock()
64
+	defer cfg.Unlock()
65
+	return cfg.dbExists
83 66
 }
84 67
 
85 68
 // Skip provides a way for a KV Object to avoid persisting it in the KV Store
86
-func (a *Allocator) Skip() bool {
69
+func (cfg *PoolsConfig) Skip() bool {
87 70
 	return false
88 71
 }
89 72
 
90
-func (a *Allocator) watchForChanges() error {
91
-	if a.store == nil {
73
+func (cfg *PoolsConfig) watchForChanges() error {
74
+	if cfg.ds == nil {
92 75
 		return nil
93 76
 	}
94
-
95
-	kvpChan, err := a.store.KVStore().Watch(datastore.Key(a.Key()...), nil)
77
+	kvpChan, err := cfg.ds.KVStore().Watch(datastore.Key(cfg.Key()...), nil)
96 78
 	if err != nil {
97 79
 		return err
98 80
 	}
... ...
@@ -101,7 +83,7 @@ func (a *Allocator) watchForChanges() error {
101 101
 			select {
102 102
 			case kvPair := <-kvpChan:
103 103
 				if kvPair != nil {
104
-					a.subnetConfigFromStore(kvPair)
104
+					cfg.readFromKey(kvPair)
105 105
 				}
106 106
 			}
107 107
 		}
... ...
@@ -109,50 +91,40 @@ func (a *Allocator) watchForChanges() error {
109 109
 	return nil
110 110
 }
111 111
 
112
-func (a *Allocator) readFromStore() error {
113
-	a.Lock()
114
-	store := a.store
115
-	a.Unlock()
116
-
117
-	if store == nil {
112
+func (cfg *PoolsConfig) writeToStore() error {
113
+	if cfg.ds == nil {
118 114
 		return nil
119 115
 	}
120
-
121
-	kvPair, err := a.store.KVStore().Get(datastore.Key(a.Key()...))
122
-	if err != nil {
123
-		return err
116
+	err := cfg.ds.PutObjectAtomic(cfg)
117
+	if err == datastore.ErrKeyModified {
118
+		return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err)
124 119
 	}
125
-
126
-	a.subnetConfigFromStore(kvPair)
127
-
128
-	return nil
120
+	return err
129 121
 }
130 122
 
131
-func (a *Allocator) writeToStore() error {
132
-	a.Lock()
133
-	store := a.store
134
-	a.Unlock()
135
-	if store == nil {
123
+func (cfg *PoolsConfig) readFromStore() error {
124
+	if cfg.ds == nil {
136 125
 		return nil
137 126
 	}
138
-	err := store.PutObjectAtomic(a)
139
-	if err == datastore.ErrKeyModified {
140
-		return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err)
127
+	return cfg.ds.GetObject(datastore.Key(cfg.Key()...), cfg)
128
+}
129
+
130
+func (cfg *PoolsConfig) readFromKey(kvPair *store.KVPair) {
131
+	if cfg.dbIndex < kvPair.LastIndex {
132
+		cfg.SetValue(kvPair.Value)
133
+		cfg.dbIndex = kvPair.LastIndex
134
+		cfg.dbExists = true
141 135
 	}
142
-	return err
143 136
 }
144 137
 
145
-func (a *Allocator) deleteFromStore() error {
146
-	a.Lock()
147
-	store := a.store
148
-	a.Unlock()
149
-	if store == nil {
138
+func (cfg *PoolsConfig) deleteFromStore() error {
139
+	if cfg.ds == nil {
150 140
 		return nil
151 141
 	}
152
-	return store.DeleteObjectAtomic(a)
142
+	return cfg.ds.DeleteObjectAtomic(cfg)
153 143
 }
154 144
 
155 145
 // DataScope method returns the storage scope of the datastore
156
-func (a *Allocator) DataScope() datastore.DataScope {
157
-	return datastore.GlobalScope
146
+func (cfg *PoolsConfig) DataScope() datastore.DataScope {
147
+	return cfg.scope
158 148
 }
159 149
new file mode 100644
... ...
@@ -0,0 +1,302 @@
0
+package ipam
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+	"net"
6
+	"strings"
7
+	"sync"
8
+
9
+	"github.com/docker/libnetwork/datastore"
10
+	"github.com/docker/libnetwork/ipamapi"
11
+	"github.com/docker/libnetwork/types"
12
+)
13
+
14
+// SubnetKey is the pointer to the configured pools in each address space
15
+type SubnetKey struct {
16
+	AddressSpace string
17
+	Subnet       string
18
+	ChildSubnet  string
19
+}
20
+
21
+// PoolData contains the configured pool data
22
+type PoolData struct {
23
+	ParentKey SubnetKey
24
+	Pool      *net.IPNet
25
+	Range     *AddressRange `json:",omitempty"`
26
+	RefCount  int
27
+}
28
+
29
+// PoolsConfig contains the pool configurations
30
+type PoolsConfig struct {
31
+	subnets  map[SubnetKey]*PoolData
32
+	dbIndex  uint64
33
+	dbExists bool
34
+	id       string
35
+	scope    datastore.DataScope
36
+	ds       datastore.DataStore
37
+	alloc    *Allocator
38
+	sync.Mutex
39
+}
40
+
41
+// AddressRange specifies first and last ip ordinal which
42
+// identify a range in a a pool of addresses
43
+type AddressRange struct {
44
+	Sub        *net.IPNet
45
+	Start, End uint32
46
+}
47
+
48
+// String returns the string form of the AddressRange object
49
+func (r *AddressRange) String() string {
50
+	return fmt.Sprintf("Sub: %s, range [%d, %d]", r.Sub, r.Start, r.End)
51
+}
52
+
53
+// MarshalJSON returns the JSON encoding of the Range object
54
+func (r *AddressRange) MarshalJSON() ([]byte, error) {
55
+	m := map[string]interface{}{
56
+		"Sub":   r.Sub.String(),
57
+		"Start": r.Start,
58
+		"End":   r.End,
59
+	}
60
+	return json.Marshal(m)
61
+}
62
+
63
+// UnmarshalJSON decodes data into the Range object
64
+func (r *AddressRange) UnmarshalJSON(data []byte) error {
65
+	m := map[string]interface{}{}
66
+	err := json.Unmarshal(data, &m)
67
+	if err != nil {
68
+		return err
69
+	}
70
+	if r.Sub, err = types.ParseCIDR(m["Sub"].(string)); err != nil {
71
+		return err
72
+	}
73
+	r.Start = uint32(m["Start"].(float64))
74
+	r.End = uint32(m["End"].(float64))
75
+	return nil
76
+}
77
+
78
+// String returns the string form of the SubnetKey object
79
+func (s *SubnetKey) String() string {
80
+	k := fmt.Sprintf("%s/%s", s.AddressSpace, s.Subnet)
81
+	if s.ChildSubnet != "" {
82
+		k = fmt.Sprintf("%s/%s", k, s.ChildSubnet)
83
+	}
84
+	return k
85
+}
86
+
87
+// FromString populate the SubnetKey object reading it from string
88
+func (s *SubnetKey) FromString(str string) error {
89
+	if str == "" || !strings.Contains(str, "/") {
90
+		return fmt.Errorf("invalid string form for subnetkey: %s", str)
91
+	}
92
+
93
+	p := strings.Split(str, "/")
94
+	if len(p) != 3 && len(p) != 5 {
95
+		return fmt.Errorf("invalid string form for subnetkey: %s", str)
96
+	}
97
+	s.AddressSpace = p[0]
98
+	s.Subnet = fmt.Sprintf("%s/%s", p[1], p[2])
99
+	if len(p) == 5 {
100
+		s.ChildSubnet = fmt.Sprintf("%s/%s", p[3], p[4])
101
+	}
102
+
103
+	return nil
104
+}
105
+
106
+// String returns the string form of the PoolData object
107
+func (p *PoolData) String() string {
108
+	return fmt.Sprintf("ParentKey: %s, Pool: %s, Range: %s, RefCount: %d",
109
+		p.ParentKey.String(), p.Pool.String(), p.Range, p.RefCount)
110
+}
111
+
112
+// MarshalJSON returns the JSON encoding of the PoolData object
113
+func (p *PoolData) MarshalJSON() ([]byte, error) {
114
+	m := map[string]interface{}{
115
+		"ParentKey": p.ParentKey,
116
+		"RefCount":  p.RefCount,
117
+	}
118
+	if p.Pool != nil {
119
+		m["Pool"] = p.Pool.String()
120
+	}
121
+	if p.Range != nil {
122
+		m["Range"] = p.Range
123
+	}
124
+	return json.Marshal(m)
125
+}
126
+
127
+// UnmarshalJSON decodes data into the PoolData object
128
+func (p *PoolData) UnmarshalJSON(data []byte) error {
129
+	var (
130
+		err error
131
+		t   struct {
132
+			ParentKey SubnetKey
133
+			Pool      string
134
+			Range     *AddressRange `json:",omitempty"`
135
+			RefCount  int
136
+		}
137
+	)
138
+
139
+	if err = json.Unmarshal(data, &t); err != nil {
140
+		return err
141
+	}
142
+
143
+	p.ParentKey = t.ParentKey
144
+	p.Range = t.Range
145
+	p.RefCount = t.RefCount
146
+	if t.Pool != "" {
147
+		if p.Pool, err = types.ParseCIDR(t.Pool); err != nil {
148
+			return err
149
+		}
150
+	}
151
+
152
+	return nil
153
+}
154
+
155
+// MarshalJSON returns the JSON encoding of the PoolsConfig object
156
+func (cfg *PoolsConfig) MarshalJSON() ([]byte, error) {
157
+	cfg.Lock()
158
+	defer cfg.Unlock()
159
+
160
+	m := map[string]interface{}{
161
+		"Scope": string(cfg.scope),
162
+	}
163
+
164
+	if cfg.subnets != nil {
165
+		s := map[string]*PoolData{}
166
+		for k, v := range cfg.subnets {
167
+			s[k.String()] = v
168
+		}
169
+		m["Subnets"] = s
170
+	}
171
+
172
+	return json.Marshal(m)
173
+}
174
+
175
+// UnmarshalJSON decodes data into the PoolsConfig object
176
+func (cfg *PoolsConfig) UnmarshalJSON(data []byte) error {
177
+	cfg.Lock()
178
+	defer cfg.Unlock()
179
+
180
+	m := map[string]interface{}{}
181
+	err := json.Unmarshal(data, &m)
182
+	if err != nil {
183
+		return err
184
+	}
185
+
186
+	cfg.scope = datastore.LocalScope
187
+	s := m["Scope"].(string)
188
+	if s == string(datastore.GlobalScope) {
189
+		cfg.scope = datastore.GlobalScope
190
+	}
191
+
192
+	if v, ok := m["Subnets"]; ok {
193
+		sb, _ := json.Marshal(v)
194
+		var s map[string]*PoolData
195
+		err := json.Unmarshal(sb, &s)
196
+		if err != nil {
197
+			return err
198
+		}
199
+		for ks, v := range s {
200
+			k := SubnetKey{}
201
+			k.FromString(ks)
202
+			cfg.subnets[k] = v
203
+		}
204
+	}
205
+
206
+	return nil
207
+}
208
+
209
+func (cfg *PoolsConfig) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange) (func() error, error) {
210
+	cfg.Lock()
211
+	defer cfg.Unlock()
212
+
213
+	// Check if already allocated
214
+	if p, ok := cfg.subnets[k]; ok {
215
+		cfg.incRefCount(p, 1)
216
+		return func() error { return nil }, nil
217
+	}
218
+
219
+	// If master pool, check for overlap
220
+	if ipr == nil {
221
+		if cfg.contains(k.AddressSpace, nw) {
222
+			return nil, ipamapi.ErrPoolOverlap
223
+		}
224
+		// This is a new master pool, add it along with corresponding bitmask
225
+		cfg.subnets[k] = &PoolData{Pool: nw, RefCount: 1}
226
+		return func() error { return cfg.alloc.insertBitMask(cfg.ds, k, nw) }, nil
227
+	}
228
+
229
+	// This is a new non-master pool
230
+	p := &PoolData{
231
+		ParentKey: SubnetKey{AddressSpace: k.AddressSpace, Subnet: k.Subnet},
232
+		Pool:      nw,
233
+		Range:     ipr,
234
+		RefCount:  1,
235
+	}
236
+	cfg.subnets[k] = p
237
+
238
+	// Look for parent pool
239
+	pp, ok := cfg.subnets[p.ParentKey]
240
+	if ok {
241
+		cfg.incRefCount(pp, 1)
242
+		return func() error { return nil }, nil
243
+	}
244
+
245
+	// Parent pool does not exist, add it along with corresponding bitmask
246
+	cfg.subnets[p.ParentKey] = &PoolData{Pool: nw, RefCount: 1}
247
+	return func() error { return cfg.alloc.insertBitMask(cfg.ds, p.ParentKey, nw) }, nil
248
+}
249
+
250
+func (cfg *PoolsConfig) updatePoolDBOnRemoval(k SubnetKey) (func() error, error) {
251
+	cfg.Lock()
252
+	defer cfg.Unlock()
253
+
254
+	p, ok := cfg.subnets[k]
255
+	if !ok {
256
+		return nil, ipamapi.ErrBadPool
257
+	}
258
+
259
+	cfg.incRefCount(p, -1)
260
+
261
+	c := p
262
+	for ok {
263
+		if c.RefCount == 0 {
264
+			delete(cfg.subnets, k)
265
+			if c.Range == nil {
266
+				return func() error {
267
+					bm, err := cfg.alloc.retrieveBitmask(cfg.ds, k, c.Pool)
268
+					if err != nil {
269
+						return fmt.Errorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err)
270
+					}
271
+					return bm.Destroy()
272
+				}, nil
273
+			}
274
+		}
275
+		k = c.ParentKey
276
+		c, ok = cfg.subnets[k]
277
+	}
278
+
279
+	return func() error { return nil }, nil
280
+}
281
+
282
+func (cfg *PoolsConfig) incRefCount(p *PoolData, delta int) {
283
+	c := p
284
+	ok := true
285
+	for ok {
286
+		c.RefCount += delta
287
+		c, ok = cfg.subnets[c.ParentKey]
288
+	}
289
+}
290
+
291
+// Checks whether the passed subnet is a superset or subset of any of the subset in this config db
292
+func (cfg *PoolsConfig) contains(space string, nw *net.IPNet) bool {
293
+	for k, v := range cfg.subnets {
294
+		if space == k.AddressSpace && k.ChildSubnet == "" {
295
+			if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) {
296
+				return true
297
+			}
298
+		}
299
+	}
300
+	return false
301
+}
0 302
new file mode 100644
... ...
@@ -0,0 +1,128 @@
0
+package ipam
1
+
2
+import (
3
+	"fmt"
4
+	"net"
5
+
6
+	"github.com/docker/libnetwork/ipamapi"
7
+	"github.com/docker/libnetwork/types"
8
+)
9
+
10
+type ipVersion int
11
+
12
+const (
13
+	v4 = 4
14
+	v6 = 6
15
+)
16
+
17
+func getAddressRange(pool string) (*AddressRange, error) {
18
+	ip, nw, err := net.ParseCIDR(pool)
19
+	if err != nil {
20
+		return nil, ipamapi.ErrInvalidSubPool
21
+	}
22
+	lIP, e := types.GetHostPartIP(nw.IP, nw.Mask)
23
+	if e != nil {
24
+		return nil, fmt.Errorf("failed to compute range's lowest ip address: %v", e)
25
+	}
26
+	bIP, e := types.GetBroadcastIP(nw.IP, nw.Mask)
27
+	if e != nil {
28
+		return nil, fmt.Errorf("failed to compute range's broadcast ip address: %v", e)
29
+	}
30
+	hIP, e := types.GetHostPartIP(bIP, nw.Mask)
31
+	if e != nil {
32
+		return nil, fmt.Errorf("failed to compute range's highest ip address: %v", e)
33
+	}
34
+	nw.IP = ip
35
+	return &AddressRange{nw, ipToUint32(types.GetMinimalIP(lIP)), ipToUint32(types.GetMinimalIP(hIP))}, nil
36
+}
37
+
38
+func initLocalPredefinedPools() []*net.IPNet {
39
+	pl := make([]*net.IPNet, 0, 274)
40
+	mask := []byte{255, 255, 0, 0}
41
+	for i := 17; i < 32; i++ {
42
+		pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
43
+	}
44
+	for i := 0; i < 256; i++ {
45
+		pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), 0, 0}, Mask: mask})
46
+	}
47
+	mask24 := []byte{255, 255, 255, 0}
48
+	for i := 42; i < 45; i++ {
49
+		pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i), 0}, Mask: mask24})
50
+	}
51
+	return pl
52
+}
53
+
54
+func initGlobalPredefinedPools() []*net.IPNet {
55
+	pl := make([]*net.IPNet, 0, 256*256)
56
+	mask := []byte{255, 255, 255, 0}
57
+	for i := 0; i < 256; i++ {
58
+		for j := 0; j < 256; j++ {
59
+			pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
60
+		}
61
+	}
62
+	return pl
63
+}
64
+
65
+// Check subnets size. In case configured subnet is v6 and host size is
66
+// greater than 32 bits, adjust subnet to /96.
67
+func adjustAndCheckSubnetSize(subnet *net.IPNet) (*net.IPNet, error) {
68
+	ones, bits := subnet.Mask.Size()
69
+	if v6 == getAddressVersion(subnet.IP) {
70
+		if ones < minNetSizeV6 {
71
+			return nil, ipamapi.ErrInvalidPool
72
+		}
73
+		if ones < minNetSizeV6Eff {
74
+			newMask := net.CIDRMask(minNetSizeV6Eff, bits)
75
+			return &net.IPNet{IP: subnet.IP, Mask: newMask}, nil
76
+		}
77
+	} else {
78
+		if ones < minNetSize {
79
+			return nil, ipamapi.ErrInvalidPool
80
+		}
81
+	}
82
+	return subnet, nil
83
+}
84
+
85
+// It generates the ip address in the passed subnet specified by
86
+// the passed host address ordinal
87
+func generateAddress(ordinal uint32, network *net.IPNet) net.IP {
88
+	var address [16]byte
89
+
90
+	// Get network portion of IP
91
+	if getAddressVersion(network.IP) == v4 {
92
+		copy(address[:], network.IP.To4())
93
+	} else {
94
+		copy(address[:], network.IP)
95
+	}
96
+
97
+	end := len(network.Mask)
98
+	addIntToIP(address[:end], ordinal)
99
+
100
+	return net.IP(address[:end])
101
+}
102
+
103
+func getAddressVersion(ip net.IP) ipVersion {
104
+	if ip.To4() == nil {
105
+		return v6
106
+	}
107
+	return v4
108
+}
109
+
110
+// Adds the ordinal IP to the current array
111
+// 192.168.0.0 + 53 => 192.168.53
112
+func addIntToIP(array []byte, ordinal uint32) {
113
+	for i := len(array) - 1; i >= 0; i-- {
114
+		array[i] |= (byte)(ordinal & 0xff)
115
+		ordinal >>= 8
116
+	}
117
+}
118
+
119
+// Convert an ordinal to the respective IP address
120
+func ipToUint32(ip []byte) uint32 {
121
+	value := uint32(0)
122
+	for i := 0; i < len(ip); i++ {
123
+		j := len(ip) - 1 - i
124
+		value += uint32(ip[i]) << uint(j*8)
125
+	}
126
+	return value
127
+}