Browse code

Vendoring in libnetwork ipam support

* Pluggable IPAM driver support
* Performance and Scalability enhancements
* Libkv fixes in multiple backend stores

Signed-off-by: Madhu Venugopal <madhu@docker.com>

Madhu Venugopal authored on 2015/10/05 12:02:02
Showing 66 changed files
... ...
@@ -20,12 +20,12 @@ clone git github.com/tchap/go-patricia v2.1.0
20 20
 clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
21 21
 
22 22
 #get libnetwork packages
23
-clone git github.com/docker/libnetwork c3a9e0d8d0c53f3db251620e5f48470e267f292b
23
+clone git github.com/docker/libnetwork 0521fe53fc3e7d4e7c2e463800f36662c9169f20
24 24
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
25 25
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
26 26
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
27 27
 clone git github.com/hashicorp/serf 7151adcef72687bf95f451a2e0ba15cb19412bf2
28
-clone git github.com/docker/libkv ea7ff6ae76485ab93ac36799d3e13b1905787ffe
28
+clone git github.com/docker/libkv 958cd316db2bc916466bdcc632a3188d62ce6e87
29 29
 clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
30 30
 clone git github.com/vishvananda/netlink 4b5dce31de6d42af5bb9811c6d265472199e0fec
31 31
 clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
... ...
@@ -68,9 +68,16 @@ func main() {
68 68
 
69 69
 You can find other usage examples for `libkv` under the `docker/swarm` or `docker/libnetwork` repositories.
70 70
 
71
+## Supported versions
72
+
73
+`libkv` supports:
74
+- Consul version >= `0.5.1` because it uses Sessions with `Delete` behavior for the use of `TTLs` (mimics zookeeper's Ephemeral node support), If you don't plan to use `TTLs`: you can use Consul version `0.4.0+`.
75
+- Etcd version >= `2.0` because it uses the `2.0.0` branch of the `coreos/go-etcd` client, this might change in the future as the support for `APIv3` comes along.
76
+- Zookeeper version >= `3.4.5`. Although this might work with previous version but this remains untested as of now.
77
+
71 78
 ## TLS
72 79
 
73
-The etcd backend supports etcd servers that require TLS Client Authentication.  Zookeeper and Consul support are planned.  This feature is somewhat experimental and the store.ClientTLSConfig struct may change to accommodate the additional backends.
80
+The etcd backend supports etcd servers that require TLS Client Authentication. Zookeeper and Consul support are planned. This feature is somewhat experimental and the store.ClientTLSConfig struct may change to accommodate the additional backends.
74 81
 
75 82
 ## Warning
76 83
 
... ...
@@ -6,7 +6,9 @@ import (
6 6
 	"errors"
7 7
 	"os"
8 8
 	"path/filepath"
9
+	"sync"
9 10
 	"sync/atomic"
11
+	"time"
10 12
 
11 13
 	"github.com/boltdb/bolt"
12 14
 	"github.com/docker/libkv"
... ...
@@ -25,15 +27,29 @@ var (
25 25
 	ErrBoltAPIUnsupported = errors.New("API not supported by BoltDB backend")
26 26
 )
27 27
 
28
+const (
29
+	filePerm os.FileMode = 0644
30
+)
31
+
28 32
 //BoltDB type implements the Store interface
29 33
 type BoltDB struct {
30 34
 	client     *bolt.DB
31 35
 	boltBucket []byte
32 36
 	dbIndex    uint64
37
+	path       string
38
+	timeout    time.Duration
39
+	// By default libkv opens and closes the bolt DB connection  for every
40
+	// get/put operation. This allows multiple apps to use a Bolt DB at the
41
+	// same time.
42
+	// PersistConnection flag provides an option to override ths behavior.
43
+	// ie: open the connection in New and use it till Close is called.
44
+	PersistConnection bool
45
+	sync.Mutex
33 46
 }
34 47
 
35 48
 const (
36 49
 	libkvmetadatalen = 8
50
+	transientTimeout = time.Duration(10) * time.Second
37 51
 )
38 52
 
39 53
 // Register registers boltdb to libkv
... ...
@@ -43,6 +59,12 @@ func Register() {
43 43
 
44 44
 // New opens a new BoltDB connection to the specified path and bucket
45 45
 func New(endpoints []string, options *store.Config) (store.Store, error) {
46
+	var (
47
+		db          *bolt.DB
48
+		err         error
49
+		boltOptions *bolt.Options
50
+	)
51
+
46 52
 	if len(endpoints) > 1 {
47 53
 		return nil, ErrMultipleEndpointsUnsupported
48 54
 	}
... ...
@@ -52,39 +74,81 @@ func New(endpoints []string, options *store.Config) (store.Store, error) {
52 52
 	}
53 53
 
54 54
 	dir, _ := filepath.Split(endpoints[0])
55
-	if err := os.MkdirAll(dir, 0750); err != nil {
55
+	if err = os.MkdirAll(dir, 0750); err != nil {
56 56
 		return nil, err
57 57
 	}
58 58
 
59
-	var boltOptions *bolt.Options
60
-	if options != nil {
59
+	if options.PersistConnection {
61 60
 		boltOptions = &bolt.Options{Timeout: options.ConnectionTimeout}
62
-	}
63
-	db, err := bolt.Open(endpoints[0], 0644, boltOptions)
64
-	if err != nil {
65
-		return nil, err
61
+		db, err = bolt.Open(endpoints[0], filePerm, boltOptions)
62
+		if err != nil {
63
+			return nil, err
64
+		}
66 65
 	}
67 66
 
68
-	b := &BoltDB{}
67
+	b := &BoltDB{
68
+		client:            db,
69
+		path:              endpoints[0],
70
+		boltBucket:        []byte(options.Bucket),
71
+		timeout:           transientTimeout,
72
+		PersistConnection: options.PersistConnection,
73
+	}
69 74
 
70
-	b.client = db
71
-	b.boltBucket = []byte(options.Bucket)
72 75
 	return b, nil
73 76
 }
74 77
 
78
+func (b *BoltDB) reset() {
79
+	b.path = ""
80
+	b.boltBucket = []byte{}
81
+}
82
+
83
+func (b *BoltDB) getDBhandle() (*bolt.DB, error) {
84
+	var (
85
+		db  *bolt.DB
86
+		err error
87
+	)
88
+	if !b.PersistConnection {
89
+		boltOptions := &bolt.Options{Timeout: b.timeout}
90
+		if db, err = bolt.Open(b.path, filePerm, boltOptions); err != nil {
91
+			return nil, err
92
+		}
93
+		b.client = db
94
+	}
95
+
96
+	return b.client, nil
97
+}
98
+
99
+func (b *BoltDB) releaseDBhandle() {
100
+	if !b.PersistConnection {
101
+		b.client.Close()
102
+	}
103
+}
104
+
75 105
 // Get the value at "key". BoltDB doesn't provide an inbuilt last modified index with every kv pair. Its implemented by
76 106
 // by a atomic counter maintained by the libkv and appened to the value passed by the client.
77 107
 func (b *BoltDB) Get(key string) (*store.KVPair, error) {
78
-	var val []byte
108
+	var (
109
+		val []byte
110
+		db  *bolt.DB
111
+		err error
112
+	)
113
+	b.Lock()
114
+	defer b.Unlock()
115
+
116
+	if db, err = b.getDBhandle(); err != nil {
117
+		return nil, err
118
+	}
119
+	defer b.releaseDBhandle()
79 120
 
80
-	db := b.client
81
-	err := db.View(func(tx *bolt.Tx) error {
121
+	err = db.View(func(tx *bolt.Tx) error {
82 122
 		bucket := tx.Bucket(b.boltBucket)
83 123
 		if bucket == nil {
84
-			return (ErrBoltBucketNotFound)
124
+			return ErrBoltBucketNotFound
85 125
 		}
86 126
 
87
-		val = bucket.Get([]byte(key))
127
+		v := bucket.Get([]byte(key))
128
+		val = make([]byte, len(v))
129
+		copy(val, v)
88 130
 
89 131
 		return nil
90 132
 	})
... ...
@@ -104,11 +168,22 @@ func (b *BoltDB) Get(key string) (*store.KVPair, error) {
104 104
 
105 105
 //Put the key, value pair. index number metadata is prepended to the value
106 106
 func (b *BoltDB) Put(key string, value []byte, opts *store.WriteOptions) error {
107
-	var dbIndex uint64
108
-	db := b.client
107
+	var (
108
+		dbIndex uint64
109
+		db      *bolt.DB
110
+		err     error
111
+	)
112
+	b.Lock()
113
+	defer b.Unlock()
114
+
109 115
 	dbval := make([]byte, libkvmetadatalen)
110 116
 
111
-	err := db.Update(func(tx *bolt.Tx) error {
117
+	if db, err = b.getDBhandle(); err != nil {
118
+		return err
119
+	}
120
+	defer b.releaseDBhandle()
121
+
122
+	err = db.Update(func(tx *bolt.Tx) error {
112 123
 		bucket, err := tx.CreateBucketIfNotExists(b.boltBucket)
113 124
 		if err != nil {
114 125
 			return err
... ...
@@ -129,12 +204,22 @@ func (b *BoltDB) Put(key string, value []byte, opts *store.WriteOptions) error {
129 129
 
130 130
 //Delete the value for the given key.
131 131
 func (b *BoltDB) Delete(key string) error {
132
-	db := b.client
132
+	var (
133
+		db  *bolt.DB
134
+		err error
135
+	)
136
+	b.Lock()
137
+	defer b.Unlock()
138
+
139
+	if db, err = b.getDBhandle(); err != nil {
140
+		return err
141
+	}
142
+	defer b.releaseDBhandle()
133 143
 
134
-	err := db.Update(func(tx *bolt.Tx) error {
144
+	err = db.Update(func(tx *bolt.Tx) error {
135 145
 		bucket := tx.Bucket(b.boltBucket)
136 146
 		if bucket == nil {
137
-			return (ErrBoltBucketNotFound)
147
+			return ErrBoltBucketNotFound
138 148
 		}
139 149
 		err := bucket.Delete([]byte(key))
140 150
 		return err
... ...
@@ -144,13 +229,23 @@ func (b *BoltDB) Delete(key string) error {
144 144
 
145 145
 // Exists checks if the key exists inside the store
146 146
 func (b *BoltDB) Exists(key string) (bool, error) {
147
-	var val []byte
147
+	var (
148
+		val []byte
149
+		db  *bolt.DB
150
+		err error
151
+	)
152
+	b.Lock()
153
+	defer b.Unlock()
154
+
155
+	if db, err = b.getDBhandle(); err != nil {
156
+		return false, err
157
+	}
158
+	defer b.releaseDBhandle()
148 159
 
149
-	db := b.client
150
-	err := db.View(func(tx *bolt.Tx) error {
160
+	err = db.View(func(tx *bolt.Tx) error {
151 161
 		bucket := tx.Bucket(b.boltBucket)
152 162
 		if bucket == nil {
153
-			return (ErrBoltBucketNotFound)
163
+			return ErrBoltBucketNotFound
154 164
 		}
155 165
 
156 166
 		val = bucket.Get([]byte(key))
... ...
@@ -166,22 +261,35 @@ func (b *BoltDB) Exists(key string) (bool, error) {
166 166
 
167 167
 // List returns the range of keys starting with the passed in prefix
168 168
 func (b *BoltDB) List(keyPrefix string) ([]*store.KVPair, error) {
169
+	var (
170
+		db  *bolt.DB
171
+		err error
172
+	)
173
+	b.Lock()
174
+	defer b.Unlock()
175
+
169 176
 	kv := []*store.KVPair{}
170 177
 
171
-	db := b.client
172
-	err := db.View(func(tx *bolt.Tx) error {
178
+	if db, err = b.getDBhandle(); err != nil {
179
+		return nil, err
180
+	}
181
+	defer b.releaseDBhandle()
182
+
183
+	err = db.View(func(tx *bolt.Tx) error {
173 184
 		bucket := tx.Bucket(b.boltBucket)
174 185
 		if bucket == nil {
175
-			return (ErrBoltBucketNotFound)
186
+			return ErrBoltBucketNotFound
176 187
 		}
177 188
 
178 189
 		cursor := bucket.Cursor()
179 190
 		prefix := []byte(keyPrefix)
180 191
 
181
-		for key, val := cursor.Seek(prefix); bytes.HasPrefix(key, prefix); key, val = cursor.Next() {
192
+		for key, v := cursor.Seek(prefix); bytes.HasPrefix(key, prefix); key, v = cursor.Next() {
182 193
 
183
-			dbIndex := binary.LittleEndian.Uint64(val[:libkvmetadatalen])
184
-			val = val[libkvmetadatalen:]
194
+			dbIndex := binary.LittleEndian.Uint64(v[:libkvmetadatalen])
195
+			v = v[libkvmetadatalen:]
196
+			val := make([]byte, len(v))
197
+			copy(val, v)
185 198
 
186 199
 			kv = append(kv, &store.KVPair{
187 200
 				Key:       string(key),
... ...
@@ -201,22 +309,30 @@ func (b *BoltDB) List(keyPrefix string) ([]*store.KVPair, error) {
201 201
 // has not been modified in the meantime, throws an
202 202
 // error if this is the case
203 203
 func (b *BoltDB) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
204
-	var val []byte
205
-	var dbIndex uint64
204
+	var (
205
+		val []byte
206
+		db  *bolt.DB
207
+		err error
208
+	)
209
+	b.Lock()
210
+	defer b.Unlock()
206 211
 
207 212
 	if previous == nil {
208 213
 		return false, store.ErrPreviousNotSpecified
209 214
 	}
210
-	db := b.client
215
+	if db, err = b.getDBhandle(); err != nil {
216
+		return false, err
217
+	}
218
+	defer b.releaseDBhandle()
211 219
 
212
-	err := db.Update(func(tx *bolt.Tx) error {
220
+	err = db.Update(func(tx *bolt.Tx) error {
213 221
 		bucket := tx.Bucket(b.boltBucket)
214 222
 		if bucket == nil {
215 223
 			return ErrBoltBucketNotFound
216 224
 		}
217 225
 
218 226
 		val = bucket.Get([]byte(key))
219
-		dbIndex = binary.LittleEndian.Uint64(val[:libkvmetadatalen])
227
+		dbIndex := binary.LittleEndian.Uint64(val[:libkvmetadatalen])
220 228
 		if dbIndex != previous.LastIndex {
221 229
 			return store.ErrKeyModified
222 230
 		}
... ...
@@ -232,13 +348,23 @@ func (b *BoltDB) AtomicDelete(key string, previous *store.KVPair) (bool, error)
232 232
 // AtomicPut puts a value at "key" if the key has not been
233 233
 // modified since the last Put, throws an error if this is the case
234 234
 func (b *BoltDB) AtomicPut(key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) {
235
-	var val []byte
236
-	var dbIndex uint64
235
+	var (
236
+		val     []byte
237
+		dbIndex uint64
238
+		db      *bolt.DB
239
+		err     error
240
+	)
241
+	b.Lock()
242
+	defer b.Unlock()
243
+
237 244
 	dbval := make([]byte, libkvmetadatalen)
238 245
 
239
-	db := b.client
246
+	if db, err = b.getDBhandle(); err != nil {
247
+		return false, nil, err
248
+	}
249
+	defer b.releaseDBhandle()
240 250
 
241
-	err := db.Update(func(tx *bolt.Tx) error {
251
+	err = db.Update(func(tx *bolt.Tx) error {
242 252
 		var err error
243 253
 		bucket := tx.Bucket(b.boltBucket)
244 254
 		if bucket == nil {
... ...
@@ -285,18 +411,35 @@ func (b *BoltDB) AtomicPut(key string, value []byte, previous *store.KVPair, opt
285 285
 
286 286
 // Close the db connection to the BoltDB
287 287
 func (b *BoltDB) Close() {
288
-	db := b.client
288
+	b.Lock()
289
+	defer b.Unlock()
289 290
 
290
-	db.Close()
291
+	if !b.PersistConnection {
292
+		b.reset()
293
+	} else {
294
+		b.client.Close()
295
+	}
296
+	return
291 297
 }
292 298
 
293 299
 // DeleteTree deletes a range of keys with a given prefix
294 300
 func (b *BoltDB) DeleteTree(keyPrefix string) error {
295
-	db := b.client
296
-	err := db.Update(func(tx *bolt.Tx) error {
301
+	var (
302
+		db  *bolt.DB
303
+		err error
304
+	)
305
+	b.Lock()
306
+	defer b.Unlock()
307
+
308
+	if db, err = b.getDBhandle(); err != nil {
309
+		return err
310
+	}
311
+	defer b.releaseDBhandle()
312
+
313
+	err = db.Update(func(tx *bolt.Tx) error {
297 314
 		bucket := tx.Bucket(b.boltBucket)
298 315
 		if bucket == nil {
299
-			return (ErrBoltBucketNotFound)
316
+			return ErrBoltBucketNotFound
300 317
 		}
301 318
 
302 319
 		cursor := bucket.Cursor()
... ...
@@ -35,7 +35,8 @@ type Consul struct {
35 35
 }
36 36
 
37 37
 type consulLock struct {
38
-	lock *api.Lock
38
+	lock    *api.Lock
39
+	renewCh chan struct{}
39 40
 }
40 41
 
41 42
 // Register registers consul to libkv
... ...
@@ -87,7 +88,7 @@ func (s *Consul) setTLS(tls *tls.Config) {
87 87
 	s.config.Scheme = "https"
88 88
 }
89 89
 
90
-// SetTimeout sets the timout for connecting to Consul
90
+// SetTimeout sets the timeout for connecting to Consul
91 91
 func (s *Consul) setTimeout(time time.Duration) {
92 92
 	s.config.WaitTime = time
93 93
 }
... ...
@@ -360,32 +361,63 @@ func (s *Consul) WatchTree(directory string, stopCh <-chan struct{}) (<-chan []*
360 360
 // NewLock returns a handle to a lock struct which can
361 361
 // be used to provide mutual exclusion on a key
362 362
 func (s *Consul) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
363
-	consulOpts := &api.LockOptions{
363
+	lockOpts := &api.LockOptions{
364 364
 		Key: s.normalize(key),
365 365
 	}
366 366
 
367
+	lock := &consulLock{}
368
+
367 369
 	if options != nil {
368
-		consulOpts.Value = options.Value
370
+		// Set optional TTL on Lock
371
+		if options.TTL != 0 {
372
+			entry := &api.SessionEntry{
373
+				Behavior:  api.SessionBehaviorRelease, // Release the lock when the session expires
374
+				TTL:       (options.TTL / 2).String(), // Consul multiplies the TTL by 2x
375
+				LockDelay: 1 * time.Millisecond,       // Virtually disable lock delay
376
+			}
377
+
378
+			// Create the key session
379
+			session, _, err := s.client.Session().Create(entry, nil)
380
+			if err != nil {
381
+				return nil, err
382
+			}
383
+
384
+			// Place the session on lock
385
+			lockOpts.Session = session
386
+
387
+			// Renew the session ttl lock periodically
388
+			go s.client.Session().RenewPeriodic(entry.TTL, session, nil, options.RenewLock)
389
+			lock.renewCh = options.RenewLock
390
+		}
391
+
392
+		// Set optional value on Lock
393
+		if options.Value != nil {
394
+			lockOpts.Value = options.Value
395
+		}
369 396
 	}
370 397
 
371
-	l, err := s.client.LockOpts(consulOpts)
398
+	l, err := s.client.LockOpts(lockOpts)
372 399
 	if err != nil {
373 400
 		return nil, err
374 401
 	}
375 402
 
376
-	return &consulLock{lock: l}, nil
403
+	lock.lock = l
404
+	return lock, nil
377 405
 }
378 406
 
379 407
 // Lock attempts to acquire the lock and blocks while
380 408
 // doing so. It returns a channel that is closed if our
381 409
 // lock is lost or if an error occurs
382
-func (l *consulLock) Lock() (<-chan struct{}, error) {
383
-	return l.lock.Lock(nil)
410
+func (l *consulLock) Lock(stopChan chan struct{}) (<-chan struct{}, error) {
411
+	return l.lock.Lock(stopChan)
384 412
 }
385 413
 
386 414
 // Unlock the "key". Calling unlock while
387 415
 // not holding the lock will throw an error
388 416
 func (l *consulLock) Unlock() error {
417
+	if l.renewCh != nil {
418
+		close(l.renewCh)
419
+	}
389 420
 	return l.lock.Unlock()
390 421
 }
391 422
 
... ...
@@ -2,6 +2,7 @@ package etcd
2 2
 
3 3
 import (
4 4
 	"crypto/tls"
5
+	"errors"
5 6
 	"net"
6 7
 	"net/http"
7 8
 	"strings"
... ...
@@ -12,6 +13,13 @@ import (
12 12
 	"github.com/docker/libkv/store"
13 13
 )
14 14
 
15
+var (
16
+	// ErrAbortTryLock is thrown when a user stops trying to seek the lock
17
+	// by sending a signal to the stop chan, this is used to verify if the
18
+	// operation succeeded
19
+	ErrAbortTryLock = errors.New("lock operation aborted")
20
+)
21
+
15 22
 // Etcd is the receiver type for the
16 23
 // Store interface
17 24
 type Etcd struct {
... ...
@@ -19,12 +27,13 @@ type Etcd struct {
19 19
 }
20 20
 
21 21
 type etcdLock struct {
22
-	client   *etcd.Client
23
-	stopLock chan struct{}
24
-	key      string
25
-	value    string
26
-	last     *etcd.Response
27
-	ttl      uint64
22
+	client    *etcd.Client
23
+	stopLock  chan struct{}
24
+	stopRenew chan struct{}
25
+	key       string
26
+	value     string
27
+	last      *etcd.Response
28
+	ttl       uint64
28 29
 }
29 30
 
30 31
 const (
... ...
@@ -395,6 +404,7 @@ func (s *Etcd) DeleteTree(directory string) error {
395 395
 func (s *Etcd) NewLock(key string, options *store.LockOptions) (lock store.Locker, err error) {
396 396
 	var value string
397 397
 	ttl := uint64(time.Duration(defaultLockTTL).Seconds())
398
+	renewCh := make(chan struct{})
398 399
 
399 400
 	// Apply options on Lock
400 401
 	if options != nil {
... ...
@@ -404,14 +414,18 @@ func (s *Etcd) NewLock(key string, options *store.LockOptions) (lock store.Locke
404 404
 		if options.TTL != 0 {
405 405
 			ttl = uint64(options.TTL.Seconds())
406 406
 		}
407
+		if options.RenewLock != nil {
408
+			renewCh = options.RenewLock
409
+		}
407 410
 	}
408 411
 
409 412
 	// Create lock object
410 413
 	lock = &etcdLock{
411
-		client: s.client,
412
-		key:    key,
413
-		value:  value,
414
-		ttl:    ttl,
414
+		client:    s.client,
415
+		stopRenew: renewCh,
416
+		key:       key,
417
+		value:     value,
418
+		ttl:       ttl,
415 419
 	}
416 420
 
417 421
 	return lock, nil
... ...
@@ -420,13 +434,13 @@ func (s *Etcd) NewLock(key string, options *store.LockOptions) (lock store.Locke
420 420
 // Lock attempts to acquire the lock and blocks while
421 421
 // doing so. It returns a channel that is closed if our
422 422
 // lock is lost or if an error occurs
423
-func (l *etcdLock) Lock() (<-chan struct{}, error) {
423
+func (l *etcdLock) Lock(stopChan chan struct{}) (<-chan struct{}, error) {
424 424
 
425 425
 	key := store.Normalize(l.key)
426 426
 
427
-	// Lock holder channels
427
+	// Lock holder channel
428 428
 	lockHeld := make(chan struct{})
429
-	stopLocking := make(chan struct{})
429
+	stopLocking := l.stopRenew
430 430
 
431 431
 	var lastIndex uint64
432 432
 
... ...
@@ -454,7 +468,18 @@ func (l *etcdLock) Lock() (<-chan struct{}, error) {
454 454
 			// Seeker section
455 455
 			chW := make(chan *etcd.Response)
456 456
 			chWStop := make(chan bool)
457
-			l.waitLock(key, chW, chWStop)
457
+			free := make(chan bool)
458
+
459
+			go l.waitLock(key, chW, chWStop, free)
460
+
461
+			// Wait for the key to be available or for
462
+			// a signal to stop trying to lock the key
463
+			select {
464
+			case _ = <-free:
465
+				break
466
+			case _ = <-stopChan:
467
+				return nil, ErrAbortTryLock
468
+			}
458 469
 
459 470
 			// Delete or Expire event occured
460 471
 			// Retry
... ...
@@ -467,10 +492,10 @@ func (l *etcdLock) Lock() (<-chan struct{}, error) {
467 467
 // Hold the lock as long as we can
468 468
 // Updates the key ttl periodically until we receive
469 469
 // an explicit stop signal from the Unlock method
470
-func (l *etcdLock) holdLock(key string, lockHeld chan struct{}, stopLocking chan struct{}) {
470
+func (l *etcdLock) holdLock(key string, lockHeld chan struct{}, stopLocking <-chan struct{}) {
471 471
 	defer close(lockHeld)
472 472
 
473
-	update := time.NewTicker(defaultUpdateTime)
473
+	update := time.NewTicker(time.Duration(l.ttl) * time.Second / 3)
474 474
 	defer update.Stop()
475 475
 
476 476
 	var err error
... ...
@@ -490,11 +515,12 @@ func (l *etcdLock) holdLock(key string, lockHeld chan struct{}, stopLocking chan
490 490
 }
491 491
 
492 492
 // WaitLock simply waits for the key to be available for creation
493
-func (l *etcdLock) waitLock(key string, eventCh chan *etcd.Response, stopWatchCh chan bool) {
493
+func (l *etcdLock) waitLock(key string, eventCh chan *etcd.Response, stopWatchCh chan bool, free chan<- bool) {
494 494
 	go l.client.Watch(key, 0, false, eventCh, stopWatchCh)
495
+
495 496
 	for event := range eventCh {
496 497
 		if event.Action == "delete" || event.Action == "expire" {
497
-			return
498
+			free <- true
498 499
 		}
499 500
 	}
500 501
 }
... ...
@@ -43,6 +43,7 @@ type Config struct {
43 43
 	TLS               *tls.Config
44 44
 	ConnectionTimeout time.Duration
45 45
 	Bucket            string
46
+	PersistConnection bool
46 47
 }
47 48
 
48 49
 // ClientTLSConfig contains data for a Client TLS configuration in the form
... ...
@@ -113,13 +114,14 @@ type WriteOptions struct {
113 113
 
114 114
 // LockOptions contains optional request parameters
115 115
 type LockOptions struct {
116
-	Value []byte        // Optional, value to associate with the lock
117
-	TTL   time.Duration // Optional, expiration ttl associated with the lock
116
+	Value     []byte        // Optional, value to associate with the lock
117
+	TTL       time.Duration // Optional, expiration ttl associated with the lock
118
+	RenewLock chan struct{} // Optional, chan used to control and stop the session ttl renewal for the lock
118 119
 }
119 120
 
120 121
 // Locker provides locking mechanism on top of the store.
121 122
 // Similar to `sync.Lock` except it may return errors.
122 123
 type Locker interface {
123
-	Lock() (<-chan struct{}, error)
124
+	Lock(stopChan chan struct{}) (<-chan struct{}, error)
124 125
 	Unlock() error
125 126
 }
... ...
@@ -10,6 +10,9 @@ import (
10 10
 )
11 11
 
12 12
 const (
13
+	// SOH control character
14
+	SOH = "\x01"
15
+
13 16
 	defaultTimeout = 10 * time.Second
14 17
 )
15 18
 
... ...
@@ -72,6 +75,12 @@ func (s *Zookeeper) Get(key string) (pair *store.KVPair, err error) {
72 72
 		return nil, err
73 73
 	}
74 74
 
75
+	// FIXME handle very rare cases where Get returns the
76
+	// SOH control character instead of the actual value
77
+	if string(resp) == SOH {
78
+		return s.Get(store.Normalize(key))
79
+	}
80
+
75 81
 	pair = &store.KVPair{
76 82
 		Key:       key,
77 83
 		Value:     resp,
... ...
@@ -301,7 +310,7 @@ func (s *Zookeeper) AtomicPut(key string, value []byte, previous *store.KVPair,
301 301
 			// Zookeeper will complain if the directory doesn't exist.
302 302
 			if err == zk.ErrNoNode {
303 303
 				// Create the directory
304
-				parts := store.SplitKey(key)
304
+				parts := store.SplitKey(strings.TrimSuffix(key, "/"))
305 305
 				parts = parts[:len(parts)-1]
306 306
 				if err = s.createFullPath(parts, false); err != nil {
307 307
 					// Failed to create the directory.
... ...
@@ -371,7 +380,7 @@ func (s *Zookeeper) NewLock(key string, options *store.LockOptions) (lock store.
371 371
 // Lock attempts to acquire the lock and blocks while
372 372
 // doing so. It returns a channel that is closed if our
373 373
 // lock is lost or if an error occurs
374
-func (l *zookeeperLock) Lock() (<-chan struct{}, error) {
374
+func (l *zookeeperLock) Lock(stopChan chan struct{}) (<-chan struct{}, error) {
375 375
 	err := l.lock.Lock()
376 376
 
377 377
 	if err == nil {
... ...
@@ -29,7 +29,8 @@ cmd/dnet/dnet
29 29
 *.tmp
30 30
 *.coverprofile
31 31
 
32
-# IDE files
32
+# IDE files and folders
33 33
 .project
34
+.settings/
34 35
 
35 36
 libnetwork-build.created
... ...
@@ -5,6 +5,7 @@ package bitseq
5 5
 
6 6
 import (
7 7
 	"encoding/binary"
8
+	"encoding/json"
8 9
 	"fmt"
9 10
 	"sync"
10 11
 
... ...
@@ -16,10 +17,10 @@ import (
16 16
 // If needed we can think of making these configurable
17 17
 const (
18 18
 	blockLen      = uint32(32)
19
-	blockBytes    = blockLen / 8
19
+	blockBytes    = uint64(blockLen / 8)
20 20
 	blockMAX      = uint32(1<<blockLen - 1)
21 21
 	blockFirstBit = uint32(1) << (blockLen - 1)
22
-	invalidPos    = blockMAX
22
+	invalidPos    = uint64(0xFFFFFFFFFFFFFFFF)
23 23
 )
24 24
 
25 25
 var (
... ...
@@ -28,8 +29,8 @@ var (
28 28
 
29 29
 // Handle contains the sequece representing the bitmask and its identifier
30 30
 type Handle struct {
31
-	bits       uint32
32
-	unselected uint32
31
+	bits       uint64
32
+	unselected uint64
33 33
 	head       *sequence
34 34
 	app        string
35 35
 	id         string
... ...
@@ -40,7 +41,7 @@ type Handle struct {
40 40
 }
41 41
 
42 42
 // NewHandle returns a thread-safe instance of the bitmask handler
43
-func NewHandle(app string, ds datastore.DataStore, id string, numElements uint32) (*Handle, error) {
43
+func NewHandle(app string, ds datastore.DataStore, id string, numElements uint64) (*Handle, error) {
44 44
 	h := &Handle{
45 45
 		app:        app,
46 46
 		id:         id,
... ...
@@ -57,21 +58,25 @@ func NewHandle(app string, ds datastore.DataStore, id string, numElements uint32
57 57
 		return h, nil
58 58
 	}
59 59
 
60
-	// Register for status changes
61
-	h.watchForChanges()
62
-
63 60
 	// Get the initial status from the ds if present.
64 61
 	if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
65 62
 		return nil, err
66 63
 	}
67 64
 
65
+	// If the handle is not in store, write it.
66
+	if !h.Exists() {
67
+		if err := h.writeToStore(); err != nil {
68
+			return nil, fmt.Errorf("failed to write bitsequence to store: %v", err)
69
+		}
70
+	}
71
+
68 72
 	return h, nil
69 73
 }
70 74
 
71 75
 // sequence represents a recurring sequence of 32 bits long bitmasks
72 76
 type sequence struct {
73 77
 	block uint32    // block is a symbol representing 4 byte long allocation bitmask
74
-	count uint32    // number of consecutive blocks (symbols)
78
+	count uint64    // number of consecutive blocks (symbols)
75 79
 	next  *sequence // next sequence
76 80
 }
77 81
 
... ...
@@ -87,7 +92,7 @@ func (s *sequence) toString() string {
87 87
 }
88 88
 
89 89
 // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence
90
-func (s *sequence) getAvailableBit(from uint32) (uint32, uint32, error) {
90
+func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) {
91 91
 	if s.block == blockMAX || s.count == 0 {
92 92
 		return invalidPos, invalidPos, errNoBitAvailable
93 93
 	}
... ...
@@ -140,9 +145,9 @@ func (s *sequence) toByteArray() ([]byte, error) {
140 140
 
141 141
 	p := s
142 142
 	for p != nil {
143
-		b := make([]byte, 8)
143
+		b := make([]byte, 12)
144 144
 		binary.BigEndian.PutUint32(b[0:], p.block)
145
-		binary.BigEndian.PutUint32(b[4:], p.count)
145
+		binary.BigEndian.PutUint64(b[4:], p.count)
146 146
 		bb = append(bb, b...)
147 147
 		p = p.next
148 148
 	}
... ...
@@ -153,7 +158,7 @@ func (s *sequence) toByteArray() ([]byte, error) {
153 153
 // fromByteArray construct the sequence from the byte array
154 154
 func (s *sequence) fromByteArray(data []byte) error {
155 155
 	l := len(data)
156
-	if l%8 != 0 {
156
+	if l%12 != 0 {
157 157
 		return fmt.Errorf("cannot deserialize byte sequence of lenght %d (%v)", l, data)
158 158
 	}
159 159
 
... ...
@@ -161,8 +166,8 @@ func (s *sequence) fromByteArray(data []byte) error {
161 161
 	i := 0
162 162
 	for {
163 163
 		p.block = binary.BigEndian.Uint32(data[i : i+4])
164
-		p.count = binary.BigEndian.Uint32(data[i+4 : i+8])
165
-		i += 8
164
+		p.count = binary.BigEndian.Uint64(data[i+4 : i+12])
165
+		i += 12
166 166
 		if i == l {
167 167
 			break
168 168
 		}
... ...
@@ -187,7 +192,7 @@ func (h *Handle) getCopy() *Handle {
187 187
 }
188 188
 
189 189
 // SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal
190
-func (h *Handle) SetAnyInRange(start, end uint32) (uint32, error) {
190
+func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) {
191 191
 	if end-start <= 0 || end >= h.bits {
192 192
 		return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end)
193 193
 	}
... ...
@@ -198,7 +203,7 @@ func (h *Handle) SetAnyInRange(start, end uint32) (uint32, error) {
198 198
 }
199 199
 
200 200
 // SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal
201
-func (h *Handle) SetAny() (uint32, error) {
201
+func (h *Handle) SetAny() (uint64, error) {
202 202
 	if h.Unselected() == 0 {
203 203
 		return invalidPos, errNoBitAvailable
204 204
 	}
... ...
@@ -206,7 +211,7 @@ func (h *Handle) SetAny() (uint32, error) {
206 206
 }
207 207
 
208 208
 // Set atomically sets the corresponding bit in the sequence
209
-func (h *Handle) Set(ordinal uint32) error {
209
+func (h *Handle) Set(ordinal uint64) error {
210 210
 	if err := h.validateOrdinal(ordinal); err != nil {
211 211
 		return err
212 212
 	}
... ...
@@ -215,7 +220,7 @@ func (h *Handle) Set(ordinal uint32) error {
215 215
 }
216 216
 
217 217
 // Unset atomically unsets the corresponding bit in the sequence
218
-func (h *Handle) Unset(ordinal uint32) error {
218
+func (h *Handle) Unset(ordinal uint64) error {
219 219
 	if err := h.validateOrdinal(ordinal); err != nil {
220 220
 		return err
221 221
 	}
... ...
@@ -225,7 +230,7 @@ func (h *Handle) Unset(ordinal uint32) error {
225 225
 
226 226
 // IsSet atomically checks if the ordinal bit is set. In case ordinal
227 227
 // is outside of the bit sequence limits, false is returned.
228
-func (h *Handle) IsSet(ordinal uint32) bool {
228
+func (h *Handle) IsSet(ordinal uint64) bool {
229 229
 	if err := h.validateOrdinal(ordinal); err != nil {
230 230
 		return false
231 231
 	}
... ...
@@ -236,15 +241,21 @@ func (h *Handle) IsSet(ordinal uint32) bool {
236 236
 }
237 237
 
238 238
 // set/reset the bit
239
-func (h *Handle) set(ordinal, start, end uint32, any bool, release bool) (uint32, error) {
239
+func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64, error) {
240 240
 	var (
241
-		bitPos  uint32
242
-		bytePos uint32
243
-		ret     uint32
241
+		bitPos  uint64
242
+		bytePos uint64
243
+		ret     uint64
244 244
 		err     error
245 245
 	)
246 246
 
247 247
 	for {
248
+		if h.store != nil {
249
+			if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
250
+				return ret, err
251
+			}
252
+		}
253
+
248 254
 		h.Lock()
249 255
 		// Get position if available
250 256
 		if release {
... ...
@@ -298,7 +309,7 @@ func (h *Handle) set(ordinal, start, end uint32, any bool, release bool) (uint32
298 298
 }
299 299
 
300 300
 // checks is needed because to cover the case where the number of bits is not a multiple of blockLen
301
-func (h *Handle) validateOrdinal(ordinal uint32) error {
301
+func (h *Handle) validateOrdinal(ordinal uint64) error {
302 302
 	if ordinal >= h.bits {
303 303
 		return fmt.Errorf("bit does not belong to the sequence")
304 304
 	}
... ...
@@ -306,8 +317,23 @@ func (h *Handle) validateOrdinal(ordinal uint32) error {
306 306
 }
307 307
 
308 308
 // Destroy removes from the datastore the data belonging to this handle
309
-func (h *Handle) Destroy() {
310
-	h.deleteFromStore()
309
+func (h *Handle) Destroy() error {
310
+	for {
311
+		if err := h.deleteFromStore(); err != nil {
312
+			if _, ok := err.(types.RetryError); !ok {
313
+				return fmt.Errorf("internal failure while destroying the sequence: %v", err)
314
+			}
315
+			// Fetch latest
316
+			if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil {
317
+				if err == datastore.ErrKeyNotFound { // already removed
318
+					return nil
319
+				}
320
+				return fmt.Errorf("failed to fetch from store when destroying the sequence: %v", err)
321
+			}
322
+			continue
323
+		}
324
+		return nil
325
+	}
311 326
 }
312 327
 
313 328
 // ToByteArray converts this handle's data into a byte array
... ...
@@ -315,9 +341,9 @@ func (h *Handle) ToByteArray() ([]byte, error) {
315 315
 
316 316
 	h.Lock()
317 317
 	defer h.Unlock()
318
-	ba := make([]byte, 8)
319
-	binary.BigEndian.PutUint32(ba[0:], h.bits)
320
-	binary.BigEndian.PutUint32(ba[4:], h.unselected)
318
+	ba := make([]byte, 16)
319
+	binary.BigEndian.PutUint64(ba[0:], h.bits)
320
+	binary.BigEndian.PutUint64(ba[8:], h.unselected)
321 321
 	bm, err := h.head.toByteArray()
322 322
 	if err != nil {
323 323
 		return nil, fmt.Errorf("failed to serialize head: %s", err.Error())
... ...
@@ -334,27 +360,27 @@ func (h *Handle) FromByteArray(ba []byte) error {
334 334
 	}
335 335
 
336 336
 	nh := &sequence{}
337
-	err := nh.fromByteArray(ba[8:])
337
+	err := nh.fromByteArray(ba[16:])
338 338
 	if err != nil {
339 339
 		return fmt.Errorf("failed to deserialize head: %s", err.Error())
340 340
 	}
341 341
 
342 342
 	h.Lock()
343 343
 	h.head = nh
344
-	h.bits = binary.BigEndian.Uint32(ba[0:4])
345
-	h.unselected = binary.BigEndian.Uint32(ba[4:8])
344
+	h.bits = binary.BigEndian.Uint64(ba[0:8])
345
+	h.unselected = binary.BigEndian.Uint64(ba[8:16])
346 346
 	h.Unlock()
347 347
 
348 348
 	return nil
349 349
 }
350 350
 
351 351
 // Bits returns the length of the bit sequence
352
-func (h *Handle) Bits() uint32 {
352
+func (h *Handle) Bits() uint64 {
353 353
 	return h.bits
354 354
 }
355 355
 
356 356
 // Unselected returns the number of bits which are not selected
357
-func (h *Handle) Unselected() uint32 {
357
+func (h *Handle) Unselected() uint64 {
358 358
 	h.Lock()
359 359
 	defer h.Unlock()
360 360
 	return h.unselected
... ...
@@ -367,8 +393,40 @@ func (h *Handle) String() string {
367 367
 		h.app, h.id, h.dbIndex, h.bits, h.unselected, h.head.toString())
368 368
 }
369 369
 
370
+// MarshalJSON encodes Handle into json message
371
+func (h *Handle) MarshalJSON() ([]byte, error) {
372
+	m := map[string]interface{}{
373
+		"id": h.id,
374
+	}
375
+
376
+	b, err := h.ToByteArray()
377
+	if err != nil {
378
+		return nil, err
379
+	}
380
+	m["sequence"] = b
381
+	return json.Marshal(m)
382
+}
383
+
384
+// UnmarshalJSON decodes json message into Handle
385
+func (h *Handle) UnmarshalJSON(data []byte) error {
386
+	var (
387
+		m   map[string]interface{}
388
+		b   []byte
389
+		err error
390
+	)
391
+	if err = json.Unmarshal(data, &m); err != nil {
392
+		return err
393
+	}
394
+	h.id = m["id"].(string)
395
+	bi, _ := json.Marshal(m["sequence"])
396
+	if err := json.Unmarshal(bi, &b); err != nil {
397
+		return err
398
+	}
399
+	return h.FromByteArray(b)
400
+}
401
+
370 402
 // getFirstAvailable looks for the first unset bit in passed mask starting from start
371
-func getFirstAvailable(head *sequence, start uint32) (uint32, uint32, error) {
403
+func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {
372 404
 	// Find sequence which contains the start bit
373 405
 	byteStart, bitStart := ordinalToPos(start)
374 406
 	current, _, _, inBlockBytePos := findSequence(head, byteStart)
... ...
@@ -392,7 +450,7 @@ func getFirstAvailable(head *sequence, start uint32) (uint32, uint32, error) {
392 392
 
393 393
 // checkIfAvailable checks if the bit correspondent to the specified ordinal is unset
394 394
 // If the ordinal is beyond the sequence limits, a negative response is returned
395
-func checkIfAvailable(head *sequence, ordinal uint32) (uint32, uint32, error) {
395
+func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) {
396 396
 	bytePos, bitPos := ordinalToPos(ordinal)
397 397
 
398 398
 	// Find the sequence containing this byte
... ...
@@ -412,7 +470,7 @@ func checkIfAvailable(head *sequence, ordinal uint32) (uint32, uint32, error) {
412 412
 // sequence containing the byte (current), the pointer to the previous sequence,
413 413
 // the number of blocks preceding the block containing the byte inside the current sequence.
414 414
 // If bytePos is outside of the list, function will return (nil, nil, 0, invalidPos)
415
-func findSequence(head *sequence, bytePos uint32) (*sequence, *sequence, uint32, uint32) {
415
+func findSequence(head *sequence, bytePos uint64) (*sequence, *sequence, uint64, uint64) {
416 416
 	// Find the sequence containing this byte
417 417
 	previous := head
418 418
 	current := head
... ...
@@ -453,7 +511,7 @@ func findSequence(head *sequence, bytePos uint32) (*sequence, *sequence, uint32,
453 453
 // A) block is first in current:         [prev seq] [new] [modified current seq] [next seq]
454 454
 // B) block is last in current:          [prev seq] [modified current seq] [new] [next seq]
455 455
 // C) block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [next seq]
456
-func pushReservation(bytePos, bitPos uint32, head *sequence, release bool) *sequence {
456
+func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequence {
457 457
 	// Store list's head
458 458
 	newHead := head
459 459
 
... ...
@@ -541,18 +599,18 @@ func mergeSequences(seq *sequence) {
541 541
 	}
542 542
 }
543 543
 
544
-func getNumBlocks(numBits uint32) uint32 {
545
-	numBlocks := numBits / blockLen
546
-	if numBits%blockLen != 0 {
544
+func getNumBlocks(numBits uint64) uint64 {
545
+	numBlocks := numBits / uint64(blockLen)
546
+	if numBits%uint64(blockLen) != 0 {
547 547
 		numBlocks++
548 548
 	}
549 549
 	return numBlocks
550 550
 }
551 551
 
552
-func ordinalToPos(ordinal uint32) (uint32, uint32) {
552
+func ordinalToPos(ordinal uint64) (uint64, uint64) {
553 553
 	return ordinal / 8, ordinal % 8
554 554
 }
555 555
 
556
-func posToOrdinal(bytePos, bitPos uint32) uint32 {
556
+func posToOrdinal(bytePos, bitPos uint64) uint64 {
557 557
 	return bytePos*8 + bitPos
558 558
 }
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6 6
 
7
-	log "github.com/Sirupsen/logrus"
8 7
 	"github.com/docker/libnetwork/datastore"
9 8
 	"github.com/docker/libnetwork/types"
10 9
 )
... ...
@@ -25,27 +24,16 @@ func (h *Handle) KeyPrefix() []string {
25 25
 
26 26
 // Value marshals the data to be stored in the KV store
27 27
 func (h *Handle) Value() []byte {
28
-	b, err := h.ToByteArray()
28
+	b, err := json.Marshal(h)
29 29
 	if err != nil {
30
-		log.Warnf("Failed to serialize Handle: %v", err)
31
-		b = []byte{}
32
-	}
33
-	jv, err := json.Marshal(b)
34
-	if err != nil {
35
-		log.Warnf("Failed to json encode bitseq handler byte array: %v", err)
36
-		return []byte{}
30
+		return nil
37 31
 	}
38
-	return jv
32
+	return b
39 33
 }
40 34
 
41 35
 // SetValue unmarshals the data from the KV store
42 36
 func (h *Handle) SetValue(value []byte) error {
43
-	var b []byte
44
-	if err := json.Unmarshal(value, &b); err != nil {
45
-		return err
46
-	}
47
-
48
-	return h.FromByteArray(b)
37
+	return json.Unmarshal(value, h)
49 38
 }
50 39
 
51 40
 // Index returns the latest DB Index as seen by this object
... ...
@@ -70,46 +58,46 @@ func (h *Handle) Exists() bool {
70 70
 	return h.dbExists
71 71
 }
72 72
 
73
+// New method returns a handle based on the receiver handle
74
+func (h *Handle) New() datastore.KVObject {
75
+	h.Lock()
76
+	defer h.Unlock()
77
+
78
+	return &Handle{
79
+		app:   h.app,
80
+		store: h.store,
81
+	}
82
+}
83
+
84
+// CopyTo deep copies the handle into the passed destination object
85
+func (h *Handle) CopyTo(o datastore.KVObject) error {
86
+	h.Lock()
87
+	defer h.Unlock()
88
+
89
+	dstH := o.(*Handle)
90
+	dstH.bits = h.bits
91
+	dstH.unselected = h.unselected
92
+	dstH.head = h.head.getCopy()
93
+	dstH.app = h.app
94
+	dstH.id = h.id
95
+	dstH.dbIndex = h.dbIndex
96
+	dstH.dbExists = h.dbExists
97
+	dstH.store = h.store
98
+
99
+	return nil
100
+}
101
+
73 102
 // Skip provides a way for a KV Object to avoid persisting it in the KV Store
74 103
 func (h *Handle) Skip() bool {
75 104
 	return false
76 105
 }
77 106
 
78 107
 // DataScope method returns the storage scope of the datastore
79
-func (h *Handle) DataScope() datastore.DataScope {
80
-	return datastore.GlobalScope
81
-}
82
-
83
-func (h *Handle) watchForChanges() error {
108
+func (h *Handle) DataScope() string {
84 109
 	h.Lock()
85
-	store := h.store
86
-	h.Unlock()
87
-
88
-	if store == nil {
89
-		return nil
90
-	}
110
+	defer h.Unlock()
91 111
 
92
-	kvpChan, err := store.KVStore().Watch(datastore.Key(h.Key()...), nil)
93
-	if err != nil {
94
-		return err
95
-	}
96
-	go func() {
97
-		for {
98
-			select {
99
-			case kvPair := <-kvpChan:
100
-				// Only process remote update
101
-				if kvPair != nil && (kvPair.LastIndex != h.Index()) {
102
-					err := h.fromDsValue(kvPair.Value)
103
-					if err != nil {
104
-						log.Warnf("Failed to reconstruct bitseq handle from ds watch: %s", err.Error())
105
-					} else {
106
-						h.SetIndex(kvPair.LastIndex)
107
-					}
108
-				}
109
-			}
110
-		}
111
-	}()
112
-	return nil
112
+	return h.store.Scope()
113 113
 }
114 114
 
115 115
 func (h *Handle) fromDsValue(value []byte) error {
... ...
@@ -6,20 +6,23 @@ import (
6 6
 	"github.com/BurntSushi/toml"
7 7
 	log "github.com/Sirupsen/logrus"
8 8
 	"github.com/docker/docker/pkg/discovery"
9
+	"github.com/docker/docker/pkg/tlsconfig"
9 10
 	"github.com/docker/libkv/store"
11
+	"github.com/docker/libnetwork/datastore"
10 12
 	"github.com/docker/libnetwork/netlabel"
11 13
 )
12 14
 
13 15
 // Config encapsulates configurations of various Libnetwork components
14 16
 type Config struct {
15
-	Daemon                  DaemonCfg
16
-	Cluster                 ClusterCfg
17
-	GlobalStore, LocalStore DatastoreCfg
17
+	Daemon  DaemonCfg
18
+	Cluster ClusterCfg
19
+	Scopes  map[string]*datastore.ScopeCfg
18 20
 }
19 21
 
20 22
 // DaemonCfg represents libnetwork core configuration
21 23
 type DaemonCfg struct {
22 24
 	Debug          bool
25
+	DataDir        string
23 26
 	DefaultNetwork string
24 27
 	DefaultDriver  string
25 28
 	Labels         []string
... ...
@@ -34,26 +37,28 @@ type ClusterCfg struct {
34 34
 	Heartbeat uint64
35 35
 }
36 36
 
37
-// DatastoreCfg represents Datastore configuration.
38
-type DatastoreCfg struct {
39
-	Embedded bool
40
-	Client   DatastoreClientCfg
41
-}
42
-
43
-// DatastoreClientCfg represents Datastore Client-only mode configuration
44
-type DatastoreClientCfg struct {
45
-	Provider string
46
-	Address  string
47
-	Config   *store.Config
37
+// LoadDefaultScopes loads default scope configs for scopes which
38
+// doesn't have explicit user specified configs.
39
+func (c *Config) LoadDefaultScopes(dataDir string) {
40
+	for k, v := range datastore.DefaultScopes(dataDir) {
41
+		if _, ok := c.Scopes[k]; !ok {
42
+			c.Scopes[k] = v
43
+		}
44
+	}
48 45
 }
49 46
 
50 47
 // ParseConfig parses the libnetwork configuration file
51 48
 func ParseConfig(tomlCfgFile string) (*Config, error) {
52
-	var cfg Config
53
-	if _, err := toml.DecodeFile(tomlCfgFile, &cfg); err != nil {
49
+	cfg := &Config{
50
+		Scopes: map[string]*datastore.ScopeCfg{},
51
+	}
52
+
53
+	if _, err := toml.DecodeFile(tomlCfgFile, cfg); err != nil {
54 54
 		return nil, err
55 55
 	}
56
-	return &cfg, nil
56
+
57
+	cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
58
+	return cfg, nil
57 59
 }
58 60
 
59 61
 // Option is a option setter function type used to pass varios configurations
... ...
@@ -63,7 +68,7 @@ type Option func(c *Config)
63 63
 // OptionDefaultNetwork function returns an option setter for a default network
64 64
 func OptionDefaultNetwork(dn string) Option {
65 65
 	return func(c *Config) {
66
-		log.Infof("Option DefaultNetwork: %s", dn)
66
+		log.Debugf("Option DefaultNetwork: %s", dn)
67 67
 		c.Daemon.DefaultNetwork = strings.TrimSpace(dn)
68 68
 	}
69 69
 }
... ...
@@ -71,7 +76,7 @@ func OptionDefaultNetwork(dn string) Option {
71 71
 // OptionDefaultDriver function returns an option setter for default driver
72 72
 func OptionDefaultDriver(dd string) Option {
73 73
 	return func(c *Config) {
74
-		log.Infof("Option DefaultDriver: %s", dd)
74
+		log.Debugf("Option DefaultDriver: %s", dd)
75 75
 		c.Daemon.DefaultDriver = strings.TrimSpace(dd)
76 76
 	}
77 77
 }
... ...
@@ -97,16 +102,56 @@ func OptionLabels(labels []string) Option {
97 97
 // OptionKVProvider function returns an option setter for kvstore provider
98 98
 func OptionKVProvider(provider string) Option {
99 99
 	return func(c *Config) {
100
-		log.Infof("Option OptionKVProvider: %s", provider)
101
-		c.GlobalStore.Client.Provider = strings.TrimSpace(provider)
100
+		log.Debugf("Option OptionKVProvider: %s", provider)
101
+		if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
102
+			c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
103
+		}
104
+		c.Scopes[datastore.GlobalScope].Client.Provider = strings.TrimSpace(provider)
102 105
 	}
103 106
 }
104 107
 
105 108
 // OptionKVProviderURL function returns an option setter for kvstore url
106 109
 func OptionKVProviderURL(url string) Option {
107 110
 	return func(c *Config) {
108
-		log.Infof("Option OptionKVProviderURL: %s", url)
109
-		c.GlobalStore.Client.Address = strings.TrimSpace(url)
111
+		log.Debugf("Option OptionKVProviderURL: %s", url)
112
+		if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
113
+			c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
114
+		}
115
+		c.Scopes[datastore.GlobalScope].Client.Address = strings.TrimSpace(url)
116
+	}
117
+}
118
+
119
+// OptionKVOpts function returns an option setter for kvstore options
120
+func OptionKVOpts(opts map[string]string) Option {
121
+	return func(c *Config) {
122
+		if opts["kv.cacertfile"] != "" && opts["kv.certfile"] != "" && opts["kv.keyfile"] != "" {
123
+			log.Info("Option Initializing KV with TLS")
124
+			tlsConfig, err := tlsconfig.Client(tlsconfig.Options{
125
+				CAFile:   opts["kv.cacertfile"],
126
+				CertFile: opts["kv.certfile"],
127
+				KeyFile:  opts["kv.keyfile"],
128
+			})
129
+			if err != nil {
130
+				log.Errorf("Unable to set up TLS: %s", err)
131
+				return
132
+			}
133
+			if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
134
+				c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
135
+			}
136
+			if c.Scopes[datastore.GlobalScope].Client.Config == nil {
137
+				c.Scopes[datastore.GlobalScope].Client.Config = &store.Config{TLS: tlsConfig}
138
+			} else {
139
+				c.Scopes[datastore.GlobalScope].Client.Config.TLS = tlsConfig
140
+			}
141
+			// Workaround libkv/etcd bug for https
142
+			c.Scopes[datastore.GlobalScope].Client.Config.ClientTLS = &store.ClientTLSConfig{
143
+				CACertFile: opts["kv.cacertfile"],
144
+				CertFile:   opts["kv.certfile"],
145
+				KeyFile:    opts["kv.keyfile"],
146
+			}
147
+		} else {
148
+			log.Info("Option Initializing KV without TLS")
149
+		}
110 150
 	}
111 151
 }
112 152
 
... ...
@@ -124,6 +169,13 @@ func OptionDiscoveryAddress(address string) Option {
124 124
 	}
125 125
 }
126 126
 
127
+// OptionDataDir function returns an option setter for data folder
128
+func OptionDataDir(dataDir string) Option {
129
+	return func(c *Config) {
130
+		c.Daemon.DataDir = dataDir
131
+	}
132
+}
133
+
127 134
 // ProcessOptions processes options and stores it in config
128 135
 func (c *Config) ProcessOptions(options ...Option) {
129 136
 	for _, opt := range options {
... ...
@@ -135,7 +187,7 @@ func (c *Config) ProcessOptions(options ...Option) {
135 135
 
136 136
 // IsValidName validates configuration objects supported by libnetwork
137 137
 func IsValidName(name string) bool {
138
-	if strings.TrimSpace(name) == "" || strings.Contains(name, ".") {
138
+	if strings.TrimSpace(name) == "" {
139 139
 		return false
140 140
 	}
141 141
 	return true
... ...
@@ -144,23 +196,32 @@ func IsValidName(name string) bool {
144 144
 // OptionLocalKVProvider function returns an option setter for kvstore provider
145 145
 func OptionLocalKVProvider(provider string) Option {
146 146
 	return func(c *Config) {
147
-		log.Infof("Option OptionLocalKVProvider: %s", provider)
148
-		c.LocalStore.Client.Provider = strings.TrimSpace(provider)
147
+		log.Debugf("Option OptionLocalKVProvider: %s", provider)
148
+		if _, ok := c.Scopes[datastore.LocalScope]; !ok {
149
+			c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
150
+		}
151
+		c.Scopes[datastore.LocalScope].Client.Provider = strings.TrimSpace(provider)
149 152
 	}
150 153
 }
151 154
 
152 155
 // OptionLocalKVProviderURL function returns an option setter for kvstore url
153 156
 func OptionLocalKVProviderURL(url string) Option {
154 157
 	return func(c *Config) {
155
-		log.Infof("Option OptionLocalKVProviderURL: %s", url)
156
-		c.LocalStore.Client.Address = strings.TrimSpace(url)
158
+		log.Debugf("Option OptionLocalKVProviderURL: %s", url)
159
+		if _, ok := c.Scopes[datastore.LocalScope]; !ok {
160
+			c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
161
+		}
162
+		c.Scopes[datastore.LocalScope].Client.Address = strings.TrimSpace(url)
157 163
 	}
158 164
 }
159 165
 
160 166
 // OptionLocalKVProviderConfig function returns an option setter for kvstore config
161 167
 func OptionLocalKVProviderConfig(config *store.Config) Option {
162 168
 	return func(c *Config) {
163
-		log.Infof("Option OptionLocalKVProviderConfig: %v", config)
164
-		c.LocalStore.Client.Config = config
169
+		log.Debugf("Option OptionLocalKVProviderConfig: %v", config)
170
+		if _, ok := c.Scopes[datastore.LocalScope]; !ok {
171
+			c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
172
+		}
173
+		c.Scopes[datastore.LocalScope].Client.Config = config
165 174
 	}
166 175
 }
... ...
@@ -58,6 +58,8 @@ import (
58 58
 	"github.com/docker/libnetwork/datastore"
59 59
 	"github.com/docker/libnetwork/driverapi"
60 60
 	"github.com/docker/libnetwork/hostdiscovery"
61
+	"github.com/docker/libnetwork/ipamapi"
62
+	"github.com/docker/libnetwork/netlabel"
61 63
 	"github.com/docker/libnetwork/osl"
62 64
 	"github.com/docker/libnetwork/types"
63 65
 )
... ...
@@ -116,60 +118,82 @@ type driverData struct {
116 116
 	capability driverapi.Capability
117 117
 }
118 118
 
119
+type ipamData struct {
120
+	driver ipamapi.Ipam
121
+	// default address spaces are provided by ipam driver at registration time
122
+	defaultLocalAddressSpace, defaultGlobalAddressSpace string
123
+}
124
+
119 125
 type driverTable map[string]*driverData
120
-type networkTable map[string]*network
121
-type endpointTable map[string]*endpoint
126
+
127
+//type networkTable map[string]*network
128
+//type endpointTable map[string]*endpoint
129
+type ipamTable map[string]*ipamData
122 130
 type sandboxTable map[string]*sandbox
123 131
 
124 132
 type controller struct {
125
-	id                      string
126
-	networks                networkTable
127
-	drivers                 driverTable
128
-	sandboxes               sandboxTable
129
-	cfg                     *config.Config
130
-	globalStore, localStore datastore.DataStore
131
-	discovery               hostdiscovery.HostDiscovery
132
-	extKeyListener          net.Listener
133
+	id string
134
+	//networks       networkTable
135
+	drivers        driverTable
136
+	ipamDrivers    ipamTable
137
+	sandboxes      sandboxTable
138
+	cfg            *config.Config
139
+	stores         []datastore.DataStore
140
+	discovery      hostdiscovery.HostDiscovery
141
+	extKeyListener net.Listener
142
+	watchCh        chan *endpoint
143
+	unWatchCh      chan *endpoint
144
+	svcDb          map[string]svcMap
133 145
 	sync.Mutex
134 146
 }
135 147
 
136 148
 // New creates a new instance of network controller.
137 149
 func New(cfgOptions ...config.Option) (NetworkController, error) {
138 150
 	var cfg *config.Config
151
+	cfg = &config.Config{
152
+		Daemon: config.DaemonCfg{
153
+			DriverCfg: make(map[string]interface{}),
154
+		},
155
+		Scopes: make(map[string]*datastore.ScopeCfg),
156
+	}
157
+
139 158
 	if len(cfgOptions) > 0 {
140
-		cfg = &config.Config{
141
-			Daemon: config.DaemonCfg{
142
-				DriverCfg: make(map[string]interface{}),
143
-			},
144
-		}
145 159
 		cfg.ProcessOptions(cfgOptions...)
146 160
 	}
161
+	cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
162
+
147 163
 	c := &controller{
148
-		id:        stringid.GenerateRandomID(),
149
-		cfg:       cfg,
150
-		networks:  networkTable{},
151
-		sandboxes: sandboxTable{},
152
-		drivers:   driverTable{}}
153
-	if err := initDrivers(c); err != nil {
164
+		id:          stringid.GenerateRandomID(),
165
+		cfg:         cfg,
166
+		sandboxes:   sandboxTable{},
167
+		drivers:     driverTable{},
168
+		ipamDrivers: ipamTable{},
169
+		svcDb:       make(map[string]svcMap),
170
+	}
171
+
172
+	if err := c.initStores(); err != nil {
154 173
 		return nil, err
155 174
 	}
156 175
 
157
-	if cfg != nil {
158
-		if err := c.initGlobalStore(); err != nil {
159
-			// Failing to initalize datastore is a bad situation to be in.
160
-			// But it cannot fail creating the Controller
161
-			log.Debugf("Failed to Initialize Datastore due to %v. Operating in non-clustered mode", err)
162
-		}
176
+	if cfg != nil && cfg.Cluster.Watcher != nil {
163 177
 		if err := c.initDiscovery(cfg.Cluster.Watcher); err != nil {
164 178
 			// Failing to initalize discovery is a bad situation to be in.
165 179
 			// But it cannot fail creating the Controller
166 180
 			log.Debugf("Failed to Initialize Discovery : %v", err)
167 181
 		}
168
-		if err := c.initLocalStore(); err != nil {
169
-			log.Debugf("Failed to Initialize LocalDatastore due to %v.", err)
170
-		}
171 182
 	}
172 183
 
184
+	if err := initDrivers(c); err != nil {
185
+		return nil, err
186
+	}
187
+
188
+	if err := initIpams(c, c.getStore(datastore.LocalScope),
189
+		c.getStore(datastore.GlobalScope)); err != nil {
190
+		return nil, err
191
+	}
192
+
193
+	c.sandboxCleanup()
194
+
173 195
 	if err := c.startExternalKeyListener(); err != nil {
174 196
 		return nil, err
175 197
 	}
... ...
@@ -272,43 +296,91 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver,
272 272
 	return nil
273 273
 }
274 274
 
275
+func (c *controller) RegisterIpamDriver(name string, driver ipamapi.Ipam) error {
276
+	if !config.IsValidName(name) {
277
+		return ErrInvalidName(name)
278
+	}
279
+
280
+	c.Lock()
281
+	_, ok := c.ipamDrivers[name]
282
+	c.Unlock()
283
+	if ok {
284
+		return driverapi.ErrActiveRegistration(name)
285
+	}
286
+	locAS, glbAS, err := driver.GetDefaultAddressSpaces()
287
+	if err != nil {
288
+		return fmt.Errorf("ipam driver %s failed to return default address spaces: %v", name, err)
289
+	}
290
+	c.Lock()
291
+	c.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS}
292
+	c.Unlock()
293
+
294
+	log.Debugf("Registering ipam provider: %s", name)
295
+
296
+	return nil
297
+}
298
+
275 299
 // NewNetwork creates a new network of the specified network type. The options
276 300
 // are network specific and modeled in a generic way.
277 301
 func (c *controller) NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) {
278 302
 	if !config.IsValidName(name) {
279 303
 		return nil, ErrInvalidName(name)
280 304
 	}
281
-	// Check if a network already exists with the specified network name
282
-	c.Lock()
283
-	for _, n := range c.networks {
284
-		if n.name == name {
285
-			c.Unlock()
286
-			return nil, NetworkNameError(name)
287
-		}
288
-	}
289
-	c.Unlock()
290 305
 
291 306
 	// Construct the network object
292 307
 	network := &network{
293 308
 		name:        name,
294 309
 		networkType: networkType,
310
+		generic:     map[string]interface{}{netlabel.GenericData: make(map[string]string)},
311
+		ipamType:    ipamapi.DefaultIPAM,
295 312
 		id:          stringid.GenerateRandomID(),
296 313
 		ctrlr:       c,
297
-		endpoints:   endpointTable{},
298 314
 		persist:     true,
315
+		drvOnce:     &sync.Once{},
299 316
 	}
300 317
 
301 318
 	network.processOptions(options...)
302 319
 
320
+	// Make sure we have a driver available for this network type
321
+	// before we allocate anything.
322
+	if _, err := network.driver(); err != nil {
323
+		return nil, err
324
+	}
325
+
326
+	err := network.ipamAllocate()
327
+	if err != nil {
328
+		return nil, err
329
+	}
330
+	defer func() {
331
+		if err != nil {
332
+			network.ipamRelease()
333
+		}
334
+	}()
335
+
303 336
 	if err := c.addNetwork(network); err != nil {
304 337
 		return nil, err
305 338
 	}
339
+	defer func() {
340
+		if err != nil {
341
+			if e := network.deleteNetwork(); e != nil {
342
+				log.Warnf("couldn't roll back driver network on network %s creation failure: %v", network.name, err)
343
+			}
344
+		}
345
+	}()
306 346
 
307
-	if err := c.updateToStore(network); err != nil {
308
-		log.Warnf("couldnt create network %s: %v", network.name, err)
309
-		if e := network.Delete(); e != nil {
310
-			log.Warnf("couldnt cleanup network %s: %v", network.name, err)
347
+	if err = c.updateToStore(network); err != nil {
348
+		return nil, err
349
+	}
350
+	defer func() {
351
+		if err != nil {
352
+			if e := c.deleteFromStore(network); e != nil {
353
+				log.Warnf("couldnt rollback from store, network %s on failure (%v): %v", network.name, err, e)
354
+			}
311 355
 		}
356
+	}()
357
+
358
+	network.epCnt = &endpointCnt{n: network}
359
+	if err = c.updateToStore(network.epCnt); err != nil {
312 360
 		return nil, err
313 361
 	}
314 362
 
... ...
@@ -316,49 +388,28 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti
316 316
 }
317 317
 
318 318
 func (c *controller) addNetwork(n *network) error {
319
-
320
-	c.Lock()
321
-	// Check if a driver for the specified network type is available
322
-	dd, ok := c.drivers[n.networkType]
323
-	c.Unlock()
324
-
325
-	if !ok {
326
-		var err error
327
-		dd, err = c.loadDriver(n.networkType)
328
-		if err != nil {
329
-			return err
330
-		}
319
+	d, err := n.driver()
320
+	if err != nil {
321
+		return err
331 322
 	}
332 323
 
333
-	n.Lock()
334
-	n.svcRecords = svcMap{}
335
-	n.driver = dd.driver
336
-	n.dataScope = dd.capability.DataScope
337
-	d := n.driver
338
-	n.Unlock()
339
-
340 324
 	// Create the network
341
-	if err := d.CreateNetwork(n.id, n.generic); err != nil {
325
+	if err := d.CreateNetwork(n.id, n.generic, n.getIPData(4), n.getIPData(6)); err != nil {
342 326
 		return err
343 327
 	}
344
-	if n.isGlobalScoped() {
345
-		if err := n.watchEndpoints(); err != nil {
346
-			return err
347
-		}
348
-	}
349
-	c.Lock()
350
-	c.networks[n.id] = n
351
-	c.Unlock()
352 328
 
353 329
 	return nil
354 330
 }
355 331
 
356 332
 func (c *controller) Networks() []Network {
357
-	c.Lock()
358
-	defer c.Unlock()
333
+	var list []Network
334
+
335
+	networks, err := c.getNetworksFromStore()
336
+	if err != nil {
337
+		log.Error(err)
338
+	}
359 339
 
360
-	list := make([]Network, 0, len(c.networks))
361
-	for _, n := range c.networks {
340
+	for _, n := range networks {
362 341
 		list = append(list, n)
363 342
 	}
364 343
 
... ...
@@ -400,12 +451,13 @@ func (c *controller) NetworkByID(id string) (Network, error) {
400 400
 	if id == "" {
401 401
 		return nil, ErrInvalidID(id)
402 402
 	}
403
-	c.Lock()
404
-	defer c.Unlock()
405
-	if n, ok := c.networks[id]; ok {
406
-		return n, nil
403
+
404
+	n, err := c.getNetworkFromStore(id)
405
+	if err != nil {
406
+		return nil, ErrNoSuchNetwork(id)
407 407
 	}
408
-	return nil, ErrNoSuchNetwork(id)
408
+
409
+	return n, nil
409 410
 }
410 411
 
411 412
 // NewSandbox creates a new sandbox for the passed container id
... ...
@@ -456,6 +508,18 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
456 456
 	c.Lock()
457 457
 	c.sandboxes[sb.id] = sb
458 458
 	c.Unlock()
459
+	defer func() {
460
+		if err != nil {
461
+			c.Lock()
462
+			delete(c.sandboxes, sb.id)
463
+			c.Unlock()
464
+		}
465
+	}()
466
+
467
+	err = sb.storeUpdate()
468
+	if err != nil {
469
+		return nil, fmt.Errorf("updating the store state of sandbox failed: %v", err)
470
+	}
459 471
 
460 472
 	return sb, nil
461 473
 }
... ...
@@ -534,20 +598,43 @@ func (c *controller) loadDriver(networkType string) (*driverData, error) {
534 534
 	return dd, nil
535 535
 }
536 536
 
537
-func (c *controller) getDriver(networkType string) (*driverData, error) {
537
+func (c *controller) loadIpamDriver(name string) (*ipamData, error) {
538
+	if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil {
539
+		if err == plugins.ErrNotFound {
540
+			return nil, types.NotFoundErrorf(err.Error())
541
+		}
542
+		return nil, err
543
+	}
538 544
 	c.Lock()
539
-	defer c.Unlock()
540
-	dd, ok := c.drivers[networkType]
545
+	id, ok := c.ipamDrivers[name]
546
+	c.Unlock()
541 547
 	if !ok {
542
-		return nil, types.NotFoundErrorf("driver %s not found", networkType)
548
+		return nil, ErrInvalidNetworkDriver(name)
543 549
 	}
544
-	return dd, nil
550
+	return id, nil
545 551
 }
546 552
 
547
-func (c *controller) Stop() {
548
-	if c.localStore != nil {
549
-		c.localStore.KVStore().Close()
553
+func (c *controller) getIPAM(name string) (id *ipamData, err error) {
554
+	var ok bool
555
+	c.Lock()
556
+	id, ok = c.ipamDrivers[name]
557
+	c.Unlock()
558
+	if !ok {
559
+		id, err = c.loadIpamDriver(name)
550 560
 	}
561
+	return id, err
562
+}
563
+
564
+func (c *controller) getIpamDriver(name string) (ipamapi.Ipam, error) {
565
+	id, err := c.getIPAM(name)
566
+	if err != nil {
567
+		return nil, err
568
+	}
569
+	return id.driver, nil
570
+}
571
+
572
+func (c *controller) Stop() {
573
+	c.closeStores()
551 574
 	c.stopExternalKeyListener()
552 575
 	osl.GC()
553 576
 }
554 577
new file mode 100644
... ...
@@ -0,0 +1,153 @@
0
+package datastore
1
+
2
+import (
3
+	"fmt"
4
+	"sync"
5
+
6
+	"github.com/docker/libkv/store"
7
+	"github.com/docker/libkv/store/boltdb"
8
+)
9
+
10
+type kvMap map[string]KVObject
11
+
12
+type cache struct {
13
+	sync.Mutex
14
+	kmm map[string]kvMap
15
+	ds  *datastore
16
+}
17
+
18
+func newCache(ds *datastore) *cache {
19
+	return &cache{kmm: make(map[string]kvMap), ds: ds}
20
+}
21
+
22
+func (c *cache) kmap(kvObject KVObject) (kvMap, error) {
23
+	var err error
24
+
25
+	c.Lock()
26
+	keyPrefix := Key(kvObject.KeyPrefix()...)
27
+	kmap, ok := c.kmm[keyPrefix]
28
+	c.Unlock()
29
+
30
+	if ok {
31
+		return kmap, nil
32
+	}
33
+
34
+	kmap = kvMap{}
35
+
36
+	// Bail out right away if the kvObject does not implement KVConstructor
37
+	ctor, ok := kvObject.(KVConstructor)
38
+	if !ok {
39
+		return nil, fmt.Errorf("error while populating kmap, object does not implement KVConstructor interface")
40
+	}
41
+
42
+	kvList, err := c.ds.store.List(keyPrefix)
43
+	if err != nil {
44
+		// In case of BoltDB it may return ErrBoltBucketNotFound when no writes
45
+		// have ever happened on the db bucket. So check for both err codes
46
+		if err == store.ErrKeyNotFound || err == boltdb.ErrBoltBucketNotFound {
47
+			// If the store doesn't have anything then there is nothing to
48
+			// populate in the cache. Just bail out.
49
+			goto out
50
+		}
51
+
52
+		return nil, fmt.Errorf("error while populating kmap: %v", err)
53
+	}
54
+
55
+	for _, kvPair := range kvList {
56
+		// Ignore empty kvPair values
57
+		if len(kvPair.Value) == 0 {
58
+			continue
59
+		}
60
+
61
+		dstO := ctor.New()
62
+		err = dstO.SetValue(kvPair.Value)
63
+		if err != nil {
64
+			return nil, err
65
+		}
66
+
67
+		// Make sure the object has a correct view of the DB index in
68
+		// case we need to modify it and update the DB.
69
+		dstO.SetIndex(kvPair.LastIndex)
70
+
71
+		kmap[Key(dstO.Key()...)] = dstO
72
+	}
73
+
74
+out:
75
+	// There may multiple go routines racing to fill the
76
+	// cache. The one which places the kmap in c.kmm first
77
+	// wins. The others should just use what the first populated.
78
+	c.Lock()
79
+	kmapNew, ok := c.kmm[keyPrefix]
80
+	if ok {
81
+		c.Unlock()
82
+		return kmapNew, nil
83
+	}
84
+
85
+	c.kmm[keyPrefix] = kmap
86
+	c.Unlock()
87
+
88
+	return kmap, nil
89
+}
90
+
91
+func (c *cache) add(kvObject KVObject) error {
92
+	kmap, err := c.kmap(kvObject)
93
+	if err != nil {
94
+		return err
95
+	}
96
+
97
+	c.Lock()
98
+	kmap[Key(kvObject.Key()...)] = kvObject
99
+	c.Unlock()
100
+	return nil
101
+}
102
+
103
+func (c *cache) del(kvObject KVObject) error {
104
+	kmap, err := c.kmap(kvObject)
105
+	if err != nil {
106
+		return err
107
+	}
108
+
109
+	c.Lock()
110
+	delete(kmap, Key(kvObject.Key()...))
111
+	c.Unlock()
112
+	return nil
113
+}
114
+
115
+func (c *cache) get(key string, kvObject KVObject) error {
116
+	kmap, err := c.kmap(kvObject)
117
+	if err != nil {
118
+		return err
119
+	}
120
+
121
+	c.Lock()
122
+	defer c.Unlock()
123
+
124
+	o, ok := kmap[Key(kvObject.Key()...)]
125
+	if !ok {
126
+		return ErrKeyNotFound
127
+	}
128
+
129
+	ctor, ok := o.(KVConstructor)
130
+	if !ok {
131
+		return fmt.Errorf("kvobject does not implement KVConstructor interface. could not get object")
132
+	}
133
+
134
+	return ctor.CopyTo(kvObject)
135
+}
136
+
137
+func (c *cache) list(kvObject KVObject) ([]KVObject, error) {
138
+	kmap, err := c.kmap(kvObject)
139
+	if err != nil {
140
+		return nil, err
141
+	}
142
+
143
+	c.Lock()
144
+	defer c.Unlock()
145
+
146
+	var kvol []KVObject
147
+	for _, v := range kmap {
148
+		kvol = append(kvol, v)
149
+	}
150
+
151
+	return kvol, nil
152
+}
... ...
@@ -1,8 +1,11 @@
1 1
 package datastore
2 2
 
3 3
 import (
4
+	"fmt"
5
+	"log"
4 6
 	"reflect"
5 7
 	"strings"
8
+	"sync"
6 9
 
7 10
 	"github.com/docker/libkv"
8 11
 	"github.com/docker/libkv/store"
... ...
@@ -10,26 +13,37 @@ import (
10 10
 	"github.com/docker/libkv/store/consul"
11 11
 	"github.com/docker/libkv/store/etcd"
12 12
 	"github.com/docker/libkv/store/zookeeper"
13
-	"github.com/docker/libnetwork/config"
14 13
 	"github.com/docker/libnetwork/types"
15 14
 )
16 15
 
17 16
 //DataStore exported
18 17
 type DataStore interface {
19 18
 	// GetObject gets data from datastore and unmarshals to the specified object
20
-	GetObject(key string, o KV) error
19
+	GetObject(key string, o KVObject) error
21 20
 	// PutObject adds a new Record based on an object into the datastore
22
-	PutObject(kvObject KV) error
21
+	PutObject(kvObject KVObject) error
23 22
 	// PutObjectAtomic provides an atomic add and update operation for a Record
24
-	PutObjectAtomic(kvObject KV) error
23
+	PutObjectAtomic(kvObject KVObject) error
25 24
 	// DeleteObject deletes a record
26
-	DeleteObject(kvObject KV) error
25
+	DeleteObject(kvObject KVObject) error
27 26
 	// DeleteObjectAtomic performs an atomic delete operation
28
-	DeleteObjectAtomic(kvObject KV) error
27
+	DeleteObjectAtomic(kvObject KVObject) error
29 28
 	// DeleteTree deletes a record
30
-	DeleteTree(kvObject KV) error
29
+	DeleteTree(kvObject KVObject) error
30
+	// Watchable returns whether the store is watchable are not
31
+	Watchable() bool
32
+	// Watch for changes on a KVObject
33
+	Watch(kvObject KVObject, stopCh <-chan struct{}) (<-chan KVObject, error)
34
+	// List returns of a list of KVObjects belonging to the parent
35
+	// key. The caller must pass a KVObject of the same type as
36
+	// the objects that need to be listed
37
+	List(string, KVObject) ([]KVObject, error)
38
+	// Scope returns the scope of the store
39
+	Scope() string
31 40
 	// KVStore returns access to the KV Store
32 41
 	KVStore() store.Store
42
+	// Close closes the data store
43
+	Close()
33 44
 }
34 45
 
35 46
 // ErrKeyModified is raised for an atomic update when the update is working on a stale state
... ...
@@ -39,11 +53,14 @@ var (
39 39
 )
40 40
 
41 41
 type datastore struct {
42
+	scope string
42 43
 	store store.Store
44
+	cache *cache
45
+	sync.Mutex
43 46
 }
44 47
 
45
-//KV Key Value interface used by objects to be part of the DataStore
46
-type KV interface {
48
+// KVObject is  Key/Value interface used by objects to be part of the DataStore
49
+type KVObject interface {
47 50
 	// Key method lets an object to provide the Key to be used in KV Store
48 51
 	Key() []string
49 52
 	// KeyPrefix method lets an object to return immediate parent key that can be used for tree walk
... ...
@@ -60,19 +77,39 @@ type KV interface {
60 60
 	// When SetIndex() is called, the object has been stored.
61 61
 	Exists() bool
62 62
 	// DataScope indicates the storage scope of the KV object
63
-	DataScope() DataScope
63
+	DataScope() string
64 64
 	// Skip provides a way for a KV Object to avoid persisting it in the KV Store
65 65
 	Skip() bool
66 66
 }
67 67
 
68
-// DataScope indicates the storage scope
69
-type DataScope int
68
+// KVConstructor interface defines methods which can construct a KVObject from another.
69
+type KVConstructor interface {
70
+	// New returns a new object which is created based on the
71
+	// source object
72
+	New() KVObject
73
+	// CopyTo deep copies the contents of the implementing object
74
+	// to the passed destination object
75
+	CopyTo(KVObject) error
76
+}
77
+
78
+// ScopeCfg represents Datastore configuration.
79
+type ScopeCfg struct {
80
+	Client ScopeClientCfg
81
+}
82
+
83
+// ScopeClientCfg represents Datastore Client-only mode configuration
84
+type ScopeClientCfg struct {
85
+	Provider string
86
+	Address  string
87
+	Config   *store.Config
88
+}
70 89
 
71 90
 const (
72 91
 	// LocalScope indicates to store the KV object in local datastore such as boltdb
73
-	LocalScope DataScope = iota
92
+	LocalScope = "local"
74 93
 	// GlobalScope indicates to store the KV object in global datastore such as consul/etcd/zookeeper
75
-	GlobalScope
94
+	GlobalScope   = "global"
95
+	defaultPrefix = "/var/lib/docker/network/files"
76 96
 )
77 97
 
78 98
 const (
... ...
@@ -82,7 +119,26 @@ const (
82 82
 	EndpointKeyPrefix = "endpoint"
83 83
 )
84 84
 
85
-var rootChain = []string{"docker", "libnetwork"}
85
+var (
86
+	defaultScopes = makeDefaultScopes()
87
+)
88
+
89
+func makeDefaultScopes() map[string]*ScopeCfg {
90
+	def := make(map[string]*ScopeCfg)
91
+	def[LocalScope] = &ScopeCfg{
92
+		Client: ScopeClientCfg{
93
+			Provider: "boltdb",
94
+			Address:  defaultPrefix + "/local-kv.db",
95
+			Config: &store.Config{
96
+				Bucket: "libnetwork",
97
+			},
98
+		},
99
+	}
100
+
101
+	return def
102
+}
103
+
104
+var rootChain = []string{"docker", "network", "v1.0"}
86 105
 
87 106
 func init() {
88 107
 	consul.Register()
... ...
@@ -91,6 +147,28 @@ func init() {
91 91
 	boltdb.Register()
92 92
 }
93 93
 
94
+// DefaultScopes returns a map of default scopes and it's config for clients to use.
95
+func DefaultScopes(dataDir string) map[string]*ScopeCfg {
96
+	if dataDir != "" {
97
+		defaultScopes[LocalScope].Client.Address = dataDir + "/network/files/local-kv.db"
98
+		return defaultScopes
99
+	}
100
+
101
+	defaultScopes[LocalScope].Client.Address = defaultPrefix + "/local-kv.db"
102
+	return defaultScopes
103
+}
104
+
105
+// IsValid checks if the scope config has valid configuration.
106
+func (cfg *ScopeCfg) IsValid() bool {
107
+	if cfg == nil ||
108
+		strings.TrimSpace(cfg.Client.Provider) == "" ||
109
+		strings.TrimSpace(cfg.Client.Address) == "" {
110
+		return false
111
+	}
112
+
113
+	return true
114
+}
115
+
94 116
 //Key provides convenient method to create a Key
95 117
 func Key(key ...string) string {
96 118
 	keychain := append(rootChain, key...)
... ...
@@ -110,7 +188,11 @@ func ParseKey(key string) ([]string, error) {
110 110
 }
111 111
 
112 112
 // newClient used to connect to KV Store
113
-func newClient(kv string, addrs string, config *store.Config) (DataStore, error) {
113
+func newClient(scope string, kv string, addrs string, config *store.Config, cached bool) (DataStore, error) {
114
+	if cached && scope != LocalScope {
115
+		return nil, fmt.Errorf("caching supported only for scope %s", LocalScope)
116
+	}
117
+
114 118
 	if config == nil {
115 119
 		config = &store.Config{}
116 120
 	}
... ...
@@ -118,22 +200,82 @@ func newClient(kv string, addrs string, config *store.Config) (DataStore, error)
118 118
 	if err != nil {
119 119
 		return nil, err
120 120
 	}
121
-	ds := &datastore{store: store}
121
+
122
+	ds := &datastore{scope: scope, store: store}
123
+	if cached {
124
+		ds.cache = newCache(ds)
125
+	}
126
+
122 127
 	return ds, nil
123 128
 }
124 129
 
125 130
 // NewDataStore creates a new instance of LibKV data store
126
-func NewDataStore(cfg *config.DatastoreCfg) (DataStore, error) {
127
-	if cfg == nil {
128
-		return nil, types.BadRequestErrorf("invalid configuration passed to datastore")
131
+func NewDataStore(scope string, cfg *ScopeCfg) (DataStore, error) {
132
+	if cfg == nil || cfg.Client.Provider == "" || cfg.Client.Address == "" {
133
+		c, ok := defaultScopes[scope]
134
+		if !ok || c.Client.Provider == "" || c.Client.Address == "" {
135
+			return nil, fmt.Errorf("unexpected scope %s without configuration passed", scope)
136
+		}
137
+
138
+		cfg = c
129 139
 	}
130
-	// TODO : cfg.Embedded case
131
-	return newClient(cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config)
140
+
141
+	var cached bool
142
+	if scope == LocalScope {
143
+		cached = true
144
+	}
145
+
146
+	return newClient(scope, cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config, cached)
132 147
 }
133 148
 
134
-// NewCustomDataStore can be used by clients to plugin cusom datatore that adhers to store.Store
135
-func NewCustomDataStore(customStore store.Store) DataStore {
136
-	return &datastore{store: customStore}
149
+func (ds *datastore) Close() {
150
+	ds.store.Close()
151
+}
152
+
153
+func (ds *datastore) Scope() string {
154
+	return ds.scope
155
+}
156
+
157
+func (ds *datastore) Watchable() bool {
158
+	return ds.scope != LocalScope
159
+}
160
+
161
+func (ds *datastore) Watch(kvObject KVObject, stopCh <-chan struct{}) (<-chan KVObject, error) {
162
+	sCh := make(chan struct{})
163
+
164
+	ctor, ok := kvObject.(KVConstructor)
165
+	if !ok {
166
+		return nil, fmt.Errorf("error watching object type %T, object does not implement KVConstructor interface", kvObject)
167
+	}
168
+
169
+	kvpCh, err := ds.store.Watch(Key(kvObject.Key()...), sCh)
170
+	if err != nil {
171
+		return nil, err
172
+	}
173
+
174
+	kvoCh := make(chan KVObject)
175
+
176
+	go func() {
177
+		for {
178
+			select {
179
+			case <-stopCh:
180
+				close(sCh)
181
+				return
182
+			case kvPair := <-kvpCh:
183
+				dstO := ctor.New()
184
+
185
+				if err := dstO.SetValue(kvPair.Value); err != nil {
186
+					log.Printf("Could not unmarshal kvpair value = %s", string(kvPair.Value))
187
+					break
188
+				}
189
+
190
+				dstO.SetIndex(kvPair.LastIndex)
191
+				kvoCh <- dstO
192
+			}
193
+		}
194
+	}()
195
+
196
+	return kvoCh, nil
137 197
 }
138 198
 
139 199
 func (ds *datastore) KVStore() store.Store {
... ...
@@ -141,40 +283,76 @@ func (ds *datastore) KVStore() store.Store {
141 141
 }
142 142
 
143 143
 // PutObjectAtomic adds a new Record based on an object into the datastore
144
-func (ds *datastore) PutObjectAtomic(kvObject KV) error {
144
+func (ds *datastore) PutObjectAtomic(kvObject KVObject) error {
145
+	var (
146
+		previous *store.KVPair
147
+		pair     *store.KVPair
148
+		err      error
149
+	)
150
+	ds.Lock()
151
+	defer ds.Unlock()
152
+
145 153
 	if kvObject == nil {
146 154
 		return types.BadRequestErrorf("invalid KV Object : nil")
147 155
 	}
156
+
148 157
 	kvObjValue := kvObject.Value()
149 158
 
150 159
 	if kvObjValue == nil {
151 160
 		return types.BadRequestErrorf("invalid KV Object with a nil Value for key %s", Key(kvObject.Key()...))
152 161
 	}
153 162
 
154
-	var previous *store.KVPair
163
+	if kvObject.Skip() {
164
+		goto add_cache
165
+	}
166
+
155 167
 	if kvObject.Exists() {
156 168
 		previous = &store.KVPair{Key: Key(kvObject.Key()...), LastIndex: kvObject.Index()}
157 169
 	} else {
158 170
 		previous = nil
159 171
 	}
160
-	_, pair, err := ds.store.AtomicPut(Key(kvObject.Key()...), kvObjValue, previous, nil)
172
+
173
+	_, pair, err = ds.store.AtomicPut(Key(kvObject.Key()...), kvObjValue, previous, nil)
161 174
 	if err != nil {
162 175
 		return err
163 176
 	}
164 177
 
165 178
 	kvObject.SetIndex(pair.LastIndex)
179
+
180
+add_cache:
181
+	if ds.cache != nil {
182
+		return ds.cache.add(kvObject)
183
+	}
184
+
166 185
 	return nil
167 186
 }
168 187
 
169 188
 // PutObject adds a new Record based on an object into the datastore
170
-func (ds *datastore) PutObject(kvObject KV) error {
189
+func (ds *datastore) PutObject(kvObject KVObject) error {
190
+	ds.Lock()
191
+	defer ds.Unlock()
192
+
171 193
 	if kvObject == nil {
172 194
 		return types.BadRequestErrorf("invalid KV Object : nil")
173 195
 	}
174
-	return ds.putObjectWithKey(kvObject, kvObject.Key()...)
196
+
197
+	if kvObject.Skip() {
198
+		goto add_cache
199
+	}
200
+
201
+	if err := ds.putObjectWithKey(kvObject, kvObject.Key()...); err != nil {
202
+		return err
203
+	}
204
+
205
+add_cache:
206
+	if ds.cache != nil {
207
+		return ds.cache.add(kvObject)
208
+	}
209
+
210
+	return nil
175 211
 }
176 212
 
177
-func (ds *datastore) putObjectWithKey(kvObject KV, key ...string) error {
213
+func (ds *datastore) putObjectWithKey(kvObject KVObject, key ...string) error {
178 214
 	kvObjValue := kvObject.Value()
179 215
 
180 216
 	if kvObjValue == nil {
... ...
@@ -184,39 +362,143 @@ func (ds *datastore) putObjectWithKey(kvObject KV, key ...string) error {
184 184
 }
185 185
 
186 186
 // GetObject returns a record matching the key
187
-func (ds *datastore) GetObject(key string, o KV) error {
187
+func (ds *datastore) GetObject(key string, o KVObject) error {
188
+	ds.Lock()
189
+	defer ds.Unlock()
190
+
191
+	if ds.cache != nil {
192
+		return ds.cache.get(key, o)
193
+	}
194
+
188 195
 	kvPair, err := ds.store.Get(key)
189 196
 	if err != nil {
190 197
 		return err
191 198
 	}
192
-	err = o.SetValue(kvPair.Value)
193
-	if err != nil {
199
+
200
+	if err := o.SetValue(kvPair.Value); err != nil {
194 201
 		return err
195 202
 	}
196 203
 
197
-	// Make sure the object has a correct view of the DB index in case we need to modify it
198
-	// and update the DB.
204
+	// Make sure the object has a correct view of the DB index in
205
+	// case we need to modify it and update the DB.
199 206
 	o.SetIndex(kvPair.LastIndex)
200 207
 	return nil
201 208
 }
202 209
 
210
+func (ds *datastore) ensureKey(key string) error {
211
+	exists, err := ds.store.Exists(key)
212
+	if err != nil {
213
+		return err
214
+	}
215
+	if exists {
216
+		return nil
217
+	}
218
+	return ds.store.Put(key, []byte{}, nil)
219
+}
220
+
221
+func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
222
+	ds.Lock()
223
+	defer ds.Unlock()
224
+
225
+	if ds.cache != nil {
226
+		return ds.cache.list(kvObject)
227
+	}
228
+
229
+	// Bail out right away if the kvObject does not implement KVConstructor
230
+	ctor, ok := kvObject.(KVConstructor)
231
+	if !ok {
232
+		return nil, fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
233
+	}
234
+
235
+	// Make sure the parent key exists
236
+	if err := ds.ensureKey(key); err != nil {
237
+		return nil, err
238
+	}
239
+
240
+	kvList, err := ds.store.List(key)
241
+	if err != nil {
242
+		return nil, err
243
+	}
244
+
245
+	var kvol []KVObject
246
+	for _, kvPair := range kvList {
247
+		if len(kvPair.Value) == 0 {
248
+			continue
249
+		}
250
+
251
+		dstO := ctor.New()
252
+		if err := dstO.SetValue(kvPair.Value); err != nil {
253
+			return nil, err
254
+		}
255
+
256
+		// Make sure the object has a correct view of the DB index in
257
+		// case we need to modify it and update the DB.
258
+		dstO.SetIndex(kvPair.LastIndex)
259
+
260
+		kvol = append(kvol, dstO)
261
+	}
262
+
263
+	return kvol, nil
264
+}
265
+
203 266
 // DeleteObject unconditionally deletes a record from the store
204
-func (ds *datastore) DeleteObject(kvObject KV) error {
267
+func (ds *datastore) DeleteObject(kvObject KVObject) error {
268
+	ds.Lock()
269
+	defer ds.Unlock()
270
+
271
+	// cleaup the cache first
272
+	if ds.cache != nil {
273
+		ds.cache.del(kvObject)
274
+	}
275
+
276
+	if kvObject.Skip() {
277
+		return nil
278
+	}
279
+
205 280
 	return ds.store.Delete(Key(kvObject.Key()...))
206 281
 }
207 282
 
208 283
 // DeleteObjectAtomic performs atomic delete on a record
209
-func (ds *datastore) DeleteObjectAtomic(kvObject KV) error {
284
+func (ds *datastore) DeleteObjectAtomic(kvObject KVObject) error {
285
+	ds.Lock()
286
+	defer ds.Unlock()
287
+
210 288
 	if kvObject == nil {
211 289
 		return types.BadRequestErrorf("invalid KV Object : nil")
212 290
 	}
213 291
 
214 292
 	previous := &store.KVPair{Key: Key(kvObject.Key()...), LastIndex: kvObject.Index()}
215
-	_, err := ds.store.AtomicDelete(Key(kvObject.Key()...), previous)
216
-	return err
293
+
294
+	if kvObject.Skip() {
295
+		goto del_cache
296
+	}
297
+
298
+	if _, err := ds.store.AtomicDelete(Key(kvObject.Key()...), previous); err != nil {
299
+		return err
300
+	}
301
+
302
+del_cache:
303
+	// cleanup the cache only if AtomicDelete went through successfully
304
+	if ds.cache != nil {
305
+		return ds.cache.del(kvObject)
306
+	}
307
+
308
+	return nil
217 309
 }
218 310
 
219 311
 // DeleteTree unconditionally deletes a record from the store
220
-func (ds *datastore) DeleteTree(kvObject KV) error {
312
+func (ds *datastore) DeleteTree(kvObject KVObject) error {
313
+	ds.Lock()
314
+	defer ds.Unlock()
315
+
316
+	// cleaup the cache first
317
+	if ds.cache != nil {
318
+		ds.cache.del(kvObject)
319
+	}
320
+
321
+	if kvObject.Skip() {
322
+		return nil
323
+	}
324
+
221 325
 	return ds.store.DeleteTree(Key(kvObject.KeyPrefix()...))
222 326
 }
... ...
@@ -4,7 +4,6 @@ import (
4 4
 	"fmt"
5 5
 
6 6
 	"github.com/docker/libnetwork/netlabel"
7
-	"github.com/docker/libnetwork/options"
8 7
 	"github.com/docker/libnetwork/types"
9 8
 )
10 9
 
... ...
@@ -92,25 +91,6 @@ func (sb *sandbox) clearDefaultGW() error {
92 92
 	return nil
93 93
 }
94 94
 
95
-func (c *controller) createGWNetwork() (Network, error) {
96
-	netOption := options.Generic{
97
-		"BridgeName":         libnGWNetwork,
98
-		"EnableICC":          false,
99
-		"EnableIPMasquerade": true,
100
-	}
101
-
102
-	n, err := c.NewNetwork("bridge", libnGWNetwork,
103
-		NetworkOptionGeneric(options.Generic{
104
-			netlabel.GenericData: netOption,
105
-			netlabel.EnableIPv6:  false,
106
-		}))
107
-
108
-	if err != nil {
109
-		return nil, fmt.Errorf("error creating external connectivity network: %v", err)
110
-	}
111
-	return n, err
112
-}
113
-
114 95
 func (sb *sandbox) needDefaultGW() bool {
115 96
 	var needGW bool
116 97
 
117 98
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+package libnetwork
1
+
2
+import "github.com/docker/libnetwork/types"
3
+
4
+func (c *controller) createGWNetwork() (Network, error) {
5
+	return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in freebsd")
6
+}
0 7
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+package libnetwork
1
+
2
+import (
3
+	"fmt"
4
+	"strconv"
5
+
6
+	"github.com/docker/libnetwork/drivers/bridge"
7
+	"github.com/docker/libnetwork/netlabel"
8
+	"github.com/docker/libnetwork/options"
9
+)
10
+
11
+func (c *controller) createGWNetwork() (Network, error) {
12
+	netOption := map[string]string{
13
+		bridge.BridgeName:         libnGWNetwork,
14
+		bridge.EnableICC:          strconv.FormatBool(false),
15
+		bridge.EnableIPMasquerade: strconv.FormatBool(true),
16
+	}
17
+
18
+	n, err := c.NewNetwork("bridge", libnGWNetwork,
19
+		NetworkOptionGeneric(options.Generic{
20
+			netlabel.GenericData: netOption,
21
+			netlabel.EnableIPv6:  false,
22
+		}))
23
+
24
+	if err != nil {
25
+		return nil, fmt.Errorf("error creating external connectivity network: %v", err)
26
+	}
27
+	return n, err
28
+}
0 29
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+package libnetwork
1
+
2
+import "github.com/docker/libnetwork/types"
3
+
4
+func (c *controller) createGWNetwork() (Network, error) {
5
+	return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in windows")
6
+}
... ...
@@ -1,10 +1,6 @@
1 1
 package driverapi
2 2
 
3
-import (
4
-	"net"
5
-
6
-	"github.com/docker/libnetwork/datastore"
7
-)
3
+import "net"
8 4
 
9 5
 // NetworkPluginEndpointType represents the Endpoint Type used by Plugin system
10 6
 const NetworkPluginEndpointType = "NetworkDriver"
... ...
@@ -14,7 +10,7 @@ type Driver interface {
14 14
 	// CreateNetwork invokes the driver method to create a network passing
15 15
 	// the network id and network specific config. The config mechanism will
16 16
 	// eventually be replaced with labels which are yet to be introduced.
17
-	CreateNetwork(nid string, options map[string]interface{}) error
17
+	CreateNetwork(nid string, options map[string]interface{}, ipV4Data, ipV6Data []IPAMData) error
18 18
 
19 19
 	// DeleteNetwork invokes the driver method to delete network passing
20 20
 	// the network id.
... ...
@@ -25,7 +21,7 @@ type Driver interface {
25 25
 	// specific config. The endpoint information can be either consumed by
26 26
 	// the driver or populated by the driver. The config mechanism will
27 27
 	// eventually be replaced with labels which are yet to be introduced.
28
-	CreateEndpoint(nid, eid string, epInfo EndpointInfo, options map[string]interface{}) error
28
+	CreateEndpoint(nid, eid string, ifInfo InterfaceInfo, options map[string]interface{}) error
29 29
 
30 30
 	// DeleteEndpoint invokes the driver method to delete an endpoint
31 31
 	// passing the network id and endpoint id.
... ...
@@ -50,31 +46,26 @@ type Driver interface {
50 50
 	Type() string
51 51
 }
52 52
 
53
-// EndpointInfo provides a go interface to fetch or populate endpoint assigned network resources.
54
-type EndpointInfo interface {
55
-	// Interface returns the interface bound to the endpoint.
56
-	// If the value is not nil the driver is only expected to consume the interface.
57
-	// It is an error to try to add interface if the passed down value is non-nil
58
-	// If the value is nil the driver is expected to add an interface
59
-	Interface() InterfaceInfo
60
-
61
-	// AddInterface is used by the driver to add an interface for the endpoint.
62
-	// This method will return an error if the driver attempts to add interface
63
-	// if the Interface() method returned a non-nil value.
64
-	AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error
65
-}
66
-
67 53
 // InterfaceInfo provides a go interface for drivers to retrive
68 54
 // network information to interface resources.
69 55
 type InterfaceInfo interface {
56
+	// SetMacAddress allows the driver to set the mac address to the endpoint interface
57
+	// during the call to CreateEndpoint, if the mac address is not already set.
58
+	SetMacAddress(mac net.HardwareAddr) error
59
+
60
+	// SetIPAddress allows the driver to set the ip address to the endpoint interface
61
+	// during the call to CreateEndpoint, if the address is not already set.
62
+	// The API is to be used to assign both the IPv4 and IPv6 address types.
63
+	SetIPAddress(ip *net.IPNet) error
64
+
70 65
 	// MacAddress returns the MAC address.
71 66
 	MacAddress() net.HardwareAddr
72 67
 
73 68
 	// Address returns the IPv4 address.
74
-	Address() net.IPNet
69
+	Address() *net.IPNet
75 70
 
76 71
 	// AddressIPv6 returns the IPv6 address.
77
-	AddressIPv6() net.IPNet
72
+	AddressIPv6() *net.IPNet
78 73
 }
79 74
 
80 75
 // InterfaceNameInfo provides a go interface for the drivers to assign names
... ...
@@ -110,7 +101,7 @@ type DriverCallback interface {
110 110
 
111 111
 // Capability represents the high level capabilities of the drivers which libnetwork can make use of
112 112
 type Capability struct {
113
-	DataScope datastore.DataScope
113
+	DataScope string
114 114
 }
115 115
 
116 116
 // DiscoveryType represents the type of discovery element the DiscoverNew function is invoked on
... ...
@@ -126,3 +117,13 @@ type NodeDiscoveryData struct {
126 126
 	Address string
127 127
 	Self    bool
128 128
 }
129
+
130
+// IPAMData represents the per-network ip related
131
+// operational information libnetwork will send
132
+// to the network driver during CreateNetwork()
133
+type IPAMData struct {
134
+	AddressSpace string
135
+	Pool         *net.IPNet
136
+	Gateway      *net.IPNet
137
+	AuxAddresses map[string]*net.IPNet
138
+}
129 139
new file mode 100644
... ...
@@ -0,0 +1,103 @@
0
+package driverapi
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+	"net"
6
+
7
+	"github.com/docker/libnetwork/types"
8
+)
9
+
10
+// MarshalJSON encodes IPAMData into json message
11
+func (i *IPAMData) MarshalJSON() ([]byte, error) {
12
+	m := map[string]interface{}{}
13
+	m["AddressSpace"] = i.AddressSpace
14
+	if i.Pool != nil {
15
+		m["Pool"] = i.Pool.String()
16
+	}
17
+	if i.Gateway != nil {
18
+		m["Gateway"] = i.Gateway.String()
19
+	}
20
+	if i.AuxAddresses != nil {
21
+		am := make(map[string]string, len(i.AuxAddresses))
22
+		for k, v := range i.AuxAddresses {
23
+			am[k] = v.String()
24
+		}
25
+		m["AuxAddresses"] = am
26
+	}
27
+	return json.Marshal(m)
28
+}
29
+
30
+// UnmarshalJSON decodes a json message into IPAMData
31
+func (i *IPAMData) UnmarshalJSON(data []byte) error {
32
+	var (
33
+		m   map[string]interface{}
34
+		err error
35
+	)
36
+	if err := json.Unmarshal(data, &m); err != nil {
37
+		return err
38
+	}
39
+	i.AddressSpace = m["AddressSpace"].(string)
40
+	if v, ok := m["Pool"]; ok {
41
+		if i.Pool, err = types.ParseCIDR(v.(string)); err != nil {
42
+			return err
43
+		}
44
+	}
45
+	if v, ok := m["Gateway"]; ok {
46
+		if i.Gateway, err = types.ParseCIDR(v.(string)); err != nil {
47
+			return err
48
+		}
49
+	}
50
+	if v, ok := m["AuxAddresses"]; ok {
51
+		b, _ := json.Marshal(v)
52
+		var am map[string]string
53
+		if err = json.Unmarshal(b, &am); err != nil {
54
+			return err
55
+		}
56
+		i.AuxAddresses = make(map[string]*net.IPNet, len(am))
57
+		for k, v := range am {
58
+			if i.AuxAddresses[k], err = types.ParseCIDR(v); err != nil {
59
+				return err
60
+			}
61
+		}
62
+	}
63
+	return nil
64
+}
65
+
66
+// Validate checks wheter the IPAMData structure contains congruent data
67
+func (i *IPAMData) Validate() error {
68
+	var isV6 bool
69
+	if i.Pool == nil {
70
+		return types.BadRequestErrorf("invalid pool")
71
+	}
72
+	if i.Gateway == nil {
73
+		return types.BadRequestErrorf("invalid gateway address")
74
+	}
75
+	isV6 = i.IsV6()
76
+	if isV6 && i.Gateway.IP.To4() != nil || !isV6 && i.Gateway.IP.To4() == nil {
77
+		return types.BadRequestErrorf("incongruent ip versions for pool and gateway")
78
+	}
79
+	for k, sip := range i.AuxAddresses {
80
+		if isV6 && sip.IP.To4() != nil || !isV6 && sip.IP.To4() == nil {
81
+			return types.BadRequestErrorf("incongruent ip versions for pool and secondary ip address %s", k)
82
+		}
83
+	}
84
+	if !i.Pool.Contains(i.Gateway.IP) {
85
+		return types.BadRequestErrorf("invalid gateway address (%s) does not belong to the pool (%s)", i.Gateway, i.Pool)
86
+	}
87
+	for k, sip := range i.AuxAddresses {
88
+		if !i.Pool.Contains(sip.IP) {
89
+			return types.BadRequestErrorf("invalid secondary address %s (%s) does not belong to the pool (%s)", k, i.Gateway, i.Pool)
90
+		}
91
+	}
92
+	return nil
93
+}
94
+
95
+// IsV6 returns wheter this is an IPv6 IPAMData structure
96
+func (i *IPAMData) IsV6() bool {
97
+	return nil == i.Pool.IP.To4()
98
+}
99
+
100
+func (i *IPAMData) String() string {
101
+	return fmt.Sprintf("AddressSpace: %s\nPool: %v\nGateway: %v\nAddresses: %v", i.AddressSpace, i.Pool, i.Gateway, i.AuxAddresses)
102
+}
... ...
@@ -4,6 +4,9 @@ import (
4 4
 	"strings"
5 5
 
6 6
 	"github.com/docker/libnetwork/driverapi"
7
+	"github.com/docker/libnetwork/ipamapi"
8
+	builtinIpam "github.com/docker/libnetwork/ipams/builtin"
9
+	remoteIpam "github.com/docker/libnetwork/ipams/remote"
7 10
 	"github.com/docker/libnetwork/netlabel"
8 11
 )
9 12
 
... ...
@@ -29,11 +32,6 @@ func makeDriverConfig(c *controller, ntype string) map[string]interface{} {
29 29
 
30 30
 	config := make(map[string]interface{})
31 31
 
32
-	if c.validateGlobalStoreConfig() {
33
-		config[netlabel.KVProvider] = c.cfg.GlobalStore.Client.Provider
34
-		config[netlabel.KVProviderURL] = c.cfg.GlobalStore.Client.Address
35
-	}
36
-
37 32
 	for _, label := range c.cfg.Daemon.Labels {
38 33
 		if !strings.HasPrefix(netlabel.Key(label), netlabel.DriverPrefix+"."+ntype) {
39 34
 			continue
... ...
@@ -43,13 +41,38 @@ func makeDriverConfig(c *controller, ntype string) map[string]interface{} {
43 43
 	}
44 44
 
45 45
 	drvCfg, ok := c.cfg.Daemon.DriverCfg[ntype]
46
-	if !ok {
46
+	if ok {
47
+		for k, v := range drvCfg.(map[string]interface{}) {
48
+			config[k] = v
49
+		}
50
+	}
51
+
52
+	// We don't send datastore configs to external plugins
53
+	if ntype == "remote" {
47 54
 		return config
48 55
 	}
49 56
 
50
-	for k, v := range drvCfg.(map[string]interface{}) {
51
-		config[k] = v
57
+	for k, v := range c.cfg.Scopes {
58
+		if !v.IsValid() {
59
+			continue
60
+		}
61
+
62
+		config[netlabel.MakeKVProvider(k)] = v.Client.Provider
63
+		config[netlabel.MakeKVProviderURL(k)] = v.Client.Address
64
+		config[netlabel.MakeKVProviderConfig(k)] = v.Client.Config
52 65
 	}
53 66
 
54 67
 	return config
55 68
 }
69
+
70
+func initIpams(ic ipamapi.Callback, lDs, gDs interface{}) error {
71
+	for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
72
+		builtinIpam.Init,
73
+		remoteIpam.Init,
74
+	} {
75
+		if err := fn(ic, lDs, gDs); err != nil {
76
+			return err
77
+		}
78
+	}
79
+	return nil
80
+}
... ...
@@ -16,7 +16,6 @@ import (
16 16
 	"github.com/Sirupsen/logrus"
17 17
 	"github.com/docker/libnetwork/datastore"
18 18
 	"github.com/docker/libnetwork/driverapi"
19
-	"github.com/docker/libnetwork/ipallocator"
20 19
 	"github.com/docker/libnetwork/iptables"
21 20
 	"github.com/docker/libnetwork/netlabel"
22 21
 	"github.com/docker/libnetwork/netutils"
... ...
@@ -35,8 +34,11 @@ const (
35 35
 	maxAllocatePortAttempts = 10
36 36
 )
37 37
 
38
-var (
39
-	ipAllocator *ipallocator.IPAllocator
38
+const (
39
+	// DefaultGatewayV4AuxKey represents the default-gateway configured by the user
40
+	DefaultGatewayV4AuxKey = "DefaultGatewayIPv4"
41
+	// DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user
42
+	DefaultGatewayV6AuxKey = "DefaultGatewayIPv6"
40 43
 )
41 44
 
42 45
 // configuration info for the "bridge" driver.
... ...
@@ -48,18 +50,21 @@ type configuration struct {
48 48
 
49 49
 // networkConfiguration for network specific configuration
50 50
 type networkConfiguration struct {
51
+	ID                 string
51 52
 	BridgeName         string
52
-	AddressIPv4        *net.IPNet
53
-	FixedCIDR          *net.IPNet
54
-	FixedCIDRv6        *net.IPNet
55 53
 	EnableIPv6         bool
56 54
 	EnableIPMasquerade bool
57 55
 	EnableICC          bool
58 56
 	Mtu                int
59
-	DefaultGatewayIPv4 net.IP
60
-	DefaultGatewayIPv6 net.IP
61 57
 	DefaultBindingIP   net.IP
62 58
 	DefaultBridge      bool
59
+	// Internal fields set after ipam data parsing
60
+	AddressIPv4        *net.IPNet
61
+	AddressIPv6        *net.IPNet
62
+	DefaultGatewayIPv4 net.IP
63
+	DefaultGatewayIPv6 net.IP
64
+	dbIndex            uint64
65
+	dbExists           bool
63 66
 }
64 67
 
65 68
 // endpointConfiguration represents the user specified configuration for the sandbox endpoint
... ...
@@ -102,12 +107,12 @@ type driver struct {
102 102
 	natChain    *iptables.ChainInfo
103 103
 	filterChain *iptables.ChainInfo
104 104
 	networks    map[string]*bridgeNetwork
105
+	store       datastore.DataStore
105 106
 	sync.Mutex
106 107
 }
107 108
 
108 109
 // New constructs a new bridge driver
109 110
 func newDriver() *driver {
110
-	ipAllocator = ipallocator.New()
111 111
 	return &driver{networks: map[string]*bridgeNetwork{}, config: &configuration{}}
112 112
 }
113 113
 
... ...
@@ -148,19 +153,6 @@ func (c *networkConfiguration) Validate() error {
148 148
 
149 149
 	// If bridge v4 subnet is specified
150 150
 	if c.AddressIPv4 != nil {
151
-		// If Container restricted subnet is specified, it must be a subset of bridge subnet
152
-		if c.FixedCIDR != nil {
153
-			// Check Network address
154
-			if !c.AddressIPv4.Contains(c.FixedCIDR.IP) {
155
-				return &ErrInvalidContainerSubnet{}
156
-			}
157
-			// Check it is effectively a subset
158
-			brNetLen, _ := c.AddressIPv4.Mask.Size()
159
-			cnNetLen, _ := c.FixedCIDR.Mask.Size()
160
-			if brNetLen > cnNetLen {
161
-				return &ErrInvalidContainerSubnet{}
162
-			}
163
-		}
164 151
 		// If default gw is specified, it must be part of bridge subnet
165 152
 		if c.DefaultGatewayIPv4 != nil {
166 153
 			if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
... ...
@@ -169,167 +161,81 @@ func (c *networkConfiguration) Validate() error {
169 169
 		}
170 170
 	}
171 171
 
172
-	// If default v6 gw is specified, FixedCIDRv6 must be specified and gw must belong to FixedCIDRv6 subnet
172
+	// If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet
173 173
 	if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil {
174
-		if c.FixedCIDRv6 == nil || !c.FixedCIDRv6.Contains(c.DefaultGatewayIPv6) {
174
+		if c.AddressIPv6 == nil || !c.AddressIPv6.Contains(c.DefaultGatewayIPv6) {
175 175
 			return &ErrInvalidGateway{}
176 176
 		}
177 177
 	}
178
-
179 178
 	return nil
180 179
 }
181 180
 
182 181
 // Conflicts check if two NetworkConfiguration objects overlap
183
-func (c *networkConfiguration) Conflicts(o *networkConfiguration) bool {
182
+func (c *networkConfiguration) Conflicts(o *networkConfiguration) error {
184 183
 	if o == nil {
185
-		return false
184
+		return fmt.Errorf("same configuration")
186 185
 	}
187 186
 
188 187
 	// Also empty, becasue only one network with empty name is allowed
189 188
 	if c.BridgeName == o.BridgeName {
190
-		return true
189
+		return fmt.Errorf("networks have same bridge name")
191 190
 	}
192 191
 
193 192
 	// They must be in different subnets
194 193
 	if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) &&
195 194
 		(c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) {
196
-		return true
195
+		return fmt.Errorf("networks have overlapping IPv4")
197 196
 	}
198 197
 
199
-	return false
200
-}
201
-
202
-// fromMap retrieve the configuration data from the map form.
203
-func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
204
-	var err error
205
-
206
-	if i, ok := data["BridgeName"]; ok && i != nil {
207
-		if c.BridgeName, ok = i.(string); !ok {
208
-			return types.BadRequestErrorf("invalid type for BridgeName value")
209
-		}
210
-	}
211
-
212
-	if i, ok := data["Mtu"]; ok && i != nil {
213
-		if s, ok := i.(string); ok {
214
-			if c.Mtu, err = strconv.Atoi(s); err != nil {
215
-				return types.BadRequestErrorf("failed to parse Mtu value: %s", err.Error())
216
-			}
217
-		} else {
218
-			return types.BadRequestErrorf("invalid type for Mtu value")
219
-		}
198
+	// They must be in different v6 subnets
199
+	if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) &&
200
+		(c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) {
201
+		return fmt.Errorf("networks have overlapping IPv6")
220 202
 	}
221 203
 
222
-	if i, ok := data["EnableIPv6"]; ok && i != nil {
223
-		if s, ok := i.(string); ok {
224
-			if c.EnableIPv6, err = strconv.ParseBool(s); err != nil {
225
-				return types.BadRequestErrorf("failed to parse EnableIPv6 value: %s", err.Error())
226
-			}
227
-		} else {
228
-			return types.BadRequestErrorf("invalid type for EnableIPv6 value")
229
-		}
230
-	}
231
-
232
-	if i, ok := data["EnableIPMasquerade"]; ok && i != nil {
233
-		if s, ok := i.(string); ok {
234
-			if c.EnableIPMasquerade, err = strconv.ParseBool(s); err != nil {
235
-				return types.BadRequestErrorf("failed to parse EnableIPMasquerade value: %s", err.Error())
236
-			}
237
-		} else {
238
-			return types.BadRequestErrorf("invalid type for EnableIPMasquerade value")
239
-		}
240
-	}
241
-
242
-	if i, ok := data["EnableICC"]; ok && i != nil {
243
-		if s, ok := i.(string); ok {
244
-			if c.EnableICC, err = strconv.ParseBool(s); err != nil {
245
-				return types.BadRequestErrorf("failed to parse EnableICC value: %s", err.Error())
246
-			}
247
-		} else {
248
-			return types.BadRequestErrorf("invalid type for EnableICC value")
249
-		}
250
-	}
204
+	return nil
205
+}
251 206
 
252
-	if i, ok := data["DefaultBridge"]; ok && i != nil {
253
-		if s, ok := i.(string); ok {
254
-			if c.DefaultBridge, err = strconv.ParseBool(s); err != nil {
255
-				return types.BadRequestErrorf("failed to parse DefaultBridge value: %s", err.Error())
207
+func (c *networkConfiguration) fromLabels(labels map[string]string) error {
208
+	var err error
209
+	for label, value := range labels {
210
+		switch label {
211
+		case BridgeName:
212
+			c.BridgeName = value
213
+		case netlabel.DriverMTU:
214
+			if c.Mtu, err = strconv.Atoi(value); err != nil {
215
+				return parseErr(label, value, err.Error())
256 216
 			}
257
-		} else {
258
-			return types.BadRequestErrorf("invalid type for DefaultBridge value")
259
-		}
260
-	}
261
-
262
-	if i, ok := data["AddressIPv4"]; ok && i != nil {
263
-		if s, ok := i.(string); ok {
264
-			if ip, nw, e := net.ParseCIDR(s); e == nil {
265
-				nw.IP = ip
266
-				c.AddressIPv4 = nw
267
-			} else {
268
-				return types.BadRequestErrorf("failed to parse AddressIPv4 value")
217
+		case netlabel.EnableIPv6:
218
+			if c.EnableIPv6, err = strconv.ParseBool(value); err != nil {
219
+				return parseErr(label, value, err.Error())
269 220
 			}
270
-		} else {
271
-			return types.BadRequestErrorf("invalid type for AddressIPv4 value")
272
-		}
273
-	}
274
-
275
-	if i, ok := data["FixedCIDR"]; ok && i != nil {
276
-		if s, ok := i.(string); ok {
277
-			if ip, nw, e := net.ParseCIDR(s); e == nil {
278
-				nw.IP = ip
279
-				c.FixedCIDR = nw
280
-			} else {
281
-				return types.BadRequestErrorf("failed to parse FixedCIDR value")
221
+		case EnableIPMasquerade:
222
+			if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil {
223
+				return parseErr(label, value, err.Error())
282 224
 			}
283
-		} else {
284
-			return types.BadRequestErrorf("invalid type for FixedCIDR value")
285
-		}
286
-	}
287
-
288
-	if i, ok := data["FixedCIDRv6"]; ok && i != nil {
289
-		if s, ok := i.(string); ok {
290
-			if ip, nw, e := net.ParseCIDR(s); e == nil {
291
-				nw.IP = ip
292
-				c.FixedCIDRv6 = nw
293
-			} else {
294
-				return types.BadRequestErrorf("failed to parse FixedCIDRv6 value")
225
+		case EnableICC:
226
+			if c.EnableICC, err = strconv.ParseBool(value); err != nil {
227
+				return parseErr(label, value, err.Error())
295 228
 			}
296
-		} else {
297
-			return types.BadRequestErrorf("invalid type for FixedCIDRv6 value")
298
-		}
299
-	}
300
-
301
-	if i, ok := data["DefaultGatewayIPv4"]; ok && i != nil {
302
-		if s, ok := i.(string); ok {
303
-			if c.DefaultGatewayIPv4 = net.ParseIP(s); c.DefaultGatewayIPv4 == nil {
304
-				return types.BadRequestErrorf("failed to parse DefaultGatewayIPv4 value")
229
+		case DefaultBridge:
230
+			if c.DefaultBridge, err = strconv.ParseBool(value); err != nil {
231
+				return parseErr(label, value, err.Error())
305 232
 			}
306
-		} else {
307
-			return types.BadRequestErrorf("invalid type for DefaultGatewayIPv4 value")
308
-		}
309
-	}
310
-
311
-	if i, ok := data["DefaultGatewayIPv6"]; ok && i != nil {
312
-		if s, ok := i.(string); ok {
313
-			if c.DefaultGatewayIPv6 = net.ParseIP(s); c.DefaultGatewayIPv6 == nil {
314
-				return types.BadRequestErrorf("failed to parse DefaultGatewayIPv6 value")
233
+		case DefaultBindingIP:
234
+			if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil {
235
+				return parseErr(label, value, "nil ip")
315 236
 			}
316
-		} else {
317
-			return types.BadRequestErrorf("invalid type for DefaultGatewayIPv6 value")
318 237
 		}
319 238
 	}
320 239
 
321
-	if i, ok := data["DefaultBindingIP"]; ok && i != nil {
322
-		if s, ok := i.(string); ok {
323
-			if c.DefaultBindingIP = net.ParseIP(s); c.DefaultBindingIP == nil {
324
-				return types.BadRequestErrorf("failed to parse DefaultBindingIP value")
325
-			}
326
-		} else {
327
-			return types.BadRequestErrorf("invalid type for DefaultBindingIP value")
328
-		}
329
-	}
330 240
 	return nil
331 241
 }
332 242
 
243
+func parseErr(label, value, errString string) error {
244
+	return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString)
245
+}
246
+
333 247
 func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
334 248
 	n.Lock()
335 249
 	defer n.Unlock()
... ...
@@ -435,6 +341,11 @@ func (d *driver) configure(option map[string]interface{}) error {
435 435
 	var config *configuration
436 436
 	var err error
437 437
 
438
+	err = d.initStore(option)
439
+	if err != nil {
440
+		return err
441
+	}
442
+
438 443
 	d.Lock()
439 444
 	defer d.Unlock()
440 445
 
... ...
@@ -498,12 +409,12 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
498 498
 	switch opt := data.(type) {
499 499
 	case *networkConfiguration:
500 500
 		config = opt
501
-	case map[string]interface{}:
501
+	case map[string]string:
502 502
 		config = &networkConfiguration{
503 503
 			EnableICC:          true,
504 504
 			EnableIPMasquerade: true,
505 505
 		}
506
-		err = config.fromMap(opt)
506
+		err = config.fromLabels(opt)
507 507
 	case options.Generic:
508 508
 		var opaqueConfig interface{}
509 509
 		if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
... ...
@@ -516,9 +427,41 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
516 516
 	return config, err
517 517
 }
518 518
 
519
+func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
520
+	if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
521
+		return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets")
522
+	}
523
+
524
+	if len(ipamV4Data) == 0 {
525
+		return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id)
526
+	}
527
+
528
+	if ipamV4Data[0].Gateway != nil {
529
+		c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway)
530
+	}
531
+
532
+	if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok {
533
+		c.DefaultGatewayIPv4 = gw.IP
534
+	}
535
+
536
+	if len(ipamV6Data) > 0 {
537
+		if ipamV6Data[0].Gateway != nil {
538
+			c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway)
539
+		}
540
+
541
+		if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok {
542
+			c.DefaultGatewayIPv6 = gw.IP
543
+		}
544
+	}
545
+
546
+	return nil
547
+}
548
+
519 549
 func parseNetworkOptions(id string, option options.Generic) (*networkConfiguration, error) {
520
-	var err error
521
-	config := &networkConfiguration{}
550
+	var (
551
+		err    error
552
+		config = &networkConfiguration{}
553
+	)
522 554
 
523 555
 	// Parse generic label first, config will be re-assigned
524 556
 	if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
... ...
@@ -528,8 +471,8 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati
528 528
 	}
529 529
 
530 530
 	// Process well-known labels next
531
-	if _, ok := option[netlabel.EnableIPv6]; ok {
532
-		config.EnableIPv6 = option[netlabel.EnableIPv6].(bool)
531
+	if val, ok := option[netlabel.EnableIPv6]; ok {
532
+		config.EnableIPv6 = val.(bool)
533 533
 	}
534 534
 
535 535
 	// Finally validate the configuration
... ...
@@ -540,15 +483,16 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati
540 540
 	if config.BridgeName == "" && config.DefaultBridge == false {
541 541
 		config.BridgeName = "br-" + id[:12]
542 542
 	}
543
+
544
+	config.ID = id
543 545
 	return config, nil
544 546
 }
545 547
 
546 548
 // Returns the non link-local IPv6 subnet for the containers attached to this bridge if found, nil otherwise
547 549
 func getV6Network(config *networkConfiguration, i *bridgeInterface) *net.IPNet {
548
-	if config.FixedCIDRv6 != nil {
549
-		return config.FixedCIDRv6
550
+	if config.AddressIPv6 != nil {
551
+		return config.AddressIPv6
550 552
 	}
551
-
552 553
 	if i.bridgeIPv6 != nil && i.bridgeIPv6.IP != nil && !i.bridgeIPv6.IP.IsLinkLocalUnicast() {
553 554
 		return i.bridgeIPv6
554 555
 	}
... ...
@@ -569,11 +513,7 @@ func (d *driver) getNetworks() []*bridgeNetwork {
569 569
 }
570 570
 
571 571
 // Create a new network using bridge plugin
572
-func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
573
-	var err error
574
-
575
-	defer osl.InitOSContext()()
576
-
572
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
577 573
 	// Sanity checks
578 574
 	d.Lock()
579 575
 	if _, ok := d.networks[id]; ok {
... ...
@@ -587,19 +527,38 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
587 587
 	if err != nil {
588 588
 		return err
589 589
 	}
590
+
591
+	err = config.processIPAM(id, ipV4Data, ipV6Data)
592
+	if err != nil {
593
+		return err
594
+	}
595
+
596
+	if err = d.createNetwork(config); err != nil {
597
+		return err
598
+	}
599
+
600
+	return d.storeUpdate(config)
601
+}
602
+
603
+func (d *driver) createNetwork(config *networkConfiguration) error {
604
+	var err error
605
+
606
+	defer osl.InitOSContext()()
607
+
590 608
 	networkList := d.getNetworks()
591 609
 	for _, nw := range networkList {
592 610
 		nw.Lock()
593 611
 		nwConfig := nw.config
594 612
 		nw.Unlock()
595
-		if nwConfig.Conflicts(config) {
596
-			return types.ForbiddenErrorf("conflicts with network %s (%s)", nw.id, nw.config.BridgeName)
613
+		if err := nwConfig.Conflicts(config); err != nil {
614
+			return types.ForbiddenErrorf("cannot create network %s (%s): conflicts with network %s (%s): %s",
615
+				nwConfig.BridgeName, config.ID, nw.id, nw.config.BridgeName, err.Error())
597 616
 		}
598 617
 	}
599 618
 
600 619
 	// Create and set network handler in driver
601 620
 	network := &bridgeNetwork{
602
-		id:         id,
621
+		id:         config.ID,
603 622
 		endpoints:  make(map[string]*bridgeEndpoint),
604 623
 		config:     config,
605 624
 		portMapper: portmapper.New(),
... ...
@@ -607,14 +566,14 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
607 607
 	}
608 608
 
609 609
 	d.Lock()
610
-	d.networks[id] = network
610
+	d.networks[config.ID] = network
611 611
 	d.Unlock()
612 612
 
613 613
 	// On failure make sure to reset driver network handler to nil
614 614
 	defer func() {
615 615
 		if err != nil {
616 616
 			d.Lock()
617
-			delete(d.networks, id)
617
+			delete(d.networks, config.ID)
618 618
 			d.Unlock()
619 619
 		}
620 620
 	}()
... ...
@@ -627,7 +586,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
627 627
 	// networks. This step is needed now because driver might have now set the bridge
628 628
 	// name on this config struct. And because we need to check for possible address
629 629
 	// conflicts, so we need to check against operationa lnetworks.
630
-	if err = config.conflictsWithNetworks(id, networkList); err != nil {
630
+	if err = config.conflictsWithNetworks(config.ID, networkList); err != nil {
631 631
 		return err
632 632
 	}
633 633
 
... ...
@@ -654,10 +613,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
654 654
 	// Even if a bridge exists try to setup IPv4.
655 655
 	bridgeSetup.queueStep(setupBridgeIPv4)
656 656
 
657
-	enableIPv6Forwarding := false
658
-	if d.config.EnableIPForwarding && config.FixedCIDRv6 != nil {
659
-		enableIPv6Forwarding = true
660
-	}
657
+	enableIPv6Forwarding := d.config.EnableIPForwarding && config.AddressIPv6 != nil
661 658
 
662 659
 	// Conditionally queue setup steps depending on configuration values.
663 660
 	for _, step := range []struct {
... ...
@@ -674,14 +630,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
674 674
 		// the case of a previously existing device.
675 675
 		{bridgeAlreadyExists, setupVerifyAndReconcile},
676 676
 
677
-		// Setup the bridge to allocate containers IPv4 addresses in the
678
-		// specified subnet.
679
-		{config.FixedCIDR != nil, setupFixedCIDRv4},
680
-
681
-		// Setup the bridge to allocate containers global IPv6 addresses in the
682
-		// specified subnet.
683
-		{config.FixedCIDRv6 != nil, setupFixedCIDRv6},
684
-
685 677
 		// Enable IPv6 Forwarding
686 678
 		{enableIPv6Forwarding, setupIPv6Forwarding},
687 679
 
... ...
@@ -712,8 +660,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
712 712
 		}
713 713
 	}
714 714
 
715
-	// Block bridge IP from being allocated.
716
-	bridgeSetup.queueStep(allocateBridgeIP)
717 715
 	// Apply the prepared list of steps, and abort at the first error.
718 716
 	bridgeSetup.queueStep(setupDeviceUp)
719 717
 	if err = bridgeSetup.apply(); err != nil {
... ...
@@ -741,10 +687,6 @@ func (d *driver) DeleteNetwork(nid string) error {
741 741
 	config := n.config
742 742
 	n.Unlock()
743 743
 
744
-	if config.BridgeName == DefaultBridgeName {
745
-		return types.ForbiddenErrorf("default network of type \"%s\" cannot be deleted", networkType)
746
-	}
747
-
748 744
 	d.Lock()
749 745
 	delete(d.networks, nid)
750 746
 	d.Unlock()
... ...
@@ -789,22 +731,12 @@ func (d *driver) DeleteNetwork(nid string) error {
789 789
 		return err
790 790
 	}
791 791
 
792
-	// Programming
793
-	err = netlink.LinkDel(n.bridge.Link)
794
-
795
-	// Release ip addresses (ignore errors)
796
-	if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) {
797
-		if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.gatewayIPv4); e != nil {
798
-			logrus.Warnf("Failed to release default gateway address %s: %v", n.bridge.gatewayIPv4.String(), e)
799
-		}
800
-	}
801
-	if config.FixedCIDR == nil || config.FixedCIDR.Contains(n.bridge.bridgeIPv4.IP) {
802
-		if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.bridgeIPv4.IP); e != nil {
803
-			logrus.Warnf("Failed to release bridge IP %s: %v", n.bridge.bridgeIPv4.IP.String(), e)
804
-		}
792
+	// We only delete the bridge when it's not the default bridge. This is keep the backward compatible behavior.
793
+	if !config.DefaultBridge {
794
+		err = netlink.LinkDel(n.bridge.Link)
805 795
 	}
806 796
 
807
-	return err
797
+	return d.storeDelete(config)
808 798
 }
809 799
 
810 800
 func addToBridge(ifaceName, bridgeName string) error {
... ...
@@ -861,20 +793,11 @@ func setHairpinMode(link netlink.Link, enable bool) error {
861 861
 	return nil
862 862
 }
863 863
 
864
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
865
-	var (
866
-		ipv6Addr *net.IPNet
867
-		err      error
868
-	)
869
-
864
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
870 865
 	defer osl.InitOSContext()()
871 866
 
872
-	if epInfo == nil {
873
-		return errors.New("invalid endpoint info passed")
874
-	}
875
-
876
-	if epInfo.Interface() != nil {
877
-		return errors.New("non-nil interface passed to bridge(local) driver")
867
+	if ifInfo == nil {
868
+		return errors.New("invalid interface info passed")
878 869
 	}
879 870
 
880 871
 	// Get the network handler and make sure it exists
... ...
@@ -1000,12 +923,11 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo,
1000 1000
 		}
1001 1001
 	}
1002 1002
 
1003
-	// v4 address for the sandbox side pipe interface
1004
-	ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
1005
-	if err != nil {
1006
-		return err
1007
-	}
1008
-	ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
1003
+	// Create the sandbox side pipe interface
1004
+	endpoint.srcName = containerIfName
1005
+	endpoint.macAddress = ifInfo.MacAddress()
1006
+	endpoint.addr = ifInfo.Address()
1007
+	endpoint.addrv6 = ifInfo.AddressIPv6()
1009 1008
 
1010 1009
 	// Down the interface before configuring mac address.
1011 1010
 	if err = netlink.LinkSetDown(sbox); err != nil {
... ...
@@ -1013,56 +935,38 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo,
1013 1013
 	}
1014 1014
 
1015 1015
 	// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
1016
-	mac := electMacAddress(epConfig, ip4)
1017
-	err = netlink.LinkSetHardwareAddr(sbox, mac)
1016
+	if endpoint.macAddress == nil {
1017
+		endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP)
1018
+		if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil {
1019
+			return err
1020
+		}
1021
+	}
1022
+	err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress)
1018 1023
 	if err != nil {
1019 1024
 		return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
1020 1025
 	}
1021
-	endpoint.macAddress = mac
1022 1026
 
1023 1027
 	// Up the host interface after finishing all netlink configuration
1024 1028
 	if err = netlink.LinkSetUp(host); err != nil {
1025 1029
 		return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
1026 1030
 	}
1027 1031
 
1028
-	// v6 address for the sandbox side pipe interface
1029
-	ipv6Addr = &net.IPNet{}
1030
-	if config.EnableIPv6 {
1032
+	if endpoint.addrv6 == nil && config.EnableIPv6 {
1031 1033
 		var ip6 net.IP
1032
-
1033 1034
 		network := n.bridge.bridgeIPv6
1034
-		if config.FixedCIDRv6 != nil {
1035
-			network = config.FixedCIDRv6
1036
-		}
1037
-
1038 1035
 		ones, _ := network.Mask.Size()
1039 1036
 		if ones <= 80 {
1040 1037
 			ip6 = make(net.IP, len(network.IP))
1041 1038
 			copy(ip6, network.IP)
1042
-			for i, h := range mac {
1039
+			for i, h := range endpoint.macAddress {
1043 1040
 				ip6[i+10] = h
1044 1041
 			}
1045 1042
 		}
1046 1043
 
1047
-		ip6, err := ipAllocator.RequestIP(network, ip6)
1048
-		if err != nil {
1044
+		endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask}
1045
+		if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil {
1049 1046
 			return err
1050 1047
 		}
1051
-
1052
-		ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask}
1053
-	}
1054
-
1055
-	// Create the sandbox side pipe interface
1056
-	endpoint.srcName = containerIfName
1057
-	endpoint.addr = ipv4Addr
1058
-
1059
-	if config.EnableIPv6 {
1060
-		endpoint.addrv6 = ipv6Addr
1061
-	}
1062
-
1063
-	err = epInfo.AddInterface(endpoint.macAddress, *ipv4Addr, *ipv6Addr)
1064
-	if err != nil {
1065
-		return err
1066 1048
 	}
1067 1049
 
1068 1050
 	// Program any required port mapping and store them in the endpoint
... ...
@@ -1128,28 +1032,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
1128 1128
 	// Remove port mappings. Do not stop endpoint delete on unmap failure
1129 1129
 	n.releasePorts(ep)
1130 1130
 
1131
-	// Release the v4 address allocated to this endpoint's sandbox interface
1132
-	err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.addr.IP)
1133
-	if err != nil {
1134
-		return err
1135
-	}
1136
-
1137
-	n.Lock()
1138
-	config := n.config
1139
-	n.Unlock()
1140
-
1141
-	// Release the v6 address allocated to this endpoint's sandbox interface
1142
-	if config.EnableIPv6 {
1143
-		network := n.bridge.bridgeIPv6
1144
-		if config.FixedCIDRv6 != nil {
1145
-			network = config.FixedCIDRv6
1146
-		}
1147
-		err := ipAllocator.ReleaseIP(network, ep.addrv6.IP)
1148
-		if err != nil {
1149
-			return err
1150
-		}
1151
-	}
1152
-
1153 1131
 	// Try removal of link. Discard error: link pair might have
1154 1132
 	// already been deleted by sandbox delete. Make sure defer
1155 1133
 	// does not see this error either.
1156 1134
new file mode 100644
... ...
@@ -0,0 +1,211 @@
0
+package bridge
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+	"net"
6
+
7
+	"github.com/Sirupsen/logrus"
8
+	"github.com/docker/libkv/store"
9
+	"github.com/docker/libkv/store/boltdb"
10
+	"github.com/docker/libnetwork/datastore"
11
+	"github.com/docker/libnetwork/netlabel"
12
+	"github.com/docker/libnetwork/types"
13
+)
14
+
15
+const bridgePrefix = "bridge"
16
+
17
+func (d *driver) initStore(option map[string]interface{}) error {
18
+	var err error
19
+
20
+	provider, provOk := option[netlabel.LocalKVProvider]
21
+	provURL, urlOk := option[netlabel.LocalKVProviderURL]
22
+
23
+	if provOk && urlOk {
24
+		cfg := &datastore.ScopeCfg{
25
+			Client: datastore.ScopeClientCfg{
26
+				Provider: provider.(string),
27
+				Address:  provURL.(string),
28
+			},
29
+		}
30
+
31
+		provConfig, confOk := option[netlabel.LocalKVProviderConfig]
32
+		if confOk {
33
+			cfg.Client.Config = provConfig.(*store.Config)
34
+		}
35
+
36
+		d.store, err = datastore.NewDataStore(datastore.LocalScope, cfg)
37
+		if err != nil {
38
+			return fmt.Errorf("bridge driver failed to initialize data store: %v", err)
39
+		}
40
+
41
+		return d.populateNetworks()
42
+	}
43
+
44
+	return nil
45
+}
46
+
47
+func (d *driver) populateNetworks() error {
48
+	kvol, err := d.store.List(datastore.Key(bridgePrefix), &networkConfiguration{})
49
+	if err != nil && err != datastore.ErrKeyNotFound && err != boltdb.ErrBoltBucketNotFound {
50
+		return fmt.Errorf("failed to get bridge network configurations from store: %v", err)
51
+	}
52
+
53
+	// It's normal for network configuration state to be empty. Just return.
54
+	if err == datastore.ErrKeyNotFound {
55
+		return nil
56
+	}
57
+
58
+	for _, kvo := range kvol {
59
+		ncfg := kvo.(*networkConfiguration)
60
+		if err = d.createNetwork(ncfg); err != nil {
61
+			logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state", ncfg.ID, ncfg.BridgeName)
62
+		}
63
+	}
64
+
65
+	return nil
66
+}
67
+
68
+func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
69
+	if d.store == nil {
70
+		logrus.Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
71
+		return nil
72
+	}
73
+
74
+	if err := d.store.PutObjectAtomic(kvObject); err != nil {
75
+		return fmt.Errorf("failed to update bridge store for object type %T: %v", kvObject, err)
76
+	}
77
+
78
+	return nil
79
+}
80
+
81
+func (d *driver) storeDelete(kvObject datastore.KVObject) error {
82
+	if d.store == nil {
83
+		logrus.Debugf("bridge store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
84
+		return nil
85
+	}
86
+
87
+retry:
88
+	if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
89
+		if err == datastore.ErrKeyModified {
90
+			if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
91
+				return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
92
+			}
93
+			goto retry
94
+		}
95
+		return err
96
+	}
97
+
98
+	return nil
99
+}
100
+
101
+func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
102
+	nMap := make(map[string]interface{})
103
+	nMap["ID"] = ncfg.ID
104
+	nMap["BridgeName"] = ncfg.BridgeName
105
+	nMap["EnableIPv6"] = ncfg.EnableIPv6
106
+	nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
107
+	nMap["EnableICC"] = ncfg.EnableICC
108
+	nMap["Mtu"] = ncfg.Mtu
109
+	nMap["DefaultBridge"] = ncfg.DefaultBridge
110
+	nMap["DefaultBindingIP"] = ncfg.DefaultBindingIP.String()
111
+	nMap["DefaultGatewayIPv4"] = ncfg.DefaultGatewayIPv4.String()
112
+	nMap["DefaultGatewayIPv6"] = ncfg.DefaultGatewayIPv6.String()
113
+
114
+	if ncfg.AddressIPv4 != nil {
115
+		nMap["AddressIPv4"] = ncfg.AddressIPv4.String()
116
+	}
117
+
118
+	if ncfg.AddressIPv6 != nil {
119
+		nMap["AddressIPv6"] = ncfg.AddressIPv6.String()
120
+	}
121
+
122
+	return json.Marshal(nMap)
123
+}
124
+
125
+func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
126
+	var (
127
+		err  error
128
+		nMap map[string]interface{}
129
+	)
130
+
131
+	if err = json.Unmarshal(b, &nMap); err != nil {
132
+		return err
133
+	}
134
+
135
+	if v, ok := nMap["AddressIPv4"]; ok {
136
+		if ncfg.AddressIPv4, err = types.ParseCIDR(v.(string)); err != nil {
137
+			return types.InternalErrorf("failed to decode bridge network address IPv4 after json unmarshal: %s", v.(string))
138
+		}
139
+	}
140
+
141
+	if v, ok := nMap["AddressIPv6"]; ok {
142
+		if ncfg.AddressIPv6, err = types.ParseCIDR(v.(string)); err != nil {
143
+			return types.InternalErrorf("failed to decode bridge network address IPv6 after json unmarshal: %s", v.(string))
144
+		}
145
+	}
146
+
147
+	ncfg.DefaultBridge = nMap["DefaultBridge"].(bool)
148
+	ncfg.DefaultBindingIP = net.ParseIP(nMap["DefaultBindingIP"].(string))
149
+	ncfg.DefaultGatewayIPv4 = net.ParseIP(nMap["DefaultGatewayIPv4"].(string))
150
+	ncfg.DefaultGatewayIPv6 = net.ParseIP(nMap["DefaultGatewayIPv6"].(string))
151
+	ncfg.ID = nMap["ID"].(string)
152
+	ncfg.BridgeName = nMap["BridgeName"].(string)
153
+	ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
154
+	ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
155
+	ncfg.EnableICC = nMap["EnableICC"].(bool)
156
+	ncfg.Mtu = int(nMap["Mtu"].(float64))
157
+
158
+	return nil
159
+}
160
+
161
+func (ncfg *networkConfiguration) Key() []string {
162
+	return []string{bridgePrefix, ncfg.ID}
163
+}
164
+
165
+func (ncfg *networkConfiguration) KeyPrefix() []string {
166
+	return []string{bridgePrefix}
167
+}
168
+
169
+func (ncfg *networkConfiguration) Value() []byte {
170
+	b, err := json.Marshal(ncfg)
171
+	if err != nil {
172
+		return nil
173
+	}
174
+	return b
175
+}
176
+
177
+func (ncfg *networkConfiguration) SetValue(value []byte) error {
178
+	return json.Unmarshal(value, ncfg)
179
+}
180
+
181
+func (ncfg *networkConfiguration) Index() uint64 {
182
+	return ncfg.dbIndex
183
+}
184
+
185
+func (ncfg *networkConfiguration) SetIndex(index uint64) {
186
+	ncfg.dbIndex = index
187
+	ncfg.dbExists = true
188
+}
189
+
190
+func (ncfg *networkConfiguration) Exists() bool {
191
+	return ncfg.dbExists
192
+}
193
+
194
+func (ncfg *networkConfiguration) Skip() bool {
195
+	return ncfg.DefaultBridge
196
+}
197
+
198
+func (ncfg *networkConfiguration) New() datastore.KVObject {
199
+	return &networkConfiguration{}
200
+}
201
+
202
+func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
203
+	dstNcfg := o.(*networkConfiguration)
204
+	*dstNcfg = *ncfg
205
+	return nil
206
+}
207
+
208
+func (ncfg *networkConfiguration) DataScope() string {
209
+	return datastore.LocalScope
210
+}
0 211
new file mode 100644
... ...
@@ -0,0 +1,18 @@
0
+package bridge
1
+
2
+const (
3
+	// BridgeName label for bridge driver
4
+	BridgeName = "com.docker.network.bridge.name"
5
+
6
+	// EnableIPMasquerade label for bridge driver
7
+	EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade"
8
+
9
+	// EnableICC label
10
+	EnableICC = "com.docker.network.bridge.enable_icc"
11
+
12
+	// DefaultBindingIP label
13
+	DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4"
14
+
15
+	// DefaultBridge label
16
+	DefaultBridge = "com.docker.network.bridge.default_bridge"
17
+)
... ...
@@ -22,7 +22,7 @@ const (
22 22
 //Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
23 23
 func getIPVersion(config *networkConfiguration) ipVersion {
24 24
 	ipVersion := ipv4
25
-	if config.FixedCIDRv6 != nil || config.EnableIPv6 {
25
+	if config.AddressIPv6 != nil || config.EnableIPv6 {
26 26
 		ipVersion |= ipv6
27 27
 	}
28 28
 	return ipVersion
29 29
deleted file mode 100644
... ...
@@ -1,19 +0,0 @@
1
-package bridge
2
-
3
-import (
4
-	log "github.com/Sirupsen/logrus"
5
-)
6
-
7
-func setupFixedCIDRv4(config *networkConfiguration, i *bridgeInterface) error {
8
-	addrv4, _, err := i.addresses()
9
-	if err != nil {
10
-		return err
11
-	}
12
-
13
-	log.Debugf("Using IPv4 subnet: %v", config.FixedCIDR)
14
-	if err := ipAllocator.RegisterSubnet(addrv4.IPNet, config.FixedCIDR); err != nil {
15
-		return &FixedCIDRv4Error{Subnet: config.FixedCIDR, Net: addrv4.IPNet, Err: err}
16
-	}
17
-
18
-	return nil
19
-}
20 1
deleted file mode 100644
... ...
@@ -1,27 +0,0 @@
1
-package bridge
2
-
3
-import (
4
-	"os"
5
-
6
-	log "github.com/Sirupsen/logrus"
7
-	"github.com/vishvananda/netlink"
8
-)
9
-
10
-func setupFixedCIDRv6(config *networkConfiguration, i *bridgeInterface) error {
11
-	log.Debugf("Using IPv6 subnet: %v", config.FixedCIDRv6)
12
-	if err := ipAllocator.RegisterSubnet(config.FixedCIDRv6, config.FixedCIDRv6); err != nil {
13
-		return &FixedCIDRv6Error{Net: config.FixedCIDRv6, Err: err}
14
-	}
15
-
16
-	// Setting route to global IPv6 subnet
17
-	log.Debugf("Adding route to IPv6 network %s via device %s", config.FixedCIDRv6.String(), config.BridgeName)
18
-	err := netlink.RouteAdd(&netlink.Route{
19
-		Scope:     netlink.SCOPE_UNIVERSE,
20
-		LinkIndex: i.Link.Attrs().Index,
21
-		Dst:       config.FixedCIDRv6,
22
-	})
23
-	if err != nil && !os.IsExist(err) {
24
-		log.Errorf("Could not add route to IPv6 network %s via device %s", config.FixedCIDRv6.String(), config.BridgeName)
25
-	}
26
-	return nil
27
-}
... ...
@@ -3,129 +3,43 @@ package bridge
3 3
 import (
4 4
 	"fmt"
5 5
 	"io/ioutil"
6
-	"net"
7 6
 	"path/filepath"
8 7
 
9 8
 	log "github.com/Sirupsen/logrus"
10
-	"github.com/docker/libnetwork/netutils"
9
+	"github.com/docker/libnetwork/types"
11 10
 	"github.com/vishvananda/netlink"
12 11
 )
13 12
 
14
-var bridgeNetworks []*net.IPNet
15
-
16
-func init() {
17
-	// Here we don't follow the convention of using the 1st IP of the range for the gateway.
18
-	// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
19
-	// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
20
-	// on the internal addressing or other stupid things like that.
21
-	// They shouldn't, but hey, let's not break them unless we really have to.
22
-	// Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
23
-
24
-	// 172.[17-31].42.1/16
25
-	mask := []byte{255, 255, 0, 0}
26
-	for i := 17; i < 32; i++ {
27
-		bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{172, byte(i), 42, 1}, Mask: mask})
28
-	}
29
-	// 10.[0-255].42.1/16
30
-	for i := 0; i < 256; i++ {
31
-		bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{10, byte(i), 42, 1}, Mask: mask})
32
-	}
33
-	// 192.168.[42-44].1/24
34
-	mask24 := []byte{255, 255, 255, 0}
35
-	for i := 42; i < 45; i++ {
36
-		bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{192, 168, byte(i), 1}, Mask: mask24})
37
-	}
38
-}
39
-
40 13
 func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
41 14
 	addrv4, _, err := i.addresses()
42 15
 	if err != nil {
43
-		return err
44
-	}
45
-
46
-	// Check if we have an IP address already on the bridge.
47
-	if addrv4.IPNet != nil {
48
-		// Make sure to store bridge network and default gateway before getting out.
49
-		i.bridgeIPv4 = addrv4.IPNet
50
-		i.gatewayIPv4 = addrv4.IPNet.IP
51
-		return nil
52
-	}
53
-
54
-	// Do not try to configure IPv4 on a non-default bridge unless you are
55
-	// specifically asked to do so.
56
-	if config.BridgeName != DefaultBridgeName && config.DefaultBridge {
57
-		return NonDefaultBridgeNeedsIPError(config.BridgeName)
58
-	}
59
-
60
-	bridgeIPv4, err := electBridgeIPv4(config)
61
-	if err != nil {
62
-		return err
16
+		return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
63 17
 	}
64 18
 
65
-	log.Debugf("Creating bridge interface %s with network %s", config.BridgeName, bridgeIPv4)
66
-	if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: bridgeIPv4}); err != nil {
67
-		return &IPv4AddrAddError{IP: bridgeIPv4, Err: err}
19
+	if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
20
+		if addrv4.IPNet != nil {
21
+			if err := netlink.AddrDel(i.Link, &addrv4); err != nil {
22
+				return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
23
+			}
24
+		}
25
+		log.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
26
+		if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
27
+			return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
28
+		}
68 29
 	}
69 30
 
70 31
 	// Store bridge network and default gateway
71
-	i.bridgeIPv4 = bridgeIPv4
72
-	i.gatewayIPv4 = i.bridgeIPv4.IP
32
+	i.bridgeIPv4 = config.AddressIPv4
33
+	i.gatewayIPv4 = config.AddressIPv4.IP
73 34
 
74 35
 	return nil
75 36
 }
76 37
 
77
-func allocateBridgeIP(config *networkConfiguration, i *bridgeInterface) error {
78
-	// Because of the way ipallocator manages the container address space,
79
-	// reserve bridge address only if it belongs to the container network
80
-	// (if defined), no need otherwise
81
-	if config.FixedCIDR == nil || config.FixedCIDR.Contains(i.bridgeIPv4.IP) {
82
-		if _, err := ipAllocator.RequestIP(i.bridgeIPv4, i.bridgeIPv4.IP); err != nil {
83
-			return fmt.Errorf("failed to reserve bridge IP %s: %v", i.bridgeIPv4.IP.String(), err)
84
-		}
85
-	}
86
-	return nil
87
-}
88
-
89
-func electBridgeIPv4(config *networkConfiguration) (*net.IPNet, error) {
90
-	// Use the requested IPv4 CIDR when available.
91
-	if config.AddressIPv4 != nil {
92
-		return config.AddressIPv4, nil
93
-	}
94
-
95
-	// We don't check for an error here, because we don't really care if we
96
-	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
97
-	// is nil. It either doesn't exist, or we can't read it for some reason.
98
-	nameservers := []string{}
99
-	if resolvConf, _ := readResolvConf(); resolvConf != nil {
100
-		nameservers = append(nameservers, getNameserversAsCIDR(resolvConf)...)
101
-	}
102
-
103
-	// Try to automatically elect appropriate bridge IPv4 settings.
104
-	for _, n := range bridgeNetworks {
105
-		if err := netutils.CheckNameserverOverlaps(nameservers, n); err == nil {
106
-			if err := netutils.CheckRouteOverlaps(n); err == nil {
107
-				return n, nil
108
-			}
109
-		}
110
-	}
111
-
112
-	return nil, IPv4AddrRangeError(config.BridgeName)
113
-}
114
-
115 38
 func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
116 39
 	if !i.bridgeIPv4.Contains(config.DefaultGatewayIPv4) {
117 40
 		return &ErrInvalidGateway{}
118 41
 	}
119 42
 
120
-	// Because of the way ipallocator manages the container address space,
121
-	// reserve default gw address only if it belongs to the container network
122
-	// (if defined), no need otherwise
123
-	if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) {
124
-		if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil {
125
-			return fmt.Errorf("failed to reserve default gateway %s: %v", config.DefaultGatewayIPv4.String(), err)
126
-		}
127
-	}
128
-
129 43
 	// Store requested default gateway
130 44
 	i.gatewayIPv4 = config.DefaultGatewayIPv4
131 45
 
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"io/ioutil"
6 6
 	"net"
7
+	"os"
7 8
 
8 9
 	"github.com/Sirupsen/logrus"
9 10
 	"github.com/vishvananda/netlink"
... ...
@@ -57,19 +58,31 @@ func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
57 57
 	i.bridgeIPv6 = bridgeIPv6
58 58
 	i.gatewayIPv6 = i.bridgeIPv6.IP
59 59
 
60
+	if config.AddressIPv6 == nil {
61
+		return nil
62
+	}
63
+
64
+	// Setting route to global IPv6 subnet
65
+	logrus.Debugf("Adding route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
66
+	err = netlink.RouteAdd(&netlink.Route{
67
+		Scope:     netlink.SCOPE_UNIVERSE,
68
+		LinkIndex: i.Link.Attrs().Index,
69
+		Dst:       config.AddressIPv6,
70
+	})
71
+	if err != nil && !os.IsExist(err) {
72
+		logrus.Errorf("Could not add route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
73
+	}
74
+
60 75
 	return nil
61 76
 }
62 77
 
63 78
 func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
64
-	if config.FixedCIDRv6 == nil {
79
+	if config.AddressIPv6 == nil {
65 80
 		return &ErrInvalidContainerSubnet{}
66 81
 	}
67
-	if !config.FixedCIDRv6.Contains(config.DefaultGatewayIPv6) {
82
+	if !config.AddressIPv6.Contains(config.DefaultGatewayIPv6) {
68 83
 		return &ErrInvalidGateway{}
69 84
 	}
70
-	if _, err := ipAllocator.RequestIP(config.FixedCIDRv6, config.DefaultGatewayIPv6); err != nil {
71
-		return err
72
-	}
73 85
 
74 86
 	// Store requested default gateway
75 87
 	i.gatewayIPv6 = config.DefaultGatewayIPv6
... ...
@@ -23,7 +23,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
23 23
 	return dc.RegisterDriver(networkType, &driver{}, c)
24 24
 }
25 25
 
26
-func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
26
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
27 27
 	d.Lock()
28 28
 	defer d.Unlock()
29 29
 
... ...
@@ -40,7 +40,7 @@ func (d *driver) DeleteNetwork(nid string) error {
40 40
 	return types.ForbiddenErrorf("network of type \"%s\" cannot be deleted", networkType)
41 41
 }
42 42
 
43
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
43
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
44 44
 	return nil
45 45
 }
46 46
 
... ...
@@ -23,7 +23,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
23 23
 	return dc.RegisterDriver(networkType, &driver{}, c)
24 24
 }
25 25
 
26
-func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
26
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
27 27
 	d.Lock()
28 28
 	defer d.Unlock()
29 29
 
... ...
@@ -40,7 +40,7 @@ func (d *driver) DeleteNetwork(nid string) error {
40 40
 	return types.ForbiddenErrorf("network of type \"%s\" cannot be deleted", networkType)
41 41
 }
42 42
 
43
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
43
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
44 44
 	return nil
45 45
 }
46 46
 
... ...
@@ -4,7 +4,9 @@ import (
4 4
 	"fmt"
5 5
 	"net"
6 6
 
7
+	log "github.com/Sirupsen/logrus"
7 8
 	"github.com/docker/libnetwork/driverapi"
9
+	"github.com/docker/libnetwork/types"
8 10
 	"github.com/vishvananda/netlink"
9 11
 )
10 12
 
... ...
@@ -24,11 +26,27 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
24 24
 		return fmt.Errorf("could not find endpoint with id %s", eid)
25 25
 	}
26 26
 
27
+	s := n.getSubnetforIP(ep.addr)
28
+	if s == nil {
29
+		return fmt.Errorf("could not find subnet for endpoint %s", eid)
30
+	}
31
+
32
+	if err := n.obtainVxlanID(s); err != nil {
33
+		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
34
+	}
35
+
27 36
 	if err := n.joinSandbox(); err != nil {
28
-		return fmt.Errorf("network sandbox join failed: %v",
29
-			err)
37
+		return fmt.Errorf("network sandbox join failed: %v", err)
38
+	}
39
+
40
+	if err := n.joinSubnetSandbox(s); err != nil {
41
+		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
30 42
 	}
31 43
 
44
+	// joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the
45
+	// overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox
46
+	n.incEndpointCount()
47
+
32 48
 	sbox := n.sandbox()
33 49
 
34 50
 	name1, name2, err := createVethPair()
... ...
@@ -49,7 +67,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
49 49
 	}
50 50
 
51 51
 	if err := sbox.AddInterface(name1, "veth",
52
-		sbox.InterfaceOptions().Master("bridge1")); err != nil {
52
+		sbox.InterfaceOptions().Master(s.brName)); err != nil {
53 53
 		return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err)
54 54
 	}
55 55
 
... ...
@@ -63,7 +81,16 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
63 63
 	}
64 64
 
65 65
 	if err := netlink.LinkSetHardwareAddr(veth, ep.mac); err != nil {
66
-		return fmt.Errorf("could not set mac address to the container interface: %v", err)
66
+		return fmt.Errorf("could not set mac address (%v) to the container interface: %v", ep.mac, err)
67
+	}
68
+
69
+	for _, sub := range n.subnets {
70
+		if sub == s {
71
+			continue
72
+		}
73
+		if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
74
+			log.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
75
+		}
67 76
 	}
68 77
 
69 78
 	if iNames := jinfo.InterfaceName(); iNames != nil {
... ...
@@ -73,7 +100,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
73 73
 		}
74 74
 	}
75 75
 
76
-	d.peerDbAdd(nid, eid, ep.addr.IP, ep.mac,
76
+	d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
77 77
 		net.ParseIP(d.bindAddress), true)
78 78
 	d.pushLocalEndpointEvent("join", nid, eid)
79 79
 
... ...
@@ -1,7 +1,6 @@
1 1
 package overlay
2 2
 
3 3
 import (
4
-	"encoding/binary"
5 4
 	"fmt"
6 5
 	"net"
7 6
 
... ...
@@ -36,9 +35,18 @@ func (n *network) deleteEndpoint(eid string) {
36 36
 	n.Unlock()
37 37
 }
38 38
 
39
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo,
39
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
40 40
 	epOptions map[string]interface{}) error {
41
-	if err := validateID(nid, eid); err != nil {
41
+	var err error
42
+
43
+	if err = validateID(nid, eid); err != nil {
44
+		return err
45
+	}
46
+
47
+	// Since we perform lazy configuration make sure we try
48
+	// configuring the driver when we enter CreateEndpoint since
49
+	// CreateNetwork may not be called in every node.
50
+	if err := d.configure(); err != nil {
42 51
 		return err
43 52
 	}
44 53
 
... ...
@@ -48,35 +56,23 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo,
48 48
 	}
49 49
 
50 50
 	ep := &endpoint{
51
-		id: eid,
51
+		id:   eid,
52
+		addr: ifInfo.Address(),
53
+		mac:  ifInfo.MacAddress(),
52 54
 	}
53
-
54
-	if epInfo != nil && epInfo.Interface() != nil {
55
-		addr := epInfo.Interface().Address()
56
-		ep.addr = &addr
57
-		ep.mac = epInfo.Interface().MacAddress()
58
-		n.addEndpoint(ep)
59
-		return nil
60
-	}
61
-
62
-	ipID, err := d.ipAllocator.GetID()
63
-	if err != nil {
64
-		return fmt.Errorf("could not allocate ip from subnet %s: %v",
65
-			bridgeSubnet.String(), err)
55
+	if ep.addr == nil {
56
+		return fmt.Errorf("create endpoint was not passed interface IP address")
66 57
 	}
67 58
 
68
-	ep.addr = &net.IPNet{
69
-		Mask: bridgeSubnet.Mask,
59
+	if s := n.getSubnetforIP(ep.addr); s == nil {
60
+		return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid)
70 61
 	}
71
-	ep.addr.IP = make([]byte, 4)
72
-
73
-	binary.BigEndian.PutUint32(ep.addr.IP, bridgeSubnetInt+ipID)
74
-
75
-	ep.mac = netutils.GenerateMACFromIP(ep.addr.IP)
76 62
 
77
-	err = epInfo.AddInterface(ep.mac, *ep.addr, net.IPNet{})
78
-	if err != nil {
79
-		return fmt.Errorf("could not add interface to endpoint info: %v", err)
63
+	if ep.mac == nil {
64
+		ep.mac = netutils.GenerateMACFromIP(ep.addr.IP)
65
+		if err := ifInfo.SetMacAddress(ep.mac); err != nil {
66
+			return err
67
+		}
80 68
 	}
81 69
 
82 70
 	n.addEndpoint(ep)
... ...
@@ -99,7 +95,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
99 99
 		return fmt.Errorf("endpoint id %q not found", eid)
100 100
 	}
101 101
 
102
-	d.ipAllocator.Release(binary.BigEndian.Uint32(ep.addr.IP) - bridgeSubnetInt)
103 102
 	n.deleteEndpoint(eid)
104 103
 	return nil
105 104
 }
... ...
@@ -9,37 +9,54 @@ import (
9 9
 
10 10
 	"github.com/Sirupsen/logrus"
11 11
 	"github.com/docker/libnetwork/datastore"
12
-	"github.com/docker/libnetwork/ipallocator"
12
+	"github.com/docker/libnetwork/driverapi"
13
+	"github.com/docker/libnetwork/netutils"
13 14
 	"github.com/docker/libnetwork/osl"
15
+	"github.com/docker/libnetwork/types"
14 16
 	"github.com/vishvananda/netlink"
15 17
 	"github.com/vishvananda/netlink/nl"
16 18
 )
17 19
 
18 20
 type networkTable map[string]*network
19 21
 
22
+type subnet struct {
23
+	once      *sync.Once
24
+	vxlanName string
25
+	brName    string
26
+	vni       uint32
27
+	initErr   error
28
+	subnetIP  *net.IPNet
29
+	gwIP      *net.IPNet
30
+}
31
+
32
+type subnetJSON struct {
33
+	SubnetIP string
34
+	GwIP     string
35
+	Vni      uint32
36
+}
37
+
20 38
 type network struct {
21
-	id          string
22
-	vni         uint32
23
-	dbIndex     uint64
24
-	dbExists    bool
25
-	sbox        osl.Sandbox
26
-	endpoints   endpointTable
27
-	ipAllocator *ipallocator.IPAllocator
28
-	gw          net.IP
29
-	vxlanName   string
30
-	driver      *driver
31
-	joinCnt     int
32
-	once        *sync.Once
33
-	initEpoch   int
34
-	initErr     error
39
+	id        string
40
+	dbIndex   uint64
41
+	dbExists  bool
42
+	sbox      osl.Sandbox
43
+	endpoints endpointTable
44
+	driver    *driver
45
+	joinCnt   int
46
+	once      *sync.Once
47
+	initEpoch int
48
+	initErr   error
49
+	subnets   []*subnet
35 50
 	sync.Mutex
36 51
 }
37 52
 
38
-func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
53
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
39 54
 	if id == "" {
40 55
 		return fmt.Errorf("invalid network id")
41 56
 	}
42 57
 
58
+	// Since we perform lazy configuration make sure we try
59
+	// configuring the driver when we enter CreateNetwork
43 60
 	if err := d.configure(); err != nil {
44 61
 		return err
45 62
 	}
... ...
@@ -49,19 +66,43 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
49 49
 		driver:    d,
50 50
 		endpoints: endpointTable{},
51 51
 		once:      &sync.Once{},
52
+		subnets:   []*subnet{},
52 53
 	}
53 54
 
54
-	n.gw = bridgeIP.IP
55
-
56
-	d.addNetwork(n)
55
+	for _, ipd := range ipV4Data {
56
+		s := &subnet{
57
+			subnetIP: ipd.Pool,
58
+			gwIP:     ipd.Gateway,
59
+			once:     &sync.Once{},
60
+		}
61
+		n.subnets = append(n.subnets, s)
62
+	}
57 63
 
58
-	if err := n.obtainVxlanID(); err != nil {
59
-		return err
64
+	if err := n.writeToStore(); err != nil {
65
+		return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
60 66
 	}
61 67
 
68
+	d.addNetwork(n)
69
+
62 70
 	return nil
63 71
 }
64 72
 
73
+/* func (d *driver) createNetworkfromStore(nid string) (*network, error) {
74
+	n := &network{
75
+		id:        nid,
76
+		driver:    d,
77
+		endpoints: endpointTable{},
78
+		once:      &sync.Once{},
79
+		subnets:   []*subnet{},
80
+	}
81
+
82
+	err := d.store.GetObject(datastore.Key(n.Key()...), n)
83
+	if err != nil {
84
+		return nil, fmt.Errorf("unable to get network %q from data store, %v", nid, err)
85
+	}
86
+	return n, nil
87
+}*/
88
+
65 89
 func (d *driver) DeleteNetwork(nid string) error {
66 90
 	if nid == "" {
67 91
 		return fmt.Errorf("invalid network id")
... ...
@@ -77,15 +118,13 @@ func (d *driver) DeleteNetwork(nid string) error {
77 77
 	return n.releaseVxlanID()
78 78
 }
79 79
 
80
-func (n *network) joinSandbox() error {
80
+func (n *network) incEndpointCount() {
81 81
 	n.Lock()
82
-	if n.joinCnt != 0 {
83
-		n.joinCnt++
84
-		n.Unlock()
85
-		return nil
86
-	}
87
-	n.Unlock()
82
+	defer n.Unlock()
83
+	n.joinCnt++
84
+}
88 85
 
86
+func (n *network) joinSandbox() error {
89 87
 	// If there is a race between two go routines here only one will win
90 88
 	// the other will wait.
91 89
 	n.once.Do(func() {
... ...
@@ -94,16 +133,14 @@ func (n *network) joinSandbox() error {
94 94
 		n.initErr = n.initSandbox()
95 95
 	})
96 96
 
97
-	// Increment joinCnt in all the goroutines only when the one time initSandbox
98
-	// was a success.
99
-	n.Lock()
100
-	if n.initErr == nil {
101
-		n.joinCnt++
102
-	}
103
-	err := n.initErr
104
-	n.Unlock()
97
+	return n.initErr
98
+}
105 99
 
106
-	return err
100
+func (n *network) joinSubnetSandbox(s *subnet) error {
101
+	s.once.Do(func() {
102
+		s.initErr = n.initSubnetSandbox(s)
103
+	})
104
+	return s.initErr
107 105
 }
108 106
 
109 107
 func (n *network) leaveSandbox() {
... ...
@@ -118,6 +155,9 @@ func (n *network) leaveSandbox() {
118 118
 	// Reinitialize the once variable so that we will be able to trigger one time
119 119
 	// sandbox initialization(again) when another container joins subsequently.
120 120
 	n.once = &sync.Once{}
121
+	for _, s := range n.subnets {
122
+		s.once = &sync.Once{}
123
+	}
121 124
 	n.Unlock()
122 125
 
123 126
 	n.destroySandbox()
... ...
@@ -130,14 +170,50 @@ func (n *network) destroySandbox() {
130 130
 			iface.Remove()
131 131
 		}
132 132
 
133
-		if err := deleteVxlan(n.vxlanName); err != nil {
134
-			logrus.Warnf("could not cleanup sandbox properly: %v", err)
133
+		for _, s := range n.subnets {
134
+			if s.vxlanName != "" {
135
+				err := deleteVxlan(s.vxlanName)
136
+				if err != nil {
137
+					logrus.Warnf("could not cleanup sandbox properly: %v", err)
138
+				}
139
+			}
135 140
 		}
136
-
137 141
 		sbox.Destroy()
138 142
 	}
139 143
 }
140 144
 
145
+func (n *network) initSubnetSandbox(s *subnet) error {
146
+	// create a bridge and vxlan device for this subnet and move it to the sandbox
147
+	brName, err := netutils.GenerateIfaceName("bridge", 7)
148
+	if err != nil {
149
+		return err
150
+	}
151
+	sbox := n.sandbox()
152
+
153
+	if err := sbox.AddInterface(brName, "br",
154
+		sbox.InterfaceOptions().Address(s.gwIP),
155
+		sbox.InterfaceOptions().Bridge(true)); err != nil {
156
+		return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.IP.String(), err)
157
+	}
158
+
159
+	vxlanName, err := createVxlan(n.vxlanID(s))
160
+	if err != nil {
161
+		return err
162
+	}
163
+
164
+	if err := sbox.AddInterface(vxlanName, "vxlan",
165
+		sbox.InterfaceOptions().Master(brName)); err != nil {
166
+		return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.IP.String(), err)
167
+	}
168
+
169
+	n.Lock()
170
+	s.vxlanName = vxlanName
171
+	s.brName = brName
172
+	n.Unlock()
173
+
174
+	return nil
175
+}
176
+
141 177
 func (n *network) initSandbox() error {
142 178
 	n.Lock()
143 179
 	n.initEpoch++
... ...
@@ -149,15 +225,10 @@ func (n *network) initSandbox() error {
149 149
 		return fmt.Errorf("could not create network sandbox: %v", err)
150 150
 	}
151 151
 
152
-	// Add a bridge inside the namespace
153
-	if err := sbox.AddInterface("bridge1", "br",
154
-		sbox.InterfaceOptions().Address(bridgeIP),
155
-		sbox.InterfaceOptions().Bridge(true)); err != nil {
156
-		return fmt.Errorf("could not create bridge inside the network sandbox: %v", err)
157
-	}
158
-
159 152
 	n.setSandbox(sbox)
160 153
 
154
+	n.driver.peerDbUpdateSandbox(n.id)
155
+
161 156
 	var nlSock *nl.NetlinkSocket
162 157
 	sbox.InvokeFunc(func() {
163 158
 		nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
... ...
@@ -167,27 +238,6 @@ func (n *network) initSandbox() error {
167 167
 	})
168 168
 
169 169
 	go n.watchMiss(nlSock)
170
-	return n.initVxlan()
171
-}
172
-
173
-func (n *network) initVxlan() error {
174
-	var vxlanName string
175
-	n.Lock()
176
-	sbox := n.sbox
177
-	n.Unlock()
178
-
179
-	vxlanName, err := createVxlan(n.vxlanID())
180
-	if err != nil {
181
-		return err
182
-	}
183
-
184
-	if err = sbox.AddInterface(vxlanName, "vxlan",
185
-		sbox.InterfaceOptions().Master("bridge1")); err != nil {
186
-		return fmt.Errorf("could not add vxlan interface inside the network sandbox: %v", err)
187
-	}
188
-
189
-	n.vxlanName = vxlanName
190
-	n.driver.peerDbUpdateSandbox(n.id)
191 170
 	return nil
192 171
 }
193 172
 
... ...
@@ -218,14 +268,14 @@ func (n *network) watchMiss(nlSock *nl.NetlinkSocket) {
218 218
 				continue
219 219
 			}
220 220
 
221
-			mac, vtep, err := n.driver.resolvePeer(n.id, neigh.IP)
221
+			mac, IPmask, vtep, err := n.driver.resolvePeer(n.id, neigh.IP)
222 222
 			if err != nil {
223 223
 				logrus.Errorf("could not resolve peer %q: %v", neigh.IP, err)
224 224
 				continue
225 225
 			}
226 226
 
227
-			if err := n.driver.peerAdd(n.id, "dummy", neigh.IP, mac, vtep, true); err != nil {
228
-				logrus.Errorf("could not add neighbor entry for missed peer: %v", err)
227
+			if err := n.driver.peerAdd(n.id, "dummy", neigh.IP, IPmask, mac, vtep, true); err != nil {
228
+				logrus.Errorf("could not add neighbor entry for missed peer %q: %v", neigh.IP, err)
229 229
 			}
230 230
 		}
231 231
 	}
... ...
@@ -245,9 +295,34 @@ func (d *driver) deleteNetwork(nid string) {
245 245
 
246 246
 func (d *driver) network(nid string) *network {
247 247
 	d.Lock()
248
-	defer d.Unlock()
248
+	networks := d.networks
249
+	d.Unlock()
250
+
251
+	n, ok := networks[nid]
252
+	if !ok {
253
+		n = d.getNetworkFromStore(nid)
254
+		if n != nil {
255
+			n.driver = d
256
+			n.endpoints = endpointTable{}
257
+			n.once = &sync.Once{}
258
+			networks[nid] = n
259
+		}
260
+	}
261
+
262
+	return n
263
+}
264
+
265
+func (d *driver) getNetworkFromStore(nid string) *network {
266
+	if d.store == nil {
267
+		return nil
268
+	}
249 269
 
250
-	return d.networks[nid]
270
+	n := &network{id: nid}
271
+	if err := d.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
272
+		return nil
273
+	}
274
+
275
+	return n
251 276
 }
252 277
 
253 278
 func (n *network) sandbox() osl.Sandbox {
... ...
@@ -263,16 +338,16 @@ func (n *network) setSandbox(sbox osl.Sandbox) {
263 263
 	n.Unlock()
264 264
 }
265 265
 
266
-func (n *network) vxlanID() uint32 {
266
+func (n *network) vxlanID(s *subnet) uint32 {
267 267
 	n.Lock()
268 268
 	defer n.Unlock()
269 269
 
270
-	return n.vni
270
+	return s.vni
271 271
 }
272 272
 
273
-func (n *network) setVxlanID(vni uint32) {
273
+func (n *network) setVxlanID(s *subnet, vni uint32) {
274 274
 	n.Lock()
275
-	n.vni = vni
275
+	s.vni = vni
276 276
 	n.Unlock()
277 277
 }
278 278
 
... ...
@@ -285,11 +360,22 @@ func (n *network) KeyPrefix() []string {
285 285
 }
286 286
 
287 287
 func (n *network) Value() []byte {
288
-	b, err := json.Marshal(n.vxlanID())
288
+	netJSON := []*subnetJSON{}
289
+
290
+	for _, s := range n.subnets {
291
+		sj := &subnetJSON{
292
+			SubnetIP: s.subnetIP.String(),
293
+			GwIP:     s.gwIP.String(),
294
+			Vni:      s.vni,
295
+		}
296
+		netJSON = append(netJSON, sj)
297
+	}
298
+
299
+	b, err := json.Marshal(netJSON)
300
+
289 301
 	if err != nil {
290 302
 		return []byte{}
291 303
 	}
292
-
293 304
 	return b
294 305
 }
295 306
 
... ...
@@ -311,15 +397,45 @@ func (n *network) Skip() bool {
311 311
 }
312 312
 
313 313
 func (n *network) SetValue(value []byte) error {
314
-	var vni uint32
315
-	err := json.Unmarshal(value, &vni)
316
-	if err == nil {
317
-		n.setVxlanID(vni)
314
+	var newNet bool
315
+	netJSON := []*subnetJSON{}
316
+
317
+	err := json.Unmarshal(value, &netJSON)
318
+	if err != nil {
319
+		return err
318 320
 	}
319
-	return err
321
+
322
+	if len(n.subnets) == 0 {
323
+		newNet = true
324
+	}
325
+
326
+	for _, sj := range netJSON {
327
+		subnetIPstr := sj.SubnetIP
328
+		gwIPstr := sj.GwIP
329
+		vni := sj.Vni
330
+
331
+		subnetIP, _ := types.ParseCIDR(subnetIPstr)
332
+		gwIP, _ := types.ParseCIDR(gwIPstr)
333
+
334
+		if newNet {
335
+			s := &subnet{
336
+				subnetIP: subnetIP,
337
+				gwIP:     gwIP,
338
+				vni:      vni,
339
+				once:     &sync.Once{},
340
+			}
341
+			n.subnets = append(n.subnets, s)
342
+		} else {
343
+			sNet := n.getMatchingSubnet(subnetIP)
344
+			if sNet != nil {
345
+				sNet.vni = vni
346
+			}
347
+		}
348
+	}
349
+	return nil
320 350
 }
321 351
 
322
-func (n *network) DataScope() datastore.DataScope {
352
+func (n *network) DataScope() string {
323 353
 	return datastore.GlobalScope
324 354
 }
325 355
 
... ...
@@ -332,7 +448,7 @@ func (n *network) releaseVxlanID() error {
332 332
 		return fmt.Errorf("no datastore configured. cannot release vxlan id")
333 333
 	}
334 334
 
335
-	if n.vxlanID() == 0 {
335
+	if len(n.subnets) == 0 {
336 336
 		return nil
337 337
 	}
338 338
 
... ...
@@ -346,38 +462,80 @@ func (n *network) releaseVxlanID() error {
346 346
 		return fmt.Errorf("failed to delete network to vxlan id map: %v", err)
347 347
 	}
348 348
 
349
-	n.driver.vxlanIdm.Release(n.vxlanID())
350
-	n.setVxlanID(0)
349
+	for _, s := range n.subnets {
350
+		n.driver.vxlanIdm.Release(uint64(n.vxlanID(s)))
351
+		n.setVxlanID(s, 0)
352
+	}
351 353
 	return nil
352 354
 }
353 355
 
354
-func (n *network) obtainVxlanID() error {
356
+func (n *network) obtainVxlanID(s *subnet) error {
357
+	//return if the subnet already has a vxlan id assigned
358
+	if s.vni != 0 {
359
+		return nil
360
+	}
361
+
355 362
 	if n.driver.store == nil {
356 363
 		return fmt.Errorf("no datastore configured. cannot obtain vxlan id")
357 364
 	}
358 365
 
359 366
 	for {
360
-		var vxlanID uint32
361 367
 		if err := n.driver.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
362
-			if err == datastore.ErrKeyNotFound {
363
-				vxlanID, err = n.driver.vxlanIdm.GetID()
364
-				if err != nil {
365
-					return fmt.Errorf("failed to allocate vxlan id: %v", err)
366
-				}
368
+			return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
369
+		}
367 370
 
368
-				n.setVxlanID(vxlanID)
369
-				if err := n.writeToStore(); err != nil {
370
-					n.driver.vxlanIdm.Release(n.vxlanID())
371
-					n.setVxlanID(0)
372
-					if err == datastore.ErrKeyModified {
373
-						continue
374
-					}
375
-					return fmt.Errorf("failed to update data store with vxlan id: %v", err)
371
+		if s.vni == 0 {
372
+			vxlanID, err := n.driver.vxlanIdm.GetID()
373
+			if err != nil {
374
+				return fmt.Errorf("failed to allocate vxlan id: %v", err)
375
+			}
376
+
377
+			n.setVxlanID(s, uint32(vxlanID))
378
+			if err := n.writeToStore(); err != nil {
379
+				n.driver.vxlanIdm.Release(uint64(n.vxlanID(s)))
380
+				n.setVxlanID(s, 0)
381
+				if err == datastore.ErrKeyModified {
382
+					continue
376 383
 				}
377
-				return nil
384
+				return fmt.Errorf("network %q failed to update data store: %v", n.id, err)
378 385
 			}
379
-			return fmt.Errorf("failed to obtain vxlan id from data store: %v", err)
386
+			return nil
380 387
 		}
381 388
 		return nil
382 389
 	}
383 390
 }
391
+
392
+// getSubnetforIP returns the subnet to which the given IP belongs
393
+func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
394
+	for _, s := range n.subnets {
395
+		// first check if the mask lengths are the same
396
+		i, _ := s.subnetIP.Mask.Size()
397
+		j, _ := ip.Mask.Size()
398
+		if i != j {
399
+			continue
400
+		}
401
+		if s.subnetIP.Contains(ip.IP) {
402
+			return s
403
+		}
404
+	}
405
+	return nil
406
+}
407
+
408
+// getMatchingSubnet return the network's subnet that matches the input
409
+func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
410
+	if ip == nil {
411
+		return nil
412
+	}
413
+	for _, s := range n.subnets {
414
+		// first check if the mask lengths are the same
415
+		i, _ := s.subnetIP.Mask.Size()
416
+		j, _ := ip.Mask.Size()
417
+		if i != j {
418
+			continue
419
+		}
420
+		if s.subnetIP.IP.Equal(ip.IP) {
421
+			return s
422
+		}
423
+	}
424
+	return nil
425
+}
... ...
@@ -47,7 +47,7 @@ func (d *driver) serfInit() error {
47 47
 	config.UserCoalescePeriod = 1 * time.Second
48 48
 	config.UserQuiescentPeriod = 50 * time.Millisecond
49 49
 
50
-	config.LogOutput = logrus.StandardLogger().Out
50
+	config.LogOutput = &logWriter{}
51 51
 
52 52
 	s, err := serf.Create(config)
53 53
 	if err != nil {
... ...
@@ -83,34 +83,35 @@ func (d *driver) notifyEvent(event ovNotify) {
83 83
 	n := d.network(event.nid)
84 84
 	ep := n.endpoint(event.eid)
85 85
 
86
-	ePayload := fmt.Sprintf("%s %s %s", event.action, ep.addr.IP.String(), ep.mac.String())
86
+	ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
87
+		net.IP(ep.addr.Mask).String(), ep.mac.String())
87 88
 	eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
88 89
 		event.nid, event.eid)
89 90
 
90 91
 	if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
91
-		fmt.Printf("Sending user event failed: %v\n", err)
92
+		logrus.Errorf("Sending user event failed: %v\n", err)
92 93
 	}
93 94
 }
94 95
 
95 96
 func (d *driver) processEvent(u serf.UserEvent) {
96
-	fmt.Printf("Received user event name:%s, payload:%s\n", u.Name,
97
+	logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
97 98
 		string(u.Payload))
98 99
 
99
-	var dummy, action, vtepStr, nid, eid, ipStr, macStr string
100
+	var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string
100 101
 	if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
101 102
 		fmt.Printf("Failed to scan name string: %v\n", err)
102 103
 	}
103 104
 
104 105
 	if _, err := fmt.Sscan(string(u.Payload), &action,
105
-		&ipStr, &macStr); err != nil {
106
+		&ipStr, &maskStr, &macStr); err != nil {
106 107
 		fmt.Printf("Failed to scan value string: %v\n", err)
107 108
 	}
108 109
 
109
-	fmt.Printf("Parsed data = %s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, macStr)
110
+	logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
110 111
 
111 112
 	mac, err := net.ParseMAC(macStr)
112 113
 	if err != nil {
113
-		fmt.Printf("Failed to parse mac: %v\n", err)
114
+		logrus.Errorf("Failed to parse mac: %v\n", err)
114 115
 	}
115 116
 
116 117
 	if d.serfInstance.LocalMember().Addr.String() == vtepStr {
... ...
@@ -119,20 +120,20 @@ func (d *driver) processEvent(u serf.UserEvent) {
119 119
 
120 120
 	switch action {
121 121
 	case "join":
122
-		if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), mac,
122
+		if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac,
123 123
 			net.ParseIP(vtepStr), true); err != nil {
124
-			fmt.Printf("Peer add failed in the driver: %v\n", err)
124
+			logrus.Errorf("Peer add failed in the driver: %v\n", err)
125 125
 		}
126 126
 	case "leave":
127
-		if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), mac,
127
+		if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac,
128 128
 			net.ParseIP(vtepStr), true); err != nil {
129
-			fmt.Printf("Peer delete failed in the driver: %v\n", err)
129
+			logrus.Errorf("Peer delete failed in the driver: %v\n", err)
130 130
 		}
131 131
 	}
132 132
 }
133 133
 
134 134
 func (d *driver) processQuery(q *serf.Query) {
135
-	fmt.Printf("Received query name:%s, payload:%s\n", q.Name,
135
+	logrus.Debugf("Received query name:%s, payload:%s\n", q.Name,
136 136
 		string(q.Payload))
137 137
 
138 138
 	var nid, ipStr string
... ...
@@ -140,38 +141,38 @@ func (d *driver) processQuery(q *serf.Query) {
140 140
 		fmt.Printf("Failed to scan query payload string: %v\n", err)
141 141
 	}
142 142
 
143
-	peerMac, vtep, err := d.peerDbSearch(nid, net.ParseIP(ipStr))
143
+	peerMac, peerIPMask, vtep, err := d.peerDbSearch(nid, net.ParseIP(ipStr))
144 144
 	if err != nil {
145 145
 		return
146 146
 	}
147 147
 
148
-	q.Respond([]byte(fmt.Sprintf("%s %s", peerMac.String(), vtep.String())))
148
+	q.Respond([]byte(fmt.Sprintf("%s %s %s", peerMac.String(), net.IP(peerIPMask).String(), vtep.String())))
149 149
 }
150 150
 
151
-func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IP, error) {
151
+func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
152 152
 	qPayload := fmt.Sprintf("%s %s", string(nid), peerIP.String())
153 153
 	resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil)
154 154
 	if err != nil {
155
-		return nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
155
+		return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
156 156
 	}
157 157
 
158 158
 	respCh := resp.ResponseCh()
159 159
 	select {
160 160
 	case r := <-respCh:
161
-		var macStr, vtepStr string
162
-		if _, err := fmt.Sscan(string(r.Payload), &macStr, &vtepStr); err != nil {
163
-			return nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
161
+		var macStr, maskStr, vtepStr string
162
+		if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil {
163
+			return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
164 164
 		}
165 165
 
166 166
 		mac, err := net.ParseMAC(macStr)
167 167
 		if err != nil {
168
-			return nil, nil, fmt.Errorf("failed to parse mac: %v", err)
168
+			return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
169 169
 		}
170 170
 
171
-		return mac, net.ParseIP(vtepStr), nil
171
+		return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil
172 172
 
173 173
 	case <-time.After(time.Second):
174
-		return nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
174
+		return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
175 175
 	}
176 176
 }
177 177
 
... ...
@@ -192,7 +193,7 @@ func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify,
192 192
 			}
193 193
 
194 194
 			if err := d.serfInstance.Leave(); err != nil {
195
-				fmt.Printf("failed leaving the cluster: %v\n", err)
195
+				logrus.Errorf("failed leaving the cluster: %v\n", err)
196 196
 			}
197 197
 
198 198
 			d.serfInstance.Shutdown()
... ...
@@ -1,14 +1,11 @@
1 1
 package overlay
2 2
 
3 3
 import (
4
-	"encoding/binary"
5 4
 	"fmt"
6
-	"net"
7 5
 	"sync"
8 6
 
9 7
 	"github.com/Sirupsen/logrus"
10 8
 	"github.com/docker/libkv/store"
11
-	"github.com/docker/libnetwork/config"
12 9
 	"github.com/docker/libnetwork/datastore"
13 10
 	"github.com/docker/libnetwork/driverapi"
14 11
 	"github.com/docker/libnetwork/idm"
... ...
@@ -44,36 +41,8 @@ type driver struct {
44 44
 	sync.Mutex
45 45
 }
46 46
 
47
-var (
48
-	bridgeSubnet, bridgeIP *net.IPNet
49
-	once                   sync.Once
50
-	bridgeSubnetInt        uint32
51
-)
52
-
53
-func onceInit() {
54
-	var err error
55
-	_, bridgeSubnet, err = net.ParseCIDR("172.21.0.0/16")
56
-	if err != nil {
57
-		panic("could not parse cid 172.21.0.0/16")
58
-	}
59
-
60
-	bridgeSubnetInt = binary.BigEndian.Uint32(bridgeSubnet.IP.To4())
61
-
62
-	ip, subnet, err := net.ParseCIDR("172.21.255.254/16")
63
-	if err != nil {
64
-		panic("could not parse cid 172.21.255.254/16")
65
-	}
66
-
67
-	bridgeIP = &net.IPNet{
68
-		IP:   ip,
69
-		Mask: subnet.Mask,
70
-	}
71
-}
72
-
73 47
 // Init registers a new instance of overlay driver
74 48
 func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
75
-	once.Do(onceInit)
76
-
77 49
 	c := driverapi.Capability{
78 50
 		DataScope: datastore.GlobalScope,
79 51
 	}
... ...
@@ -110,21 +79,21 @@ func (d *driver) configure() error {
110 110
 	}
111 111
 
112 112
 	d.once.Do(func() {
113
-		provider, provOk := d.config[netlabel.KVProvider]
114
-		provURL, urlOk := d.config[netlabel.KVProviderURL]
113
+		provider, provOk := d.config[netlabel.GlobalKVProvider]
114
+		provURL, urlOk := d.config[netlabel.GlobalKVProviderURL]
115 115
 
116 116
 		if provOk && urlOk {
117
-			cfg := &config.DatastoreCfg{
118
-				Client: config.DatastoreClientCfg{
117
+			cfg := &datastore.ScopeCfg{
118
+				Client: datastore.ScopeClientCfg{
119 119
 					Provider: provider.(string),
120 120
 					Address:  provURL.(string),
121 121
 				},
122 122
 			}
123
-			provConfig, confOk := d.config[netlabel.KVProviderConfig]
123
+			provConfig, confOk := d.config[netlabel.GlobalKVProviderConfig]
124 124
 			if confOk {
125 125
 				cfg.Client.Config = provConfig.(*store.Config)
126 126
 			}
127
-			d.store, err = datastore.NewDataStore(cfg)
127
+			d.store, err = datastore.NewDataStore(datastore.GlobalScope, cfg)
128 128
 			if err != nil {
129 129
 				err = fmt.Errorf("failed to initialize data store: %v", err)
130 130
 				return
... ...
@@ -13,10 +13,11 @@ type peerKey struct {
13 13
 }
14 14
 
15 15
 type peerEntry struct {
16
-	eid       string
17
-	vtep      net.IP
18
-	inSandbox bool
19
-	isLocal   bool
16
+	eid        string
17
+	vtep       net.IP
18
+	peerIPMask net.IPMask
19
+	inSandbox  bool
20
+	isLocal    bool
20 21
 }
21 22
 
22 23
 type peerMap struct {
... ...
@@ -98,16 +99,18 @@ func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool
98 98
 	return nil
99 99
 }
100 100
 
101
-func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.IP, error) {
101
+func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
102 102
 	var (
103
-		peerMac net.HardwareAddr
104
-		vtep    net.IP
105
-		found   bool
103
+		peerMac    net.HardwareAddr
104
+		vtep       net.IP
105
+		peerIPMask net.IPMask
106
+		found      bool
106 107
 	)
107 108
 
108 109
 	err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
109 110
 		if pKey.peerIP.Equal(peerIP) {
110 111
 			peerMac = pKey.peerMac
112
+			peerIPMask = pEntry.peerIPMask
111 113
 			vtep = pEntry.vtep
112 114
 			found = true
113 115
 			return found
... ...
@@ -117,17 +120,17 @@ func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.
117 117
 	})
118 118
 
119 119
 	if err != nil {
120
-		return nil, nil, fmt.Errorf("peerdb search for peer ip %q failed: %v", peerIP, err)
120
+		return nil, nil, nil, fmt.Errorf("peerdb search for peer ip %q failed: %v", peerIP, err)
121 121
 	}
122 122
 
123 123
 	if !found {
124
-		return nil, nil, fmt.Errorf("peer ip %q not found in peerdb", peerIP)
124
+		return nil, nil, nil, fmt.Errorf("peer ip %q not found in peerdb", peerIP)
125 125
 	}
126 126
 
127
-	return peerMac, vtep, nil
127
+	return peerMac, peerIPMask, vtep, nil
128 128
 }
129 129
 
130
-func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP,
130
+func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
131 131
 	peerMac net.HardwareAddr, vtep net.IP, isLocal bool) {
132 132
 
133 133
 	peerDbWg.Wait()
... ...
@@ -149,9 +152,10 @@ func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP,
149 149
 	}
150 150
 
151 151
 	pEntry := peerEntry{
152
-		eid:     eid,
153
-		vtep:    vtep,
154
-		isLocal: isLocal,
152
+		eid:        eid,
153
+		vtep:       vtep,
154
+		peerIPMask: peerIPMask,
155
+		isLocal:    isLocal,
155 156
 	}
156 157
 
157 158
 	pMap.Lock()
... ...
@@ -159,7 +163,7 @@ func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP,
159 159
 	pMap.Unlock()
160 160
 }
161 161
 
162
-func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP,
162
+func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
163 163
 	peerMac net.HardwareAddr, vtep net.IP) {
164 164
 	peerDbWg.Wait()
165 165
 
... ...
@@ -209,7 +213,7 @@ func (d *driver) peerDbUpdateSandbox(nid string) {
209 209
 		// a copy of pEntry before capturing it in the following closure.
210 210
 		entry := pEntry
211 211
 		op := func() {
212
-			if err := d.peerAdd(nid, entry.eid, pKey.peerIP,
212
+			if err := d.peerAdd(nid, entry.eid, pKey.peerIP, entry.peerIPMask,
213 213
 				pKey.peerMac, entry.vtep,
214 214
 				false); err != nil {
215 215
 				fmt.Printf("peerdbupdate in sandbox failed for ip %s and mac %s: %v",
... ...
@@ -228,7 +232,7 @@ func (d *driver) peerDbUpdateSandbox(nid string) {
228 228
 	peerDbWg.Done()
229 229
 }
230 230
 
231
-func (d *driver) peerAdd(nid, eid string, peerIP net.IP,
231
+func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
232 232
 	peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
233 233
 
234 234
 	if err := validateID(nid, eid); err != nil {
... ...
@@ -236,7 +240,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP,
236 236
 	}
237 237
 
238 238
 	if updateDb {
239
-		d.peerDbAdd(nid, eid, peerIP, peerMac, vtep, false)
239
+		d.peerDbAdd(nid, eid, peerIP, peerIPMask, peerMac, vtep, false)
240 240
 	}
241 241
 
242 242
 	n := d.network(nid)
... ...
@@ -249,13 +253,31 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP,
249 249
 		return nil
250 250
 	}
251 251
 
252
+	IP := &net.IPNet{
253
+		IP:   peerIP,
254
+		Mask: peerIPMask,
255
+	}
256
+
257
+	s := n.getSubnetforIP(IP)
258
+	if s == nil {
259
+		return fmt.Errorf("couldn't find the subnet %q in network %q\n", IP.String(), n.id)
260
+	}
261
+
262
+	if err := n.obtainVxlanID(s); err != nil {
263
+		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
264
+	}
265
+
266
+	if err := n.joinSubnetSandbox(s); err != nil {
267
+		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
268
+	}
269
+
252 270
 	// Add neighbor entry for the peer IP
253
-	if err := sbox.AddNeighbor(peerIP, peerMac, sbox.NeighborOptions().LinkName(n.vxlanName)); err != nil {
271
+	if err := sbox.AddNeighbor(peerIP, peerMac, sbox.NeighborOptions().LinkName(s.vxlanName)); err != nil {
254 272
 		return fmt.Errorf("could not add neigbor entry into the sandbox: %v", err)
255 273
 	}
256 274
 
257 275
 	// Add fdb entry to the bridge for the peer mac
258
-	if err := sbox.AddNeighbor(vtep, peerMac, sbox.NeighborOptions().LinkName(n.vxlanName),
276
+	if err := sbox.AddNeighbor(vtep, peerMac, sbox.NeighborOptions().LinkName(s.vxlanName),
259 277
 		sbox.NeighborOptions().Family(syscall.AF_BRIDGE)); err != nil {
260 278
 		return fmt.Errorf("could not add fdb entry into the sandbox: %v", err)
261 279
 	}
... ...
@@ -263,7 +285,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP,
263 263
 	return nil
264 264
 }
265 265
 
266
-func (d *driver) peerDelete(nid, eid string, peerIP net.IP,
266
+func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
267 267
 	peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
268 268
 
269 269
 	if err := validateID(nid, eid); err != nil {
... ...
@@ -271,7 +293,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP,
271 271
 	}
272 272
 
273 273
 	if updateDb {
274
-		d.peerDbDelete(nid, eid, peerIP, peerMac, vtep)
274
+		d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep)
275 275
 	}
276 276
 
277 277
 	n := d.network(nid)
... ...
@@ -34,6 +34,9 @@ type CreateNetworkRequest struct {
34 34
 
35 35
 	// A free form map->object interface for communication of options.
36 36
 	Options map[string]interface{}
37
+
38
+	// IPAMData contains the address pool information for this network
39
+	IPv4Data, IPv6Data []driverapi.IPAMData
37 40
 }
38 41
 
39 42
 // CreateNetworkResponse is the response to the CreateNetworkRequest.
... ...
@@ -82,10 +82,12 @@ func (d *driver) call(methodName string, arg interface{}, retVal maybeError) err
82 82
 	return nil
83 83
 }
84 84
 
85
-func (d *driver) CreateNetwork(id string, options map[string]interface{}) error {
85
+func (d *driver) CreateNetwork(id string, options map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
86 86
 	create := &api.CreateNetworkRequest{
87 87
 		NetworkID: id,
88 88
 		Options:   options,
89
+		IPv4Data:  ipV4Data,
90
+		IPv6Data:  ipV6Data,
89 91
 	}
90 92
 	return d.call("CreateNetwork", create, &api.CreateNetworkResponse{})
91 93
 }
... ...
@@ -95,23 +97,22 @@ func (d *driver) DeleteNetwork(nid string) error {
95 95
 	return d.call("DeleteNetwork", delete, &api.DeleteNetworkResponse{})
96 96
 }
97 97
 
98
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
99
-	var reqIface *api.EndpointInterface
100
-
101
-	if epInfo == nil {
102
-		return fmt.Errorf("must not be called with nil EndpointInfo")
98
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
99
+	if ifInfo == nil {
100
+		return fmt.Errorf("must not be called with nil InterfaceInfo")
103 101
 	}
104 102
 
105
-	iface := epInfo.Interface()
106
-	if iface != nil {
107
-		addr4 := iface.Address()
108
-		addr6 := iface.AddressIPv6()
109
-		reqIface = &api.EndpointInterface{
110
-			Address:     addr4.String(),
111
-			AddressIPv6: addr6.String(),
112
-			MacAddress:  iface.MacAddress().String(),
113
-		}
103
+	reqIface := &api.EndpointInterface{}
104
+	if ifInfo.Address() != nil {
105
+		reqIface.Address = ifInfo.Address().String()
106
+	}
107
+	if ifInfo.AddressIPv6() != nil {
108
+		reqIface.AddressIPv6 = ifInfo.AddressIPv6().String()
109
+	}
110
+	if ifInfo.MacAddress() != nil {
111
+		reqIface.MacAddress = ifInfo.MacAddress().String()
114 112
 	}
113
+
115 114
 	create := &api.CreateEndpointRequest{
116 115
 		NetworkID:  nid,
117 116
 		EndpointID: eid,
... ...
@@ -127,24 +128,27 @@ func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo,
127 127
 	if err != nil {
128 128
 		return err
129 129
 	}
130
-	if reqIface != nil && inIface != nil {
131
-		// We're not supposed to add interface if there is already
132
-		// one. Attempt to roll back
133
-		return errorWithRollback("driver attempted to add interface ignoring the one provided", d.DeleteEndpoint(nid, eid))
130
+	if inIface == nil {
131
+		// Remote driver did not set any field
132
+		return nil
134 133
 	}
135 134
 
136
-	if inIface != nil {
137
-		var addr4, addr6 net.IPNet
138
-		if inIface.Address != nil {
139
-			addr4 = *(inIface.Address)
135
+	if inIface.MacAddress != nil {
136
+		if err := ifInfo.SetMacAddress(inIface.MacAddress); err != nil {
137
+			return errorWithRollback(fmt.Sprintf("driver modified interface MAC address: %v", err), d.DeleteEndpoint(nid, eid))
140 138
 		}
141
-		if inIface.AddressIPv6 != nil {
142
-			addr6 = *(inIface.AddressIPv6)
139
+	}
140
+	if inIface.Address != nil {
141
+		if err := ifInfo.SetIPAddress(inIface.Address); err != nil {
142
+			return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid))
143 143
 		}
144
-		if err := epInfo.AddInterface(inIface.MacAddress, addr4, addr6); err != nil {
145
-			return errorWithRollback(fmt.Sprintf("failed to AddInterface %v: %s", inIface, err), d.DeleteEndpoint(nid, eid))
144
+	}
145
+	if inIface.AddressIPv6 != nil {
146
+		if err := ifInfo.SetIPAddress(inIface.AddressIPv6); err != nil {
147
+			return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid))
146 148
 		}
147 149
 	}
150
+
148 151
 	return nil
149 152
 }
150 153
 
... ...
@@ -193,11 +197,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
193 193
 	}
194 194
 
195 195
 	ifaceName := res.InterfaceName
196
-	if jinfo.InterfaceName() != nil && ifaceName == nil {
197
-		return fmt.Errorf("no interface name information received while one is expected")
198
-	}
199
-
200
-	if iface := jinfo.InterfaceName(); iface != nil {
196
+	if iface := jinfo.InterfaceName(); iface != nil && ifaceName != nil {
201 197
 		if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix); err != nil {
202 198
 			return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid))
203 199
 		}
... ...
@@ -278,7 +278,7 @@ func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) {
278 278
 		outRoute := &types.StaticRoute{RouteType: inRoute.RouteType}
279 279
 
280 280
 		if inRoute.Destination != "" {
281
-			if outRoute.Destination, err = toAddr(inRoute.Destination); err != nil {
281
+			if outRoute.Destination, err = types.ParseCIDR(inRoute.Destination); err != nil {
282 282
 				return nil, err
283 283
 			}
284 284
 		}
... ...
@@ -304,12 +304,12 @@ func parseInterface(r api.CreateEndpointResponse) (*api.Interface, error) {
304 304
 		var err error
305 305
 		outIf = &api.Interface{}
306 306
 		if inIf.Address != "" {
307
-			if outIf.Address, err = toAddr(inIf.Address); err != nil {
307
+			if outIf.Address, err = types.ParseCIDR(inIf.Address); err != nil {
308 308
 				return nil, err
309 309
 			}
310 310
 		}
311 311
 		if inIf.AddressIPv6 != "" {
312
-			if outIf.AddressIPv6, err = toAddr(inIf.AddressIPv6); err != nil {
312
+			if outIf.AddressIPv6, err = types.ParseCIDR(inIf.AddressIPv6); err != nil {
313 313
 				return nil, err
314 314
 			}
315 315
 		}
... ...
@@ -322,12 +322,3 @@ func parseInterface(r api.CreateEndpointResponse) (*api.Interface, error) {
322 322
 
323 323
 	return outIf, nil
324 324
 }
325
-
326
-func toAddr(ipAddr string) (*net.IPNet, error) {
327
-	ip, ipnet, err := net.ParseCIDR(ipAddr)
328
-	if err != nil {
329
-		return nil, err
330
-	}
331
-	ipnet.IP = ip
332
-	return ipnet, nil
333
-}
... ...
@@ -19,7 +19,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
19 19
 	return dc.RegisterDriver(networkType, &driver{}, c)
20 20
 }
21 21
 
22
-func (d *driver) CreateNetwork(id string, option map[string]interface{}) error {
22
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
23 23
 	return nil
24 24
 }
25 25
 
... ...
@@ -27,7 +27,7 @@ func (d *driver) DeleteNetwork(nid string) error {
27 27
 	return nil
28 28
 }
29 29
 
30
-func (d *driver) CreateEndpoint(nid, eid string, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
30
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
31 31
 	return nil
32 32
 }
33 33
 
... ...
@@ -10,7 +10,9 @@ import (
10 10
 
11 11
 	log "github.com/Sirupsen/logrus"
12 12
 	"github.com/docker/libnetwork/datastore"
13
+	"github.com/docker/libnetwork/ipamapi"
13 14
 	"github.com/docker/libnetwork/netlabel"
15
+	"github.com/docker/libnetwork/options"
14 16
 	"github.com/docker/libnetwork/types"
15 17
 )
16 18
 
... ...
@@ -71,7 +73,9 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) {
71 71
 	epMap["id"] = ep.id
72 72
 	epMap["ep_iface"] = ep.iface
73 73
 	epMap["exposed_ports"] = ep.exposedPorts
74
-	epMap["generic"] = ep.generic
74
+	if ep.generic != nil {
75
+		epMap["generic"] = ep.generic
76
+	}
75 77
 	epMap["sandbox"] = ep.sandboxID
76 78
 	return json.Marshal(epMap)
77 79
 }
... ...
@@ -98,12 +102,43 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
98 98
 	cb, _ := json.Marshal(epMap["sandbox"])
99 99
 	json.Unmarshal(cb, &ep.sandboxID)
100 100
 
101
-	if epMap["generic"] != nil {
102
-		ep.generic = epMap["generic"].(map[string]interface{})
101
+	if v, ok := epMap["generic"]; ok {
102
+		ep.generic = v.(map[string]interface{})
103 103
 	}
104 104
 	return nil
105 105
 }
106 106
 
107
+func (ep *endpoint) New() datastore.KVObject {
108
+	return &endpoint{network: ep.getNetwork()}
109
+}
110
+
111
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
112
+	ep.Lock()
113
+	defer ep.Unlock()
114
+
115
+	dstEp := o.(*endpoint)
116
+	dstEp.name = ep.name
117
+	dstEp.id = ep.id
118
+	dstEp.sandboxID = ep.sandboxID
119
+	dstEp.dbIndex = ep.dbIndex
120
+	dstEp.dbExists = ep.dbExists
121
+
122
+	if ep.iface != nil {
123
+		dstEp.iface = &endpointInterface{}
124
+		ep.iface.CopyTo(dstEp.iface)
125
+	}
126
+
127
+	dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
128
+	copy(dstEp.exposedPorts, ep.exposedPorts)
129
+
130
+	dstEp.generic = options.Generic{}
131
+	for k, v := range ep.generic {
132
+		dstEp.generic[k] = v
133
+	}
134
+
135
+	return nil
136
+}
137
+
107 138
 func (ep *endpoint) ID() string {
108 139
 	ep.Lock()
109 140
 	defer ep.Unlock()
... ...
@@ -119,16 +154,28 @@ func (ep *endpoint) Name() string {
119 119
 }
120 120
 
121 121
 func (ep *endpoint) Network() string {
122
-	return ep.getNetwork().name
122
+	if ep.network == nil {
123
+		return ""
124
+	}
125
+
126
+	return ep.network.name
123 127
 }
124 128
 
125 129
 // endpoint Key structure : endpoint/network-id/endpoint-id
126 130
 func (ep *endpoint) Key() []string {
127
-	return []string{datastore.EndpointKeyPrefix, ep.getNetwork().id, ep.id}
131
+	if ep.network == nil {
132
+		return nil
133
+	}
134
+
135
+	return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id}
128 136
 }
129 137
 
130 138
 func (ep *endpoint) KeyPrefix() []string {
131
-	return []string{datastore.EndpointKeyPrefix, ep.getNetwork().id}
139
+	if ep.network == nil {
140
+		return nil
141
+	}
142
+
143
+	return []string{datastore.EndpointKeyPrefix, ep.network.id}
132 144
 }
133 145
 
134 146
 func (ep *endpoint) networkIDFromKey(key string) (string, error) {
... ...
@@ -188,8 +235,22 @@ func (ep *endpoint) processOptions(options ...EndpointOption) {
188 188
 	}
189 189
 }
190 190
 
191
-func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
191
+func (ep *endpoint) getNetwork() *network {
192
+	ep.Lock()
193
+	defer ep.Unlock()
194
+
195
+	return ep.network
196
+}
197
+
198
+func (ep *endpoint) getNetworkFromStore() (*network, error) {
199
+	if ep.network == nil {
200
+		return nil, fmt.Errorf("invalid network object in endpoint %s", ep.Name())
201
+	}
192 202
 
203
+	return ep.network.ctrlr.getNetworkFromStore(ep.network.id)
204
+}
205
+
206
+func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
193 207
 	if sbox == nil {
194 208
 		return types.BadRequestErrorf("endpoint cannot be joined by nil container")
195 209
 	}
... ...
@@ -212,15 +273,27 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
212 212
 		return types.BadRequestErrorf("not a valid Sandbox interface")
213 213
 	}
214 214
 
215
+	network, err := ep.getNetworkFromStore()
216
+	if err != nil {
217
+		return fmt.Errorf("failed to get network from store during join: %v", err)
218
+	}
219
+
220
+	ep, err = network.getEndpointFromStore(ep.ID())
221
+	if err != nil {
222
+		return fmt.Errorf("failed to get endpoint from store during join: %v", err)
223
+	}
224
+
215 225
 	ep.Lock()
216 226
 	if ep.sandboxID != "" {
217 227
 		ep.Unlock()
218
-		return types.ForbiddenErrorf("a sandbox has already joined the endpoint")
228
+		return types.ForbiddenErrorf("another container is attached to the same network endpoint")
219 229
 	}
230
+	ep.Unlock()
220 231
 
232
+	ep.Lock()
233
+	ep.network = network
221 234
 	ep.sandboxID = sbox.ID()
222 235
 	ep.joinInfo = &endpointJoinInfo{}
223
-	network := ep.network
224 236
 	epid := ep.id
225 237
 	ep.Unlock()
226 238
 	defer func() {
... ...
@@ -232,12 +305,16 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
232 232
 	}()
233 233
 
234 234
 	network.Lock()
235
-	driver := network.driver
236 235
 	nid := network.id
237 236
 	network.Unlock()
238 237
 
239 238
 	ep.processOptions(options...)
240 239
 
240
+	driver, err := network.driver()
241
+	if err != nil {
242
+		return fmt.Errorf("failed to join endpoint: %v", err)
243
+	}
244
+
241 245
 	err = driver.Join(nid, epid, sbox.Key(), ep, sbox.Labels())
242 246
 	if err != nil {
243 247
 		return err
... ...
@@ -259,14 +336,15 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
259 259
 		return err
260 260
 	}
261 261
 
262
-	if err = sb.updateDNS(ep.getNetwork().enableIPv6); err != nil {
262
+	// Watch for service records
263
+	network.getController().watchSvcRecord(ep)
264
+
265
+	if err = sb.updateDNS(network.enableIPv6); err != nil {
263 266
 		return err
264 267
 	}
265 268
 
266
-	if !ep.isLocalScoped() {
267
-		if err = network.ctrlr.updateToStore(ep); err != nil {
268
-			return err
269
-		}
269
+	if err = network.getController().updateToStore(ep); err != nil {
270
+		return err
270 271
 	}
271 272
 
272 273
 	sb.Lock()
... ...
@@ -324,6 +402,16 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
324 324
 		return types.BadRequestErrorf("not a valid Sandbox interface")
325 325
 	}
326 326
 
327
+	n, err := ep.getNetworkFromStore()
328
+	if err != nil {
329
+		return fmt.Errorf("failed to get network from store during leave: %v", err)
330
+	}
331
+
332
+	ep, err = n.getEndpointFromStore(ep.ID())
333
+	if err != nil {
334
+		return fmt.Errorf("failed to get endpoint from store during leave: %v", err)
335
+	}
336
+
327 337
 	ep.Lock()
328 338
 	sid := ep.sandboxID
329 339
 	ep.Unlock()
... ...
@@ -339,21 +427,19 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
339 339
 
340 340
 	ep.Lock()
341 341
 	ep.sandboxID = ""
342
-	n := ep.network
342
+	ep.network = n
343 343
 	ep.Unlock()
344 344
 
345
-	n.Lock()
346
-	c := n.ctrlr
347
-	d := n.driver
348
-	n.Unlock()
345
+	if err := n.getController().updateToStore(ep); err != nil {
346
+		ep.Lock()
347
+		ep.sandboxID = sid
348
+		ep.Unlock()
349
+		return err
350
+	}
349 351
 
350
-	if !ep.isLocalScoped() {
351
-		if err := c.updateToStore(ep); err != nil {
352
-			ep.Lock()
353
-			ep.sandboxID = sid
354
-			ep.Unlock()
355
-			return err
356
-		}
352
+	d, err := n.driver()
353
+	if err != nil {
354
+		return fmt.Errorf("failed to leave endpoint: %v", err)
357 355
 	}
358 356
 
359 357
 	if err := d.Leave(n.id, ep.id); err != nil {
... ...
@@ -364,6 +450,9 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
364 364
 		return err
365 365
 	}
366 366
 
367
+	// unwatch for service records
368
+	n.getController().unWatchSvcRecord(ep)
369
+
367 370
 	if sb.needDefaultGW() {
368 371
 		ep := sb.getEPwithoutGateway()
369 372
 		if ep == nil {
... ...
@@ -376,45 +465,44 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
376 376
 
377 377
 func (ep *endpoint) Delete() error {
378 378
 	var err error
379
+	n, err := ep.getNetworkFromStore()
380
+	if err != nil {
381
+		return fmt.Errorf("failed to get network during Delete: %v", err)
382
+	}
383
+
384
+	ep, err = n.getEndpointFromStore(ep.ID())
385
+	if err != nil {
386
+		return fmt.Errorf("failed to get endpoint from store during Delete: %v", err)
387
+	}
388
+
379 389
 	ep.Lock()
380 390
 	epid := ep.id
381 391
 	name := ep.name
382
-	n := ep.network
383 392
 	if ep.sandboxID != "" {
384 393
 		ep.Unlock()
385 394
 		return &ActiveContainerError{name: name, id: epid}
386 395
 	}
387
-	n.Lock()
388
-	ctrlr := n.ctrlr
389
-	n.Unlock()
390 396
 	ep.Unlock()
391 397
 
392
-	if !ep.isLocalScoped() {
393
-		if err = ctrlr.deleteFromStore(ep); err != nil {
394
-			return err
395
-		}
398
+	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
399
+		return err
396 400
 	}
397 401
 	defer func() {
398 402
 		if err != nil {
399
-			ep.dbExists = false
400
-			if !ep.isLocalScoped() {
401
-				if e := ctrlr.updateToStore(ep); e != nil {
402
-					log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
403
-				}
403
+			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
404
+				log.Warnf("failed to update network %s : %v", n.name, e)
404 405
 			}
405 406
 		}
406 407
 	}()
407 408
 
408
-	// Update the endpoint count in network and update it in the datastore
409
-	n.DecEndpointCnt()
410
-	if err = ctrlr.updateToStore(n); err != nil {
409
+	if err = n.getController().deleteFromStore(ep); err != nil {
411 410
 		return err
412 411
 	}
413 412
 	defer func() {
414 413
 		if err != nil {
415
-			n.IncEndpointCnt()
416
-			if e := ctrlr.updateToStore(n); e != nil {
417
-				log.Warnf("failed to update network %s : %v", n.name, e)
414
+			ep.dbExists = false
415
+			if e := n.getController().updateToStore(ep); e != nil {
416
+				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
418 417
 			}
419 418
 		}
420 419
 	}()
... ...
@@ -423,6 +511,8 @@ func (ep *endpoint) Delete() error {
423 423
 		return err
424 424
 	}
425 425
 
426
+	ep.releaseAddress()
427
+
426 428
 	return nil
427 429
 }
428 430
 
... ...
@@ -433,38 +523,21 @@ func (ep *endpoint) deleteEndpoint() error {
433 433
 	epid := ep.id
434 434
 	ep.Unlock()
435 435
 
436
-	n.Lock()
437
-	_, ok := n.endpoints[epid]
438
-	if !ok {
439
-		n.Unlock()
440
-		return nil
436
+	driver, err := n.driver()
437
+	if err != nil {
438
+		return fmt.Errorf("failed to delete endpoint: %v", err)
441 439
 	}
442 440
 
443
-	nid := n.id
444
-	driver := n.driver
445
-	delete(n.endpoints, epid)
446
-	n.Unlock()
447
-
448
-	if err := driver.DeleteEndpoint(nid, epid); err != nil {
441
+	if err := driver.DeleteEndpoint(n.id, epid); err != nil {
449 442
 		if _, ok := err.(types.ForbiddenError); ok {
450
-			n.Lock()
451
-			n.endpoints[epid] = ep
452
-			n.Unlock()
453 443
 			return err
454 444
 		}
455 445
 		log.Warnf("driver error deleting endpoint %s : %v", name, err)
456 446
 	}
457 447
 
458
-	n.updateSvcRecord(ep, false)
459 448
 	return nil
460 449
 }
461 450
 
462
-func (ep *endpoint) getNetwork() *network {
463
-	ep.Lock()
464
-	defer ep.Unlock()
465
-	return ep.network
466
-}
467
-
468 451
 func (ep *endpoint) getSandbox() (*sandbox, bool) {
469 452
 	ep.Lock()
470 453
 	c := ep.network.getController()
... ...
@@ -482,7 +555,7 @@ func (ep *endpoint) getFirstInterfaceAddress() net.IP {
482 482
 	ep.Lock()
483 483
 	defer ep.Unlock()
484 484
 
485
-	if ep.iface != nil {
485
+	if ep.iface.addr != nil {
486 486
 		return ep.iface.addr.IP
487 487
 	}
488 488
 
... ...
@@ -540,12 +613,94 @@ func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
540 540
 	}
541 541
 }
542 542
 
543
-func (ep *endpoint) DataScope() datastore.DataScope {
544
-	ep.Lock()
545
-	defer ep.Unlock()
546
-	return ep.network.dataScope
543
+func (ep *endpoint) DataScope() string {
544
+	return ep.getNetwork().DataScope()
545
+}
546
+
547
+func (ep *endpoint) assignAddress() error {
548
+	var (
549
+		ipam ipamapi.Ipam
550
+		err  error
551
+	)
552
+
553
+	n := ep.getNetwork()
554
+	if n.Type() == "host" || n.Type() == "null" {
555
+		return nil
556
+	}
557
+
558
+	log.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
559
+
560
+	ipam, err = n.getController().getIpamDriver(n.ipamType)
561
+	if err != nil {
562
+		return err
563
+	}
564
+	err = ep.assignAddressVersion(4, ipam)
565
+	if err != nil {
566
+		return err
567
+	}
568
+	return ep.assignAddressVersion(6, ipam)
547 569
 }
548 570
 
549
-func (ep *endpoint) isLocalScoped() bool {
550
-	return ep.DataScope() == datastore.LocalScope
571
+func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
572
+	var (
573
+		poolID  *string
574
+		address **net.IPNet
575
+	)
576
+
577
+	n := ep.getNetwork()
578
+	switch ipVer {
579
+	case 4:
580
+		poolID = &ep.iface.v4PoolID
581
+		address = &ep.iface.addr
582
+	case 6:
583
+		poolID = &ep.iface.v6PoolID
584
+		address = &ep.iface.addrv6
585
+	default:
586
+		return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
587
+	}
588
+
589
+	ipInfo := n.getIPInfo(ipVer)
590
+
591
+	// ipv6 address is not mandatory
592
+	if len(ipInfo) == 0 && ipVer == 6 {
593
+		return nil
594
+	}
595
+
596
+	for _, d := range ipInfo {
597
+		addr, _, err := ipam.RequestAddress(d.PoolID, nil, nil)
598
+		if err == nil {
599
+			ep.Lock()
600
+			*address = addr
601
+			*poolID = d.PoolID
602
+			ep.Unlock()
603
+			return nil
604
+		}
605
+		if err != ipamapi.ErrNoAvailableIPs {
606
+			return err
607
+		}
608
+	}
609
+	return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
610
+}
611
+
612
+func (ep *endpoint) releaseAddress() {
613
+	n := ep.getNetwork()
614
+	if n.Type() == "host" || n.Type() == "null" {
615
+		return
616
+	}
617
+
618
+	log.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
619
+
620
+	ipam, err := n.getController().getIpamDriver(n.ipamType)
621
+	if err != nil {
622
+		log.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
623
+		return
624
+	}
625
+	if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
626
+		log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
627
+	}
628
+	if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
629
+		if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
630
+			log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
631
+		}
632
+	}
551 633
 }
552 634
new file mode 100644
... ...
@@ -0,0 +1,147 @@
0
+package libnetwork
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+	"sync"
6
+
7
+	"github.com/docker/libnetwork/datastore"
8
+)
9
+
10
+type endpointCnt struct {
11
+	n        *network
12
+	Count    uint64
13
+	dbIndex  uint64
14
+	dbExists bool
15
+	sync.Mutex
16
+}
17
+
18
+const epCntKeyPrefix = "endpoint_count"
19
+
20
+func (ec *endpointCnt) Key() []string {
21
+	ec.Lock()
22
+	defer ec.Unlock()
23
+
24
+	return []string{epCntKeyPrefix, ec.n.id}
25
+}
26
+
27
+func (ec *endpointCnt) KeyPrefix() []string {
28
+	ec.Lock()
29
+	defer ec.Unlock()
30
+
31
+	return []string{epCntKeyPrefix, ec.n.id}
32
+}
33
+
34
+func (ec *endpointCnt) Value() []byte {
35
+	ec.Lock()
36
+	defer ec.Unlock()
37
+
38
+	b, err := json.Marshal(ec)
39
+	if err != nil {
40
+		return nil
41
+	}
42
+	return b
43
+}
44
+
45
+func (ec *endpointCnt) SetValue(value []byte) error {
46
+	ec.Lock()
47
+	defer ec.Unlock()
48
+
49
+	return json.Unmarshal(value, &ec)
50
+}
51
+
52
+func (ec *endpointCnt) Index() uint64 {
53
+	ec.Lock()
54
+	defer ec.Unlock()
55
+	return ec.dbIndex
56
+}
57
+
58
+func (ec *endpointCnt) SetIndex(index uint64) {
59
+	ec.Lock()
60
+	ec.dbIndex = index
61
+	ec.dbExists = true
62
+	ec.Unlock()
63
+}
64
+
65
+func (ec *endpointCnt) Exists() bool {
66
+	ec.Lock()
67
+	defer ec.Unlock()
68
+	return ec.dbExists
69
+}
70
+
71
+func (ec *endpointCnt) Skip() bool {
72
+	ec.Lock()
73
+	defer ec.Unlock()
74
+	return !ec.n.persist
75
+}
76
+
77
+func (ec *endpointCnt) New() datastore.KVObject {
78
+	ec.Lock()
79
+	defer ec.Unlock()
80
+
81
+	return &endpointCnt{
82
+		n: ec.n,
83
+	}
84
+}
85
+
86
+func (ec *endpointCnt) CopyTo(o datastore.KVObject) error {
87
+	ec.Lock()
88
+	defer ec.Unlock()
89
+
90
+	dstEc := o.(*endpointCnt)
91
+	dstEc.n = ec.n
92
+	dstEc.Count = ec.Count
93
+	dstEc.dbExists = ec.dbExists
94
+	dstEc.dbIndex = ec.dbIndex
95
+
96
+	return nil
97
+}
98
+
99
+func (ec *endpointCnt) DataScope() string {
100
+	return ec.n.DataScope()
101
+}
102
+
103
+func (ec *endpointCnt) EndpointCnt() uint64 {
104
+	ec.Lock()
105
+	defer ec.Unlock()
106
+
107
+	return ec.Count
108
+}
109
+
110
+func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error {
111
+retry:
112
+	ec.Lock()
113
+	if inc {
114
+		ec.Count++
115
+	} else {
116
+		ec.Count--
117
+	}
118
+	ec.Unlock()
119
+
120
+	store := ec.n.getController().getStore(ec.DataScope())
121
+	if store == nil {
122
+		return fmt.Errorf("store not found for scope %s", ec.DataScope())
123
+	}
124
+
125
+	if err := ec.n.getController().updateToStore(ec); err != nil {
126
+		if err == datastore.ErrKeyModified {
127
+			if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
128
+				return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err)
129
+			}
130
+
131
+			goto retry
132
+		}
133
+
134
+		return err
135
+	}
136
+
137
+	return nil
138
+}
139
+
140
+func (ec *endpointCnt) IncEndpointCnt() error {
141
+	return ec.atomicIncDecEpCnt(true)
142
+}
143
+
144
+func (ec *endpointCnt) DecEndpointCnt() error {
145
+	return ec.atomicIncDecEpCnt(false)
146
+}
... ...
@@ -2,6 +2,7 @@ package libnetwork
2 2
 
3 3
 import (
4 4
 	"encoding/json"
5
+	"fmt"
5 6
 	"net"
6 7
 
7 8
 	"github.com/docker/libnetwork/driverapi"
... ...
@@ -34,26 +35,34 @@ type InterfaceInfo interface {
34 34
 	MacAddress() net.HardwareAddr
35 35
 
36 36
 	// Address returns the IPv4 address assigned to the endpoint.
37
-	Address() net.IPNet
37
+	Address() *net.IPNet
38 38
 
39 39
 	// AddressIPv6 returns the IPv6 address assigned to the endpoint.
40
-	AddressIPv6() net.IPNet
40
+	AddressIPv6() *net.IPNet
41 41
 }
42 42
 
43 43
 type endpointInterface struct {
44 44
 	mac       net.HardwareAddr
45
-	addr      net.IPNet
46
-	addrv6    net.IPNet
45
+	addr      *net.IPNet
46
+	addrv6    *net.IPNet
47 47
 	srcName   string
48 48
 	dstPrefix string
49 49
 	routes    []*net.IPNet
50
+	v4PoolID  string
51
+	v6PoolID  string
50 52
 }
51 53
 
52 54
 func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
53 55
 	epMap := make(map[string]interface{})
54
-	epMap["mac"] = epi.mac.String()
55
-	epMap["addr"] = epi.addr.String()
56
-	epMap["addrv6"] = epi.addrv6.String()
56
+	if epi.mac != nil {
57
+		epMap["mac"] = epi.mac.String()
58
+	}
59
+	if epi.addr != nil {
60
+		epMap["addr"] = epi.addr.String()
61
+	}
62
+	if epi.addrv6 != nil {
63
+		epMap["addrv6"] = epi.addrv6.String()
64
+	}
57 65
 	epMap["srcName"] = epi.srcName
58 66
 	epMap["dstPrefix"] = epi.dstPrefix
59 67
 	var routes []string
... ...
@@ -61,28 +70,33 @@ func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
61 61
 		routes = append(routes, route.String())
62 62
 	}
63 63
 	epMap["routes"] = routes
64
+	epMap["v4PoolID"] = epi.v4PoolID
65
+	epMap["v6PoolID"] = epi.v6PoolID
64 66
 	return json.Marshal(epMap)
65 67
 }
66 68
 
67
-func (epi *endpointInterface) UnmarshalJSON(b []byte) (err error) {
68
-	var epMap map[string]interface{}
69
-	if err := json.Unmarshal(b, &epMap); err != nil {
69
+func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
70
+	var (
71
+		err   error
72
+		epMap map[string]interface{}
73
+	)
74
+	if err = json.Unmarshal(b, &epMap); err != nil {
70 75
 		return err
71 76
 	}
72
-
73
-	mac, _ := net.ParseMAC(epMap["mac"].(string))
74
-	epi.mac = mac
75
-
76
-	ip, ipnet, _ := net.ParseCIDR(epMap["addr"].(string))
77
-	if ipnet != nil {
78
-		ipnet.IP = ip
79
-		epi.addr = *ipnet
77
+	if v, ok := epMap["mac"]; ok {
78
+		if epi.mac, err = net.ParseMAC(v.(string)); err != nil {
79
+			return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
80
+		}
80 81
 	}
81
-
82
-	ip, ipnet, _ = net.ParseCIDR(epMap["addrv6"].(string))
83
-	if ipnet != nil {
84
-		ipnet.IP = ip
85
-		epi.addrv6 = *ipnet
82
+	if v, ok := epMap["addr"]; ok {
83
+		if epi.addr, err = types.ParseCIDR(v.(string)); err != nil {
84
+			return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
85
+		}
86
+	}
87
+	if v, ok := epMap["addrv6"]; ok {
88
+		if epi.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
89
+			return types.InternalErrorf("failed to decode endpoint interface ipv6 address after json unmarshal: %v", err)
90
+		}
86 91
 	}
87 92
 
88 93
 	epi.srcName = epMap["srcName"].(string)
... ...
@@ -99,6 +113,24 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) (err error) {
99 99
 			epi.routes = append(epi.routes, ipr)
100 100
 		}
101 101
 	}
102
+	epi.v4PoolID = epMap["v4PoolID"].(string)
103
+	epi.v6PoolID = epMap["v6PoolID"].(string)
104
+
105
+	return nil
106
+}
107
+
108
+func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error {
109
+	dstEpi.mac = types.GetMacCopy(epi.mac)
110
+	dstEpi.addr = types.GetIPNetCopy(epi.addr)
111
+	dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6)
112
+	dstEpi.srcName = epi.srcName
113
+	dstEpi.dstPrefix = epi.dstPrefix
114
+	dstEpi.v4PoolID = epi.v4PoolID
115
+	dstEpi.v6PoolID = epi.v6PoolID
116
+
117
+	for _, route := range epi.routes {
118
+		dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route))
119
+	}
102 120
 
103 121
 	return nil
104 122
 }
... ...
@@ -110,21 +142,38 @@ type endpointJoinInfo struct {
110 110
 }
111 111
 
112 112
 func (ep *endpoint) Info() EndpointInfo {
113
-	return ep
113
+	n, err := ep.getNetworkFromStore()
114
+	if err != nil {
115
+		return nil
116
+	}
117
+
118
+	ep, err = n.getEndpointFromStore(ep.ID())
119
+	if err != nil {
120
+		return nil
121
+	}
122
+
123
+	sb, ok := ep.getSandbox()
124
+	if !ok {
125
+		// endpoint hasn't joined any sandbox.
126
+		// Just return the endpoint
127
+		return ep
128
+	}
129
+
130
+	return sb.getEndpoint(ep.ID())
114 131
 }
115 132
 
116 133
 func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
117
-	ep.Lock()
118
-	network := ep.network
119
-	epid := ep.id
120
-	ep.Unlock()
134
+	n, err := ep.getNetworkFromStore()
135
+	if err != nil {
136
+		return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
137
+	}
121 138
 
122
-	network.Lock()
123
-	driver := network.driver
124
-	nid := network.id
125
-	network.Unlock()
139
+	driver, err := n.driver()
140
+	if err != nil {
141
+		return nil, fmt.Errorf("failed to get driver info: %v", err)
142
+	}
126 143
 
127
-	return driver.EndpointOperInfo(nid, epid)
144
+	return driver.EndpointOperInfo(n.ID(), ep.ID())
128 145
 }
129 146
 
130 147
 func (ep *endpoint) Iface() InterfaceInfo {
... ...
@@ -149,17 +198,32 @@ func (ep *endpoint) Interface() driverapi.InterfaceInfo {
149 149
 	return nil
150 150
 }
151 151
 
152
-func (ep *endpoint) AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error {
153
-	ep.Lock()
154
-	defer ep.Unlock()
152
+func (epi *endpointInterface) SetMacAddress(mac net.HardwareAddr) error {
153
+	if epi.mac != nil {
154
+		return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", epi.mac, mac)
155
+	}
156
+	if mac == nil {
157
+		return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
158
+	}
159
+	epi.mac = types.GetMacCopy(mac)
160
+	return nil
161
+}
155 162
 
156
-	iface := &endpointInterface{
157
-		addr:   *types.GetIPNetCopy(&ipv4),
158
-		addrv6: *types.GetIPNetCopy(&ipv6),
163
+func (epi *endpointInterface) SetIPAddress(address *net.IPNet) error {
164
+	if address.IP == nil {
165
+		return types.BadRequestErrorf("tried to set nil IP address to endpoint interface")
166
+	}
167
+	if address.IP.To4() == nil {
168
+		return setAddress(&epi.addrv6, address)
159 169
 	}
160
-	iface.mac = types.GetMacCopy(mac)
170
+	return setAddress(&epi.addr, address)
171
+}
161 172
 
162
-	ep.iface = iface
173
+func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error {
174
+	if *ifaceAddr != nil {
175
+		return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address)
176
+	}
177
+	*ifaceAddr = types.GetIPNetCopy(address)
163 178
 	return nil
164 179
 }
165 180
 
... ...
@@ -167,12 +231,12 @@ func (epi *endpointInterface) MacAddress() net.HardwareAddr {
167 167
 	return types.GetMacCopy(epi.mac)
168 168
 }
169 169
 
170
-func (epi *endpointInterface) Address() net.IPNet {
171
-	return (*types.GetIPNetCopy(&epi.addr))
170
+func (epi *endpointInterface) Address() *net.IPNet {
171
+	return types.GetIPNetCopy(epi.addr)
172 172
 }
173 173
 
174
-func (epi *endpointInterface) AddressIPv6() net.IPNet {
175
-	return (*types.GetIPNetCopy(&epi.addrv6))
174
+func (epi *endpointInterface) AddressIPv6() *net.IPNet {
175
+	return types.GetIPNetCopy(epi.addrv6)
176 176
 }
177 177
 
178 178
 func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error {
... ...
@@ -129,7 +129,7 @@ type ActiveEndpointsError struct {
129 129
 }
130 130
 
131 131
 func (aee *ActiveEndpointsError) Error() string {
132
-	return fmt.Sprintf("network with name %s id %s has active endpoints", aee.name, aee.id)
132
+	return fmt.Sprintf("network %s has active endpoints", aee.name)
133 133
 }
134 134
 
135 135
 // Forbidden denotes the type of this error
... ...
@@ -10,13 +10,13 @@ import (
10 10
 
11 11
 // Idm manages the reservation/release of numerical ids from a contiguos set
12 12
 type Idm struct {
13
-	start  uint32
14
-	end    uint32
13
+	start  uint64
14
+	end    uint64
15 15
 	handle *bitseq.Handle
16 16
 }
17 17
 
18 18
 // New returns an instance of id manager for a set of [start-end] numerical ids
19
-func New(ds datastore.DataStore, id string, start, end uint32) (*Idm, error) {
19
+func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) {
20 20
 	if id == "" {
21 21
 		return nil, fmt.Errorf("Invalid id")
22 22
 	}
... ...
@@ -33,7 +33,7 @@ func New(ds datastore.DataStore, id string, start, end uint32) (*Idm, error) {
33 33
 }
34 34
 
35 35
 // GetID returns the first available id in the set
36
-func (i *Idm) GetID() (uint32, error) {
36
+func (i *Idm) GetID() (uint64, error) {
37 37
 	if i.handle == nil {
38 38
 		return 0, fmt.Errorf("ID set is not initialized")
39 39
 	}
... ...
@@ -42,7 +42,7 @@ func (i *Idm) GetID() (uint32, error) {
42 42
 }
43 43
 
44 44
 // GetSpecificID tries to reserve the specified id
45
-func (i *Idm) GetSpecificID(id uint32) error {
45
+func (i *Idm) GetSpecificID(id uint64) error {
46 46
 	if i.handle == nil {
47 47
 		return fmt.Errorf("ID set is not initialized")
48 48
 	}
... ...
@@ -55,6 +55,6 @@ func (i *Idm) GetSpecificID(id uint32) error {
55 55
 }
56 56
 
57 57
 // Release releases the specified id
58
-func (i *Idm) Release(id uint32) {
58
+func (i *Idm) Release(id uint64) {
59 59
 	i.handle.Unset(id - i.start)
60 60
 }
61 61
deleted file mode 100644
... ...
@@ -1,175 +0,0 @@
1
-// Package ipallocator defines the default IP allocator. It will move out of libnetwork as an external IPAM plugin.
2
-// This has been imported unchanged from Docker, besides additon of registration logic
3
-package ipallocator
4
-
5
-import (
6
-	"errors"
7
-	"math/big"
8
-	"net"
9
-	"sync"
10
-
11
-	"github.com/Sirupsen/logrus"
12
-	"github.com/docker/libnetwork/netutils"
13
-)
14
-
15
-// allocatedMap is thread-unsafe set of allocated IP
16
-type allocatedMap struct {
17
-	p     map[string]struct{}
18
-	last  *big.Int
19
-	begin *big.Int
20
-	end   *big.Int
21
-}
22
-
23
-func newAllocatedMap(network *net.IPNet) *allocatedMap {
24
-	firstIP, lastIP := netutils.NetworkRange(network)
25
-	begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
26
-	end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1))
27
-
28
-	return &allocatedMap{
29
-		p:     make(map[string]struct{}),
30
-		begin: begin,
31
-		end:   end,
32
-		last:  big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin
33
-	}
34
-}
35
-
36
-type networkSet map[string]*allocatedMap
37
-
38
-var (
39
-	// ErrNoAvailableIPs preformatted error
40
-	ErrNoAvailableIPs = errors.New("no available ip addresses on network")
41
-	// ErrIPAlreadyAllocated preformatted error
42
-	ErrIPAlreadyAllocated = errors.New("ip already allocated")
43
-	// ErrIPOutOfRange preformatted error
44
-	ErrIPOutOfRange = errors.New("requested ip is out of range")
45
-	// ErrNetworkAlreadyRegistered preformatted error
46
-	ErrNetworkAlreadyRegistered = errors.New("network already registered")
47
-	// ErrBadSubnet preformatted error
48
-	ErrBadSubnet = errors.New("network does not contain specified subnet")
49
-)
50
-
51
-// IPAllocator manages the ipam
52
-type IPAllocator struct {
53
-	allocatedIPs networkSet
54
-	mutex        sync.Mutex
55
-}
56
-
57
-// New returns a new instance of IPAllocator
58
-func New() *IPAllocator {
59
-	return &IPAllocator{networkSet{}, sync.Mutex{}}
60
-}
61
-
62
-// RegisterSubnet registers network in global allocator with bounds
63
-// defined by subnet. If you want to use network range you must call
64
-// this method before first RequestIP, otherwise full network range will be used
65
-func (a *IPAllocator) RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
66
-	a.mutex.Lock()
67
-	defer a.mutex.Unlock()
68
-
69
-	nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
70
-	key := nw.String()
71
-	if _, ok := a.allocatedIPs[key]; ok {
72
-		return ErrNetworkAlreadyRegistered
73
-	}
74
-
75
-	// Check that subnet is within network
76
-	beginIP, endIP := netutils.NetworkRange(subnet)
77
-	if !(network.Contains(beginIP) && network.Contains(endIP)) {
78
-		return ErrBadSubnet
79
-	}
80
-
81
-	n := newAllocatedMap(subnet)
82
-	a.allocatedIPs[key] = n
83
-	return nil
84
-}
85
-
86
-// RequestIP requests an available ip from the given network.  It
87
-// will return the next available ip if the ip provided is nil.  If the
88
-// ip provided is not nil it will validate that the provided ip is available
89
-// for use or return an error
90
-func (a *IPAllocator) RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
91
-	a.mutex.Lock()
92
-	defer a.mutex.Unlock()
93
-
94
-	nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
95
-	key := nw.String()
96
-	allocated, ok := a.allocatedIPs[key]
97
-	if !ok {
98
-		allocated = newAllocatedMap(nw)
99
-		a.allocatedIPs[key] = allocated
100
-	}
101
-
102
-	if ip == nil {
103
-		return allocated.getNextIP()
104
-	}
105
-	return allocated.checkIP(ip)
106
-}
107
-
108
-// ReleaseIP adds the provided ip back into the pool of
109
-// available ips to be returned for use.
110
-func (a *IPAllocator) ReleaseIP(network *net.IPNet, ip net.IP) error {
111
-	a.mutex.Lock()
112
-	defer a.mutex.Unlock()
113
-
114
-	nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
115
-	if allocated, exists := a.allocatedIPs[nw.String()]; exists {
116
-		delete(allocated.p, ip.String())
117
-	}
118
-	return nil
119
-}
120
-
121
-func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
122
-	if _, ok := allocated.p[ip.String()]; ok {
123
-		return nil, ErrIPAlreadyAllocated
124
-	}
125
-
126
-	pos := ipToBigInt(ip)
127
-	// Verify that the IP address is within our network range.
128
-	if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
129
-		return nil, ErrIPOutOfRange
130
-	}
131
-
132
-	// Register the IP.
133
-	allocated.p[ip.String()] = struct{}{}
134
-
135
-	return ip, nil
136
-}
137
-
138
-// return an available ip if one is currently available.  If not,
139
-// return the next available ip for the network
140
-func (allocated *allocatedMap) getNextIP() (net.IP, error) {
141
-	pos := big.NewInt(0).Set(allocated.last)
142
-	allRange := big.NewInt(0).Sub(allocated.end, allocated.begin)
143
-	for i := big.NewInt(0); i.Cmp(allRange) <= 0; i.Add(i, big.NewInt(1)) {
144
-		pos.Add(pos, big.NewInt(1))
145
-		if pos.Cmp(allocated.end) == 1 {
146
-			pos.Set(allocated.begin)
147
-		}
148
-		if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
149
-			continue
150
-		}
151
-		allocated.p[bigIntToIP(pos).String()] = struct{}{}
152
-		allocated.last.Set(pos)
153
-		return bigIntToIP(pos), nil
154
-	}
155
-	return nil, ErrNoAvailableIPs
156
-}
157
-
158
-// Converts a 4 bytes IP into a 128 bit integer
159
-func ipToBigInt(ip net.IP) *big.Int {
160
-	x := big.NewInt(0)
161
-	if ip4 := ip.To4(); ip4 != nil {
162
-		return x.SetBytes(ip4)
163
-	}
164
-	if ip6 := ip.To16(); ip6 != nil {
165
-		return x.SetBytes(ip6)
166
-	}
167
-
168
-	logrus.Errorf("ipToBigInt: Wrong IP length! %s", ip)
169
-	return nil
170
-}
171
-
172
-// Converts 128 bit integer into a 4 bytes IP address
173
-func bigIntToIP(v *big.Int) net.IP {
174
-	return net.IP(v.Bytes())
175
-}
176 1
new file mode 100644
... ...
@@ -0,0 +1,510 @@
0
+package ipam
1
+
2
+import (
3
+	"fmt"
4
+	"net"
5
+	"sync"
6
+
7
+	log "github.com/Sirupsen/logrus"
8
+	"github.com/docker/libnetwork/bitseq"
9
+	"github.com/docker/libnetwork/datastore"
10
+	"github.com/docker/libnetwork/ipamapi"
11
+	"github.com/docker/libnetwork/ipamutils"
12
+	"github.com/docker/libnetwork/types"
13
+)
14
+
15
+const (
16
+	localAddressSpace  = "LocalDefault"
17
+	globalAddressSpace = "GlobalDefault"
18
+	// The biggest configurable host subnets
19
+	minNetSize   = 8
20
+	minNetSizeV6 = 64
21
+	// datastore keyes for ipam objects
22
+	dsConfigKey = "ipam/" + ipamapi.DefaultIPAM + "/config"
23
+	dsDataKey   = "ipam/" + ipamapi.DefaultIPAM + "/data"
24
+)
25
+
26
+// Allocator provides per address space ipv4/ipv6 book keeping
27
+type Allocator struct {
28
+	// Predefined pools for default address spaces
29
+	predefined map[string][]*net.IPNet
30
+	addrSpaces map[string]*addrSpace
31
+	// stores        []datastore.Datastore
32
+	// Allocated addresses in each address space's subnet
33
+	addresses map[SubnetKey]*bitseq.Handle
34
+	sync.Mutex
35
+}
36
+
37
+// NewAllocator returns an instance of libnetwork ipam
38
+func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
39
+	a := &Allocator{}
40
+
41
+	// Load predefined subnet pools
42
+	a.predefined = map[string][]*net.IPNet{
43
+		localAddressSpace:  ipamutils.PredefinedBroadNetworks,
44
+		globalAddressSpace: ipamutils.PredefinedGranularNetworks,
45
+	}
46
+
47
+	// Initialize bitseq map
48
+	a.addresses = make(map[SubnetKey]*bitseq.Handle)
49
+
50
+	// Initialize address spaces
51
+	a.addrSpaces = make(map[string]*addrSpace)
52
+	for _, aspc := range []struct {
53
+		as string
54
+		ds datastore.DataStore
55
+	}{
56
+		{localAddressSpace, lcDs},
57
+		{globalAddressSpace, glDs},
58
+	} {
59
+		if aspc.ds == nil {
60
+			continue
61
+		}
62
+
63
+		a.addrSpaces[aspc.as] = &addrSpace{
64
+			subnets: map[SubnetKey]*PoolData{},
65
+			id:      dsConfigKey + "/" + aspc.as,
66
+			scope:   aspc.ds.Scope(),
67
+			ds:      aspc.ds,
68
+			alloc:   a,
69
+		}
70
+	}
71
+
72
+	return a, nil
73
+}
74
+
75
+func (a *Allocator) refresh(as string) error {
76
+	aSpace, err := a.getAddressSpaceFromStore(as)
77
+	if err != nil {
78
+		return fmt.Errorf("error getting pools config from store during init: %v",
79
+			err)
80
+	}
81
+
82
+	if aSpace == nil {
83
+		return nil
84
+	}
85
+
86
+	if err := a.updateBitMasks(aSpace); err != nil {
87
+		return fmt.Errorf("error updating bit masks during init: %v", err)
88
+	}
89
+
90
+	a.Lock()
91
+	a.addrSpaces[as] = aSpace
92
+	a.Unlock()
93
+
94
+	return nil
95
+}
96
+
97
+func (a *Allocator) updateBitMasks(aSpace *addrSpace) error {
98
+	var inserterList []func() error
99
+
100
+	aSpace.Lock()
101
+	for k, v := range aSpace.subnets {
102
+		if v.Range == nil {
103
+			kk := k
104
+			vv := v
105
+			inserterList = append(inserterList, func() error { return a.insertBitMask(kk, vv.Pool) })
106
+		}
107
+	}
108
+	aSpace.Unlock()
109
+
110
+	// Add the bitmasks (data could come from datastore)
111
+	if inserterList != nil {
112
+		for _, f := range inserterList {
113
+			if err := f(); err != nil {
114
+				return err
115
+			}
116
+		}
117
+	}
118
+
119
+	return nil
120
+}
121
+
122
+// GetDefaultAddressSpaces returns the local and global default address spaces
123
+func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
124
+	return localAddressSpace, globalAddressSpace, nil
125
+}
126
+
127
+// RequestPool returns an address pool along with its unique id.
128
+func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
129
+	log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
130
+	k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6)
131
+	if err != nil {
132
+		return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err)
133
+	}
134
+
135
+retry:
136
+	if err := a.refresh(addressSpace); err != nil {
137
+		return "", nil, nil, err
138
+	}
139
+
140
+	aSpace, err := a.getAddrSpace(addressSpace)
141
+	if err != nil {
142
+		return "", nil, nil, err
143
+	}
144
+
145
+	insert, err := aSpace.updatePoolDBOnAdd(*k, nw, ipr)
146
+	if err != nil {
147
+		return "", nil, nil, err
148
+	}
149
+
150
+	if err := a.writeToStore(aSpace); err != nil {
151
+		if _, ok := err.(types.RetryError); !ok {
152
+			return "", nil, nil, types.InternalErrorf("pool configuration failed because of %s", err.Error())
153
+		}
154
+
155
+		goto retry
156
+	}
157
+
158
+	return k.String(), nw, nil, insert()
159
+}
160
+
161
+// ReleasePool releases the address pool identified by the passed id
162
+func (a *Allocator) ReleasePool(poolID string) error {
163
+	log.Debugf("ReleasePool(%s)", poolID)
164
+	k := SubnetKey{}
165
+	if err := k.FromString(poolID); err != nil {
166
+		return types.BadRequestErrorf("invalid pool id: %s", poolID)
167
+	}
168
+
169
+retry:
170
+	if err := a.refresh(k.AddressSpace); err != nil {
171
+		return err
172
+	}
173
+
174
+	aSpace, err := a.getAddrSpace(k.AddressSpace)
175
+	if err != nil {
176
+		return err
177
+	}
178
+
179
+	remove, err := aSpace.updatePoolDBOnRemoval(k)
180
+	if err != nil {
181
+		return err
182
+	}
183
+
184
+	if err = a.writeToStore(aSpace); err != nil {
185
+		if _, ok := err.(types.RetryError); !ok {
186
+			return types.InternalErrorf("pool (%s) removal failed because of %v", poolID, err)
187
+		}
188
+		goto retry
189
+	}
190
+
191
+	return remove()
192
+}
193
+
194
+// Given the address space, returns the local or global PoolConfig based on the
195
+// address space is local or global. AddressSpace locality is being registered with IPAM out of band.
196
+func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
197
+	a.Lock()
198
+	defer a.Unlock()
199
+	aSpace, ok := a.addrSpaces[as]
200
+	if !ok {
201
+		return nil, types.BadRequestErrorf("cannot find address space %s (most likey the backing datastore is not configured)", as)
202
+	}
203
+	return aSpace, nil
204
+}
205
+
206
+func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) {
207
+	var (
208
+		nw  *net.IPNet
209
+		ipr *AddressRange
210
+		err error
211
+	)
212
+
213
+	if addressSpace == "" {
214
+		return nil, nil, nil, ipamapi.ErrInvalidAddressSpace
215
+	}
216
+
217
+	if pool == "" && subPool != "" {
218
+		return nil, nil, nil, ipamapi.ErrInvalidSubPool
219
+	}
220
+
221
+	if pool != "" {
222
+		if _, nw, err = net.ParseCIDR(pool); err != nil {
223
+			return nil, nil, nil, ipamapi.ErrInvalidPool
224
+		}
225
+		if subPool != "" {
226
+			if ipr, err = getAddressRange(subPool); err != nil {
227
+				return nil, nil, nil, err
228
+			}
229
+		}
230
+	} else {
231
+		if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
232
+			return nil, nil, nil, err
233
+		}
234
+
235
+	}
236
+
237
+	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil
238
+}
239
+
240
+func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
241
+	//log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String())
242
+
243
+	store := a.getStore(key.AddressSpace)
244
+	if store == nil {
245
+		return fmt.Errorf("could not find store for address space %s while inserting bit mask", key.AddressSpace)
246
+	}
247
+
248
+	ipVer := getAddressVersion(pool.IP)
249
+	ones, bits := pool.Mask.Size()
250
+	numAddresses := uint64(1 << uint(bits-ones))
251
+
252
+	if ipVer == v4 {
253
+		// Do not let broadcast address be reserved
254
+		numAddresses--
255
+	}
256
+
257
+	// Allow /64 subnet
258
+	if ipVer == v6 && numAddresses == 0 {
259
+		numAddresses--
260
+	}
261
+
262
+	// Generate the new address masks. AddressMask content may come from datastore
263
+	h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses)
264
+	if err != nil {
265
+		return err
266
+	}
267
+
268
+	// Do not let network identifier address be reserved
269
+	// Do the same for IPv6 so that bridge ip starts with XXXX...::1
270
+	h.Set(0)
271
+
272
+	a.Lock()
273
+	a.addresses[key] = h
274
+	a.Unlock()
275
+	return nil
276
+}
277
+
278
+func (a *Allocator) retrieveBitmask(k SubnetKey, n *net.IPNet) (*bitseq.Handle, error) {
279
+	a.Lock()
280
+	bm, ok := a.addresses[k]
281
+	a.Unlock()
282
+	if !ok {
283
+		log.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String())
284
+		if err := a.insertBitMask(k, n); err != nil {
285
+			return nil, fmt.Errorf("could not find bitmask in datastore for %s", k.String())
286
+		}
287
+		a.Lock()
288
+		bm = a.addresses[k]
289
+		a.Unlock()
290
+	}
291
+	return bm, nil
292
+}
293
+
294
+func (a *Allocator) getPredefineds(as string) []*net.IPNet {
295
+	a.Lock()
296
+	defer a.Unlock()
297
+	l := make([]*net.IPNet, 0, len(a.predefined[as]))
298
+	for _, pool := range a.predefined[as] {
299
+		l = append(l, pool)
300
+	}
301
+	return l
302
+}
303
+
304
+func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) {
305
+	var v ipVersion
306
+	v = v4
307
+	if ipV6 {
308
+		v = v6
309
+	}
310
+
311
+	if as != localAddressSpace && as != globalAddressSpace {
312
+		return nil, fmt.Errorf("no default pool availbale for non-default addresss spaces")
313
+	}
314
+
315
+	aSpace, err := a.getAddrSpace(as)
316
+	if err != nil {
317
+		return nil, err
318
+	}
319
+
320
+	for _, nw := range a.getPredefineds(as) {
321
+		if v != getAddressVersion(nw.IP) {
322
+			continue
323
+		}
324
+		aSpace.Lock()
325
+		_, ok := aSpace.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}]
326
+		aSpace.Unlock()
327
+		if ok {
328
+			continue
329
+		}
330
+
331
+		if !aSpace.contains(as, nw) {
332
+			if as == localAddressSpace {
333
+				// Check if nw overlap with system routes, name servers
334
+				if _, err := ipamutils.FindAvailableNetwork([]*net.IPNet{nw}); err == nil {
335
+					return nw, nil
336
+				}
337
+				continue
338
+			}
339
+			return nw, nil
340
+		}
341
+	}
342
+
343
+	return nil, types.NotFoundErrorf("could not find an available predefined network")
344
+}
345
+
346
+// RequestAddress returns an address from the specified pool ID
347
+func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
348
+	log.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
349
+	k := SubnetKey{}
350
+	if err := k.FromString(poolID); err != nil {
351
+		return nil, nil, types.BadRequestErrorf("invalid pool id: %s", poolID)
352
+	}
353
+
354
+	if err := a.refresh(k.AddressSpace); err != nil {
355
+		return nil, nil, err
356
+	}
357
+
358
+	aSpace, err := a.getAddrSpace(k.AddressSpace)
359
+	if err != nil {
360
+		return nil, nil, err
361
+	}
362
+
363
+	aSpace.Lock()
364
+	p, ok := aSpace.subnets[k]
365
+	if !ok {
366
+		aSpace.Unlock()
367
+		return nil, nil, types.NotFoundErrorf("cannot find address pool for poolID:%s", poolID)
368
+	}
369
+
370
+	if prefAddress != nil && !p.Pool.Contains(prefAddress) {
371
+		aSpace.Unlock()
372
+		return nil, nil, ipamapi.ErrIPOutOfRange
373
+	}
374
+
375
+	c := p
376
+	for c.Range != nil {
377
+		k = c.ParentKey
378
+		c, ok = aSpace.subnets[k]
379
+	}
380
+	aSpace.Unlock()
381
+
382
+	bm, err := a.retrieveBitmask(k, c.Pool)
383
+	if err != nil {
384
+		return nil, nil, fmt.Errorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v",
385
+			k.String(), prefAddress, poolID, err)
386
+	}
387
+	ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range)
388
+	if err != nil {
389
+		return nil, nil, err
390
+	}
391
+
392
+	return &net.IPNet{IP: ip, Mask: p.Pool.Mask}, nil, nil
393
+}
394
+
395
+// ReleaseAddress releases the address from the specified pool ID
396
+func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
397
+	log.Debugf("ReleaseAddress(%s, %v)", poolID, address)
398
+	k := SubnetKey{}
399
+	if err := k.FromString(poolID); err != nil {
400
+		return types.BadRequestErrorf("invalid pool id: %s", poolID)
401
+	}
402
+
403
+	if err := a.refresh(k.AddressSpace); err != nil {
404
+		return err
405
+	}
406
+
407
+	aSpace, err := a.getAddrSpace(k.AddressSpace)
408
+	if err != nil {
409
+		return err
410
+	}
411
+
412
+	aSpace.Lock()
413
+	p, ok := aSpace.subnets[k]
414
+	if !ok {
415
+		aSpace.Unlock()
416
+		return ipamapi.ErrBadPool
417
+	}
418
+
419
+	if address == nil {
420
+		aSpace.Unlock()
421
+		return ipamapi.ErrInvalidRequest
422
+	}
423
+
424
+	if !p.Pool.Contains(address) {
425
+		aSpace.Unlock()
426
+		return ipamapi.ErrIPOutOfRange
427
+	}
428
+
429
+	c := p
430
+	for c.Range != nil {
431
+		k = c.ParentKey
432
+		c = aSpace.subnets[k]
433
+	}
434
+	aSpace.Unlock()
435
+
436
+	mask := p.Pool.Mask
437
+	if p.Range != nil {
438
+		mask = p.Range.Sub.Mask
439
+	}
440
+
441
+	h, err := types.GetHostPartIP(address, mask)
442
+	if err != nil {
443
+		return fmt.Errorf("failed to release address %s: %v", address.String(), err)
444
+	}
445
+
446
+	bm, err := a.retrieveBitmask(k, c.Pool)
447
+	if err != nil {
448
+		return fmt.Errorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v",
449
+			k.String(), address, poolID, err)
450
+	}
451
+
452
+	return bm.Unset(ipToUint64(h))
453
+}
454
+
455
+func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange) (net.IP, error) {
456
+	var (
457
+		ordinal uint64
458
+		err     error
459
+		base    *net.IPNet
460
+	)
461
+
462
+	base = types.GetIPNetCopy(nw)
463
+
464
+	if bitmask.Unselected() <= 0 {
465
+		return nil, ipamapi.ErrNoAvailableIPs
466
+	}
467
+	if ipr == nil && prefAddress == nil {
468
+		ordinal, err = bitmask.SetAny()
469
+	} else if prefAddress != nil {
470
+		hostPart, e := types.GetHostPartIP(prefAddress, base.Mask)
471
+		if e != nil {
472
+			return nil, fmt.Errorf("failed to allocate preferred address %s: %v", prefAddress.String(), e)
473
+		}
474
+		ordinal = ipToUint64(types.GetMinimalIP(hostPart))
475
+		err = bitmask.Set(ordinal)
476
+	} else {
477
+		base.IP = ipr.Sub.IP
478
+		ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End)
479
+	}
480
+	if err != nil {
481
+		return nil, ipamapi.ErrNoAvailableIPs
482
+	}
483
+
484
+	// Convert IP ordinal for this subnet into IP address
485
+	return generateAddress(ordinal, base), nil
486
+}
487
+
488
+// DumpDatabase dumps the internal info
489
+func (a *Allocator) DumpDatabase() string {
490
+	a.Lock()
491
+	defer a.Unlock()
492
+
493
+	var s string
494
+	for as, aSpace := range a.addrSpaces {
495
+		s = fmt.Sprintf("\n\n%s Config", as)
496
+		aSpace.Lock()
497
+		for k, config := range aSpace.subnets {
498
+			s = fmt.Sprintf("%s%s", s, fmt.Sprintf("\n%v: %v", k, config))
499
+		}
500
+		aSpace.Unlock()
501
+	}
502
+
503
+	s = fmt.Sprintf("%s\n\nBitmasks", s)
504
+	for k, bm := range a.addresses {
505
+		s = fmt.Sprintf("%s%s", s, fmt.Sprintf("\n\t%s: %s\n\t%d", k, bm, bm.Unselected()))
506
+	}
507
+
508
+	return s
509
+}
0 510
new file mode 100644
... ...
@@ -0,0 +1,131 @@
0
+package ipam
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+
6
+	log "github.com/Sirupsen/logrus"
7
+	"github.com/docker/libnetwork/datastore"
8
+	"github.com/docker/libnetwork/types"
9
+)
10
+
11
+// Key provides the Key to be used in KV Store
12
+func (aSpace *addrSpace) Key() []string {
13
+	aSpace.Lock()
14
+	defer aSpace.Unlock()
15
+	return []string{aSpace.id}
16
+}
17
+
18
+// KeyPrefix returns the immediate parent key that can be used for tree walk
19
+func (aSpace *addrSpace) KeyPrefix() []string {
20
+	aSpace.Lock()
21
+	defer aSpace.Unlock()
22
+	return []string{dsConfigKey}
23
+}
24
+
25
+// Value marshals the data to be stored in the KV store
26
+func (aSpace *addrSpace) Value() []byte {
27
+	b, err := json.Marshal(aSpace)
28
+	if err != nil {
29
+		log.Warnf("Failed to marshal ipam configured pools: %v", err)
30
+		return nil
31
+	}
32
+	return b
33
+}
34
+
35
+// SetValue unmarshalls the data from the KV store.
36
+func (aSpace *addrSpace) SetValue(value []byte) error {
37
+	rc := &addrSpace{subnets: make(map[SubnetKey]*PoolData)}
38
+	if err := json.Unmarshal(value, rc); err != nil {
39
+		return err
40
+	}
41
+	aSpace.subnets = rc.subnets
42
+	return nil
43
+}
44
+
45
+// Index returns the latest DB Index as seen by this object
46
+func (aSpace *addrSpace) Index() uint64 {
47
+	aSpace.Lock()
48
+	defer aSpace.Unlock()
49
+	return aSpace.dbIndex
50
+}
51
+
52
+// SetIndex method allows the datastore to store the latest DB Index into this object
53
+func (aSpace *addrSpace) SetIndex(index uint64) {
54
+	aSpace.Lock()
55
+	aSpace.dbIndex = index
56
+	aSpace.dbExists = true
57
+	aSpace.Unlock()
58
+}
59
+
60
+// Exists method is true if this object has been stored in the DB.
61
+func (aSpace *addrSpace) Exists() bool {
62
+	aSpace.Lock()
63
+	defer aSpace.Unlock()
64
+	return aSpace.dbExists
65
+}
66
+
67
+// Skip provides a way for a KV Object to avoid persisting it in the KV Store
68
+func (aSpace *addrSpace) Skip() bool {
69
+	return false
70
+}
71
+
72
+func (a *Allocator) getStore(as string) datastore.DataStore {
73
+	a.Lock()
74
+	defer a.Unlock()
75
+
76
+	if aSpace, ok := a.addrSpaces[as]; ok {
77
+		return aSpace.ds
78
+	}
79
+
80
+	return nil
81
+}
82
+
83
+func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
84
+	store := a.getStore(as)
85
+	if store == nil {
86
+		return nil, fmt.Errorf("store for address space %s not found", as)
87
+	}
88
+
89
+	pc := &addrSpace{id: dsConfigKey + "/" + as, ds: store, alloc: a}
90
+	if err := store.GetObject(datastore.Key(pc.Key()...), pc); err != nil {
91
+		if err == datastore.ErrKeyNotFound {
92
+			return nil, nil
93
+		}
94
+
95
+		return nil, fmt.Errorf("could not get pools config from store: %v", err)
96
+	}
97
+
98
+	return pc, nil
99
+}
100
+
101
+func (a *Allocator) writeToStore(aSpace *addrSpace) error {
102
+	store := aSpace.store()
103
+	if store == nil {
104
+		return fmt.Errorf("invalid store while trying to write %s address space", aSpace.DataScope())
105
+	}
106
+
107
+	err := store.PutObjectAtomic(aSpace)
108
+	if err == datastore.ErrKeyModified {
109
+		return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err)
110
+	}
111
+
112
+	return err
113
+}
114
+
115
+func (a *Allocator) deleteFromStore(aSpace *addrSpace) error {
116
+	store := aSpace.store()
117
+	if store == nil {
118
+		return fmt.Errorf("invalid store while trying to delete %s address space", aSpace.DataScope())
119
+	}
120
+
121
+	return store.DeleteObjectAtomic(aSpace)
122
+}
123
+
124
+// DataScope method returns the storage scope of the datastore
125
+func (aSpace *addrSpace) DataScope() string {
126
+	aSpace.Lock()
127
+	defer aSpace.Unlock()
128
+
129
+	return aSpace.scope
130
+}
0 131
new file mode 100644
... ...
@@ -0,0 +1,359 @@
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
+// addrSpace contains the pool configurations for the address space
30
+type addrSpace struct {
31
+	subnets  map[SubnetKey]*PoolData
32
+	dbIndex  uint64
33
+	dbExists bool
34
+	id       string
35
+	scope    string
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 uint64
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 = uint64(m["Start"].(float64))
74
+	r.End = uint64(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 addrSpace object
156
+func (aSpace *addrSpace) MarshalJSON() ([]byte, error) {
157
+	aSpace.Lock()
158
+	defer aSpace.Unlock()
159
+
160
+	m := map[string]interface{}{
161
+		"Scope": string(aSpace.scope),
162
+	}
163
+
164
+	if aSpace.subnets != nil {
165
+		s := map[string]*PoolData{}
166
+		for k, v := range aSpace.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 addrSpace object
176
+func (aSpace *addrSpace) UnmarshalJSON(data []byte) error {
177
+	aSpace.Lock()
178
+	defer aSpace.Unlock()
179
+
180
+	m := map[string]interface{}{}
181
+	err := json.Unmarshal(data, &m)
182
+	if err != nil {
183
+		return err
184
+	}
185
+
186
+	aSpace.scope = datastore.LocalScope
187
+	s := m["Scope"].(string)
188
+	if s == string(datastore.GlobalScope) {
189
+		aSpace.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
+			aSpace.subnets[k] = v
203
+		}
204
+	}
205
+
206
+	return nil
207
+}
208
+
209
+// CopyTo deep copies the pool data to the destination pooldata
210
+func (p *PoolData) CopyTo(dstP *PoolData) error {
211
+	dstP.ParentKey = p.ParentKey
212
+	dstP.Pool = types.GetIPNetCopy(p.Pool)
213
+
214
+	if p.Range != nil {
215
+		dstP.Range = &AddressRange{}
216
+		dstP.Range.Sub = types.GetIPNetCopy(p.Range.Sub)
217
+		dstP.Range.Start = p.Range.Start
218
+		dstP.Range.End = p.Range.End
219
+	}
220
+
221
+	dstP.RefCount = p.RefCount
222
+	return nil
223
+}
224
+
225
+func (aSpace *addrSpace) CopyTo(o datastore.KVObject) error {
226
+	aSpace.Lock()
227
+	defer aSpace.Unlock()
228
+
229
+	dstAspace := o.(*addrSpace)
230
+
231
+	dstAspace.id = aSpace.id
232
+	dstAspace.ds = aSpace.ds
233
+	dstAspace.alloc = aSpace.alloc
234
+	dstAspace.scope = aSpace.scope
235
+	dstAspace.dbIndex = aSpace.dbIndex
236
+	dstAspace.dbExists = aSpace.dbExists
237
+
238
+	dstAspace.subnets = make(map[SubnetKey]*PoolData)
239
+	for k, v := range aSpace.subnets {
240
+		dstAspace.subnets[k] = &PoolData{}
241
+		v.CopyTo(dstAspace.subnets[k])
242
+	}
243
+
244
+	return nil
245
+}
246
+
247
+func (aSpace *addrSpace) New() datastore.KVObject {
248
+	aSpace.Lock()
249
+	defer aSpace.Unlock()
250
+
251
+	return &addrSpace{
252
+		id:    aSpace.id,
253
+		ds:    aSpace.ds,
254
+		alloc: aSpace.alloc,
255
+		scope: aSpace.scope,
256
+	}
257
+}
258
+
259
+func (aSpace *addrSpace) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange) (func() error, error) {
260
+	aSpace.Lock()
261
+	defer aSpace.Unlock()
262
+
263
+	// Check if already allocated
264
+	if p, ok := aSpace.subnets[k]; ok {
265
+		aSpace.incRefCount(p, 1)
266
+		return func() error { return nil }, nil
267
+	}
268
+
269
+	// If master pool, check for overlap
270
+	if ipr == nil {
271
+		if aSpace.contains(k.AddressSpace, nw) {
272
+			return nil, ipamapi.ErrPoolOverlap
273
+		}
274
+		// This is a new master pool, add it along with corresponding bitmask
275
+		aSpace.subnets[k] = &PoolData{Pool: nw, RefCount: 1}
276
+		return func() error { return aSpace.alloc.insertBitMask(k, nw) }, nil
277
+	}
278
+
279
+	// This is a new non-master pool
280
+	p := &PoolData{
281
+		ParentKey: SubnetKey{AddressSpace: k.AddressSpace, Subnet: k.Subnet},
282
+		Pool:      nw,
283
+		Range:     ipr,
284
+		RefCount:  1,
285
+	}
286
+	aSpace.subnets[k] = p
287
+
288
+	// Look for parent pool
289
+	pp, ok := aSpace.subnets[p.ParentKey]
290
+	if ok {
291
+		aSpace.incRefCount(pp, 1)
292
+		return func() error { return nil }, nil
293
+	}
294
+
295
+	// Parent pool does not exist, add it along with corresponding bitmask
296
+	aSpace.subnets[p.ParentKey] = &PoolData{Pool: nw, RefCount: 1}
297
+	return func() error { return aSpace.alloc.insertBitMask(p.ParentKey, nw) }, nil
298
+}
299
+
300
+func (aSpace *addrSpace) updatePoolDBOnRemoval(k SubnetKey) (func() error, error) {
301
+	aSpace.Lock()
302
+	defer aSpace.Unlock()
303
+
304
+	p, ok := aSpace.subnets[k]
305
+	if !ok {
306
+		return nil, ipamapi.ErrBadPool
307
+	}
308
+
309
+	aSpace.incRefCount(p, -1)
310
+
311
+	c := p
312
+	for ok {
313
+		if c.RefCount == 0 {
314
+			delete(aSpace.subnets, k)
315
+			if c.Range == nil {
316
+				return func() error {
317
+					bm, err := aSpace.alloc.retrieveBitmask(k, c.Pool)
318
+					if err != nil {
319
+						return fmt.Errorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err)
320
+					}
321
+					return bm.Destroy()
322
+				}, nil
323
+			}
324
+		}
325
+		k = c.ParentKey
326
+		c, ok = aSpace.subnets[k]
327
+	}
328
+
329
+	return func() error { return nil }, nil
330
+}
331
+
332
+func (aSpace *addrSpace) incRefCount(p *PoolData, delta int) {
333
+	c := p
334
+	ok := true
335
+	for ok {
336
+		c.RefCount += delta
337
+		c, ok = aSpace.subnets[c.ParentKey]
338
+	}
339
+}
340
+
341
+// Checks whether the passed subnet is a superset or subset of any of the subset in this config db
342
+func (aSpace *addrSpace) contains(space string, nw *net.IPNet) bool {
343
+	for k, v := range aSpace.subnets {
344
+		if space == k.AddressSpace && k.ChildSubnet == "" {
345
+			if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) {
346
+				return true
347
+			}
348
+		}
349
+	}
350
+	return false
351
+}
352
+
353
+func (aSpace *addrSpace) store() datastore.DataStore {
354
+	aSpace.Lock()
355
+	defer aSpace.Unlock()
356
+
357
+	return aSpace.ds
358
+}
0 359
new file mode 100644
... ...
@@ -0,0 +1,81 @@
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, ipToUint64(types.GetMinimalIP(lIP)), ipToUint64(types.GetMinimalIP(hIP))}, nil
36
+}
37
+
38
+// It generates the ip address in the passed subnet specified by
39
+// the passed host address ordinal
40
+func generateAddress(ordinal uint64, network *net.IPNet) net.IP {
41
+	var address [16]byte
42
+
43
+	// Get network portion of IP
44
+	if getAddressVersion(network.IP) == v4 {
45
+		copy(address[:], network.IP.To4())
46
+	} else {
47
+		copy(address[:], network.IP)
48
+	}
49
+
50
+	end := len(network.Mask)
51
+	addIntToIP(address[:end], ordinal)
52
+
53
+	return net.IP(address[:end])
54
+}
55
+
56
+func getAddressVersion(ip net.IP) ipVersion {
57
+	if ip.To4() == nil {
58
+		return v6
59
+	}
60
+	return v4
61
+}
62
+
63
+// Adds the ordinal IP to the current array
64
+// 192.168.0.0 + 53 => 192.168.53
65
+func addIntToIP(array []byte, ordinal uint64) {
66
+	for i := len(array) - 1; i >= 0; i-- {
67
+		array[i] |= (byte)(ordinal & 0xff)
68
+		ordinal >>= 8
69
+	}
70
+}
71
+
72
+// Convert an ordinal to the respective IP address
73
+func ipToUint64(ip []byte) (value uint64) {
74
+	cip := types.GetMinimalIP(ip)
75
+	for i := 0; i < len(cip); i++ {
76
+		j := len(cip) - 1 - i
77
+		value += uint64(cip[i]) << uint(j*8)
78
+	}
79
+	return value
80
+}
0 81
new file mode 100644
... ...
@@ -0,0 +1,72 @@
0
+// Package ipamapi specifies the contract the IPAM service (built-in or remote) needs to satisfy.
1
+package ipamapi
2
+
3
+import (
4
+	"errors"
5
+	"net"
6
+)
7
+
8
+/********************
9
+ * IPAM plugin types
10
+ ********************/
11
+
12
+const (
13
+	// DefaultIPAM is the name of the built-in default ipam driver
14
+	DefaultIPAM = "default"
15
+	// PluginEndpointType represents the Endpoint Type used by Plugin system
16
+	PluginEndpointType = "IpamDriver"
17
+)
18
+
19
+// Callback provides a Callback interface for registering an IPAM instance into LibNetwork
20
+type Callback interface {
21
+	// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a ipam instance
22
+	RegisterIpamDriver(name string, driver Ipam) error
23
+}
24
+
25
+/**************
26
+ * IPAM Errors
27
+ **************/
28
+
29
+// Weel-known errors returned by IPAM
30
+var (
31
+	ErrInvalidIpamService       = errors.New("Invalid IPAM Service")
32
+	ErrInvalidIpamConfigService = errors.New("Invalid IPAM Config Service")
33
+	ErrIpamNotAvailable         = errors.New("IPAM Service not available")
34
+	ErrIpamInternalError        = errors.New("IPAM Internal Error")
35
+	ErrInvalidAddressSpace      = errors.New("Invalid Address Space")
36
+	ErrInvalidPool              = errors.New("Invalid Address Pool")
37
+	ErrInvalidSubPool           = errors.New("Invalid Address SubPool")
38
+	ErrInvalidRequest           = errors.New("Invalid Request")
39
+	ErrPoolNotFound             = errors.New("Address Pool not found")
40
+	ErrOverlapPool              = errors.New("Address pool overlaps with existing pool on this address space")
41
+	ErrNoAvailablePool          = errors.New("No available pool")
42
+	ErrNoAvailableIPs           = errors.New("No available addresses on this pool")
43
+	ErrIPAlreadyAllocated       = errors.New("Address already in use")
44
+	ErrIPOutOfRange             = errors.New("Requested address is out of range")
45
+	ErrPoolOverlap              = errors.New("Pool overlaps with other one on this address space")
46
+	ErrBadPool                  = errors.New("Address space does not contain specified address pool")
47
+)
48
+
49
+/*******************************
50
+ * IPAM Service Interface
51
+ *******************************/
52
+
53
+// Ipam represents the interface the IPAM service plugins must implement
54
+// in order to allow injection/modification of IPAM database.
55
+type Ipam interface {
56
+	// GetDefaultAddressSpaces returns the default local and global address spaces for this ipam
57
+	GetDefaultAddressSpaces() (string, string, error)
58
+	// RequestPool returns an address pool along with its unique id. Address space is a mandatory field
59
+	// which denotes a set of non-overlapping pools. pool describes the pool of addresses in CIDR notation.
60
+	// subpool indicates a smaller range of addresses from the pool, for now it is specified in CIDR notation.
61
+	// Both pool and subpool are non mandatory fields. When they are not specified, Ipam driver may choose to
62
+	// return a self chosen pool for this request. In such case the v6 flag needs to be set appropriately so
63
+	// that the driver would return the expected ip version pool.
64
+	RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error)
65
+	// ReleasePool releases the address pool identified by the passed id
66
+	ReleasePool(poolID string) error
67
+	// Request address from the specified pool ID. Input options or preferred IP can be passed.
68
+	RequestAddress(string, net.IP, map[string]string) (*net.IPNet, map[string]string, error)
69
+	// Release the address from the specified pool ID
70
+	ReleaseAddress(string, net.IP) error
71
+}
0 72
new file mode 100644
... ...
@@ -0,0 +1,35 @@
0
+package builtin
1
+
2
+import (
3
+	"fmt"
4
+
5
+	"github.com/docker/libnetwork/datastore"
6
+	"github.com/docker/libnetwork/ipam"
7
+	"github.com/docker/libnetwork/ipamapi"
8
+)
9
+
10
+// Init registers the built-in ipam service with libnetwork
11
+func Init(ic ipamapi.Callback, l, g interface{}) error {
12
+	var (
13
+		ok                bool
14
+		localDs, globalDs datastore.DataStore
15
+	)
16
+
17
+	if l != nil {
18
+		if localDs, ok = l.(datastore.DataStore); !ok {
19
+			return fmt.Errorf("incorrect local datastore passed to built-in ipam init")
20
+		}
21
+	}
22
+
23
+	if g != nil {
24
+		if globalDs, ok = g.(datastore.DataStore); !ok {
25
+			return fmt.Errorf("incorrect global datastore passed to built-in ipam init")
26
+		}
27
+	}
28
+	a, err := ipam.NewAllocator(localDs, globalDs)
29
+	if err != nil {
30
+		return err
31
+	}
32
+
33
+	return ic.RegisterIpamDriver(ipamapi.DefaultIPAM, a)
34
+}
0 35
new file mode 100644
... ...
@@ -0,0 +1,77 @@
0
+// Package api defines the data structure to be used in the request/response
1
+// messages between libnetwork and the remote ipam plugin
2
+package api
3
+
4
+// Response is the basic response structure used in all responses
5
+type Response struct {
6
+	Error string
7
+}
8
+
9
+// IsSuccess returns wheter the plugin response is successful
10
+func (r *Response) IsSuccess() bool {
11
+	return r.Error == ""
12
+}
13
+
14
+// GetError returns the error from the response, if any.
15
+func (r *Response) GetError() string {
16
+	return r.Error
17
+}
18
+
19
+// GetAddressSpacesResponse is the response to the ``get default address spaces`` request message
20
+type GetAddressSpacesResponse struct {
21
+	Response
22
+	LocalDefaultAddressSpace  string
23
+	GlobalDefaultAddressSpace string
24
+}
25
+
26
+// RequestPoolRequest represents the expected data in a ``request address pool`` request message
27
+type RequestPoolRequest struct {
28
+	AddressSpace string
29
+	Pool         string
30
+	SubPool      string
31
+	Options      map[string]string
32
+	V6           bool
33
+}
34
+
35
+// RequestPoolResponse represents the response message to a ``request address pool`` request
36
+type RequestPoolResponse struct {
37
+	Response
38
+	PoolID string
39
+	Pool   string // CIDR format
40
+	Data   map[string]string
41
+}
42
+
43
+// ReleasePoolRequest represents the expected data in a ``release address pool`` request message
44
+type ReleasePoolRequest struct {
45
+	PoolID string
46
+}
47
+
48
+// ReleasePoolResponse represents the response message to a ``release address pool`` request
49
+type ReleasePoolResponse struct {
50
+	Response
51
+}
52
+
53
+// RequestAddressRequest represents the expected data in a ``request address`` request message
54
+type RequestAddressRequest struct {
55
+	PoolID  string
56
+	Address string
57
+	Options map[string]string
58
+}
59
+
60
+// RequestAddressResponse represents the expected data in the response message to a ``request address`` request
61
+type RequestAddressResponse struct {
62
+	Response
63
+	Address string // in CIDR format
64
+	Data    map[string]string
65
+}
66
+
67
+// ReleaseAddressRequest represents the expected data in a ``release address`` request message
68
+type ReleaseAddressRequest struct {
69
+	PoolID  string
70
+	Address string
71
+}
72
+
73
+// ReleaseAddressResponse represents the response message to a ``release address`` request
74
+type ReleaseAddressResponse struct {
75
+	Response
76
+}
0 77
new file mode 100644
... ...
@@ -0,0 +1,103 @@
0
+package remote
1
+
2
+import (
3
+	"fmt"
4
+	"net"
5
+
6
+	log "github.com/Sirupsen/logrus"
7
+	"github.com/docker/docker/pkg/plugins"
8
+	"github.com/docker/libnetwork/ipamapi"
9
+	"github.com/docker/libnetwork/ipams/remote/api"
10
+	"github.com/docker/libnetwork/types"
11
+)
12
+
13
+type allocator struct {
14
+	endpoint *plugins.Client
15
+	name     string
16
+}
17
+
18
+// PluginResponse is the interface for the plugin request responses
19
+type PluginResponse interface {
20
+	IsSuccess() bool
21
+	GetError() string
22
+}
23
+
24
+func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {
25
+	a := &allocator{name: name, endpoint: client}
26
+	return a
27
+}
28
+
29
+// Init registers a remote ipam when its plugin is activated
30
+func Init(cb ipamapi.Callback, l, g interface{}) error {
31
+	plugins.Handle(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
32
+		if err := cb.RegisterIpamDriver(name, newAllocator(name, client)); err != nil {
33
+			log.Errorf("error registering remote ipam %s due to %v", name, err)
34
+		}
35
+	})
36
+	return nil
37
+}
38
+
39
+func (a *allocator) call(methodName string, arg interface{}, retVal PluginResponse) error {
40
+	method := ipamapi.PluginEndpointType + "." + methodName
41
+	err := a.endpoint.Call(method, arg, retVal)
42
+	if err != nil {
43
+		return err
44
+	}
45
+	if !retVal.IsSuccess() {
46
+		return fmt.Errorf("remote: %s", retVal.GetError())
47
+	}
48
+	return nil
49
+}
50
+
51
+// GetDefaultAddressSpaces returns the local and global default address spaces
52
+func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
53
+	res := &api.GetAddressSpacesResponse{}
54
+	if err := a.call("GetDefaultAddressSpaces", nil, res); err != nil {
55
+		return "", "", err
56
+	}
57
+	return res.LocalDefaultAddressSpace, res.GlobalDefaultAddressSpace, nil
58
+}
59
+
60
+// RequestPool requests an address pool in the specified address space
61
+func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
62
+	req := &api.RequestPoolRequest{AddressSpace: addressSpace, Pool: pool, SubPool: subPool, Options: options, V6: v6}
63
+	res := &api.RequestPoolResponse{}
64
+	if err := a.call("RequestPool", req, res); err != nil {
65
+		return "", nil, nil, err
66
+	}
67
+	retPool, err := types.ParseCIDR(res.Pool)
68
+	return res.PoolID, retPool, res.Data, err
69
+}
70
+
71
+// ReleasePool removes an address pool from the specified address space
72
+func (a *allocator) ReleasePool(poolID string) error {
73
+	req := &api.ReleasePoolRequest{PoolID: poolID}
74
+	res := &api.ReleasePoolResponse{}
75
+	return a.call("ReleasePool", req, res)
76
+}
77
+
78
+// RequestAddress requests an address from the address pool
79
+func (a *allocator) RequestAddress(poolID string, address net.IP, options map[string]string) (*net.IPNet, map[string]string, error) {
80
+	var prefAddress string
81
+	if address != nil {
82
+		prefAddress = address.String()
83
+	}
84
+	req := &api.RequestAddressRequest{PoolID: poolID, Address: prefAddress, Options: options}
85
+	res := &api.RequestAddressResponse{}
86
+	if err := a.call("RequestAddress", req, res); err != nil {
87
+		return nil, nil, err
88
+	}
89
+	retAddress, err := types.ParseCIDR(res.Address)
90
+	return retAddress, res.Data, err
91
+}
92
+
93
+// ReleaseAddress releases the address from the specified address pool
94
+func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
95
+	var relAddress string
96
+	if address != nil {
97
+		relAddress = address.String()
98
+	}
99
+	req := &api.ReleaseAddressRequest{PoolID: poolID, Address: relAddress}
100
+	res := &api.ReleaseAddressResponse{}
101
+	return a.call("ReleaseAddress", req, res)
102
+}
0 103
new file mode 100644
... ...
@@ -0,0 +1,42 @@
0
+// Package ipamutils provides utililty functions for ipam management
1
+package ipamutils
2
+
3
+import "net"
4
+
5
+var (
6
+	// PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
7
+	// (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks`
8
+	PredefinedBroadNetworks []*net.IPNet
9
+	// PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
10
+	// (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
11
+	PredefinedGranularNetworks []*net.IPNet
12
+)
13
+
14
+func init() {
15
+	PredefinedBroadNetworks = initBroadPredefinedNetworks()
16
+	PredefinedGranularNetworks = initGranularPredefinedNetworks()
17
+}
18
+
19
+func initBroadPredefinedNetworks() []*net.IPNet {
20
+	pl := make([]*net.IPNet, 0, 31)
21
+	mask := []byte{255, 255, 0, 0}
22
+	for i := 17; i < 32; i++ {
23
+		pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
24
+	}
25
+	mask20 := []byte{255, 255, 240, 0}
26
+	for i := 0; i < 16; i++ {
27
+		pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i << 4), 0}, Mask: mask20})
28
+	}
29
+	return pl
30
+}
31
+
32
+func initGranularPredefinedNetworks() []*net.IPNet {
33
+	pl := make([]*net.IPNet, 0, 256*256)
34
+	mask := []byte{255, 255, 255, 0}
35
+	for i := 0; i < 256; i++ {
36
+		for j := 0; j < 256; j++ {
37
+			pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
38
+		}
39
+	}
40
+	return pl
41
+}
0 42
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+// Package ipamutils provides utililty functions for ipam management
1
+package ipamutils
2
+
3
+import (
4
+	"fmt"
5
+	"net"
6
+
7
+	"github.com/docker/libnetwork/netutils"
8
+	"github.com/docker/libnetwork/resolvconf"
9
+	"github.com/vishvananda/netlink"
10
+)
11
+
12
+// ElectInterfaceAddresses looks for an interface on the OS with the specified name
13
+// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
14
+// it chooses from a predifined list the first IPv4 address which does not conflict
15
+// with other interfaces on the system.
16
+func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
17
+	var (
18
+		v4Net  *net.IPNet
19
+		v6Nets []*net.IPNet
20
+		err    error
21
+	)
22
+
23
+	link, _ := netlink.LinkByName(name)
24
+	if link != nil {
25
+		v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
26
+		if err != nil {
27
+			return nil, nil, err
28
+		}
29
+		v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
30
+		if err != nil {
31
+			return nil, nil, err
32
+		}
33
+		if len(v4addr) > 0 {
34
+			v4Net = v4addr[0].IPNet
35
+		}
36
+		for _, nlAddr := range v6addr {
37
+			v6Nets = append(v6Nets, nlAddr.IPNet)
38
+		}
39
+	}
40
+
41
+	if link == nil || v4Net == nil {
42
+		// Choose from predifined broad networks
43
+		v4Net, err = FindAvailableNetwork(PredefinedBroadNetworks)
44
+		if err != nil {
45
+			return nil, nil, err
46
+		}
47
+	}
48
+
49
+	return v4Net, v6Nets, nil
50
+}
51
+
52
+// FindAvailableNetwork returns a network from the passed list which does not
53
+// overlap with existing interfaces in the system
54
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
55
+	// We don't check for an error here, because we don't really care if we
56
+	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
57
+	// is nil. It either doesn't exist, or we can't read it for some reason.
58
+	var nameservers []string
59
+	if rc, err := resolvconf.Get(); err == nil {
60
+		nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
61
+	}
62
+	for _, nw := range list {
63
+		if err := netutils.CheckNameserverOverlaps(nameservers, nw); err == nil {
64
+			if err := netutils.CheckRouteOverlaps(nw); err == nil {
65
+				return nw, nil
66
+			}
67
+		}
68
+	}
69
+	return nil, fmt.Errorf("no available network")
70
+}
0 71
new file mode 100644
... ...
@@ -0,0 +1,22 @@
0
+// Package ipamutils provides utililty functions for ipam management
1
+package ipamutils
2
+
3
+import (
4
+	"net"
5
+
6
+	"github.com/docker/libnetwork/types"
7
+)
8
+
9
+// ElectInterfaceAddresses looks for an interface on the OS with the specified name
10
+// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
11
+// it chooses from a predifined list the first IPv4 address which does not conflict
12
+// with other interfaces on the system.
13
+func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
14
+	return nil, nil, types.NotImplementedErrorf("not supported on windows")
15
+}
16
+
17
+// FindAvailableNetwork returns a network from the passed list which does not
18
+// overlap with existing interfaces in the system
19
+func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
20
+	return nil, types.NotImplementedErrorf("not supported on windows")
21
+}
... ...
@@ -1,6 +1,8 @@
1 1
 package netlabel
2 2
 
3
-import "strings"
3
+import (
4
+	"strings"
5
+)
4 6
 
5 7
 const (
6 8
 	// Prefix constant marks the reserved label space for libnetwork
... ...
@@ -9,6 +11,10 @@ const (
9 9
 	// DriverPrefix constant marks the reserved label space for libnetwork drivers
10 10
 	DriverPrefix = Prefix + ".driver"
11 11
 
12
+	// DriverPrivatePrefix constant marks the reserved label space
13
+	// for internal libnetwork drivers
14
+	DriverPrivatePrefix = DriverPrefix + ".private"
15
+
12 16
 	// GenericData constant that helps to identify an option as a Generic constant
13 17
 	GenericData = Prefix + ".generic"
14 18
 
... ...
@@ -18,38 +24,83 @@ const (
18 18
 	// MacAddress constant represents Mac Address config of a Container
19 19
 	MacAddress = Prefix + ".endpoint.macaddress"
20 20
 
21
-	// ExposedPorts constant represents exposedports of a Container
21
+	// ExposedPorts constant represents the container's Exposed Ports
22 22
 	ExposedPorts = Prefix + ".endpoint.exposedports"
23 23
 
24 24
 	//EnableIPv6 constant represents enabling IPV6 at network level
25 25
 	EnableIPv6 = Prefix + ".enable_ipv6"
26 26
 
27
-	// KVProvider constant represents the KV provider backend
28
-	KVProvider = DriverPrefix + ".kv_provider"
29
-
30
-	// KVProviderURL constant represents the KV provider URL
31
-	KVProviderURL = DriverPrefix + ".kv_provider_url"
32
-
33
-	// KVProviderConfig constant represents the KV provider Config
34
-	KVProviderConfig = DriverPrefix + ".kv_provider_config"
27
+	// DriverMTU constant represents the MTU size for the network driver
28
+	DriverMTU = DriverPrefix + ".mtu"
35 29
 
36 30
 	// OverlayBindInterface constant represents overlay driver bind interface
37 31
 	OverlayBindInterface = DriverPrefix + ".overlay.bind_interface"
38 32
 
39 33
 	// OverlayNeighborIP constant represents overlay driver neighbor IP
40 34
 	OverlayNeighborIP = DriverPrefix + ".overlay.neighbor_ip"
35
+
36
+	// Gateway represents the gateway for the network
37
+	Gateway = Prefix + ".gateway"
41 38
 )
42 39
 
43
-// Key extracts the key portion of the label
44
-func Key(label string) string {
45
-	kv := strings.SplitN(label, "=", 2)
40
+var (
41
+	// GlobalKVProvider constant represents the KV provider backend
42
+	GlobalKVProvider = MakeKVProvider("global")
43
+
44
+	// GlobalKVProviderURL constant represents the KV provider URL
45
+	GlobalKVProviderURL = MakeKVProviderURL("global")
46
+
47
+	// GlobalKVProviderConfig constant represents the KV provider Config
48
+	GlobalKVProviderConfig = MakeKVProviderConfig("global")
49
+
50
+	// LocalKVProvider constant represents the KV provider backend
51
+	LocalKVProvider = MakeKVProvider("local")
52
+
53
+	// LocalKVProviderURL constant represents the KV provider URL
54
+	LocalKVProviderURL = MakeKVProviderURL("local")
46 55
 
47
-	return kv[0]
56
+	// LocalKVProviderConfig constant represents the KV provider Config
57
+	LocalKVProviderConfig = MakeKVProviderConfig("local")
58
+)
59
+
60
+// MakeKVProvider returns the kvprovider label for the scope
61
+func MakeKVProvider(scope string) string {
62
+	return DriverPrivatePrefix + scope + "kv_provider"
63
+}
64
+
65
+// MakeKVProviderURL returns the kvprovider url label for the scope
66
+func MakeKVProviderURL(scope string) string {
67
+	return DriverPrivatePrefix + scope + "kv_provider_url"
68
+}
69
+
70
+// MakeKVProviderConfig returns the kvprovider config label for the scope
71
+func MakeKVProviderConfig(scope string) string {
72
+	return DriverPrivatePrefix + scope + "kv_provider_config"
73
+}
74
+
75
+// Key extracts the key portion of the label
76
+func Key(label string) (key string) {
77
+	if kv := strings.SplitN(label, "=", 2); len(kv) > 0 {
78
+		key = kv[0]
79
+	}
80
+	return
48 81
 }
49 82
 
50 83
 // Value extracts the value portion of the label
51
-func Value(label string) string {
52
-	kv := strings.SplitN(label, "=", 2)
84
+func Value(label string) (value string) {
85
+	if kv := strings.SplitN(label, "=", 2); len(kv) > 1 {
86
+		value = kv[1]
87
+	}
88
+	return
89
+}
53 90
 
54
-	return kv[1]
91
+// KeyValue decomposes the label in the (key,value) pair
92
+func KeyValue(label string) (key string, value string) {
93
+	if kv := strings.SplitN(label, "=", 2); len(kv) > 0 {
94
+		key = kv[0]
95
+		if len(kv) > 1 {
96
+			value = kv[1]
97
+		}
98
+	}
99
+	return
55 100
 }
... ...
@@ -2,7 +2,9 @@ package libnetwork
2 2
 
3 3
 import (
4 4
 	"encoding/json"
5
+	"fmt"
5 6
 	"net"
7
+	"strconv"
6 8
 	"sync"
7 9
 
8 10
 	log "github.com/Sirupsen/logrus"
... ...
@@ -11,6 +13,7 @@ import (
11 11
 	"github.com/docker/libnetwork/datastore"
12 12
 	"github.com/docker/libnetwork/driverapi"
13 13
 	"github.com/docker/libnetwork/etchosts"
14
+	"github.com/docker/libnetwork/ipamapi"
14 15
 	"github.com/docker/libnetwork/netlabel"
15 16
 	"github.com/docker/libnetwork/options"
16 17
 	"github.com/docker/libnetwork/types"
... ...
@@ -47,6 +50,16 @@ type Network interface {
47 47
 
48 48
 	// EndpointByID returns the Endpoint which has the passed id. If not found, the error ErrNoSuchEndpoint is returned.
49 49
 	EndpointByID(id string) (Endpoint, error)
50
+
51
+	// Return certain operational data belonging to this network
52
+	Info() NetworkInfo
53
+}
54
+
55
+// NetworkInfo returns some configuration and operational information about the network
56
+type NetworkInfo interface {
57
+	IpamConfig() (string, []*IpamConf, []*IpamConf)
58
+	Labels() map[string]string
59
+	Scope() string
50 60
 }
51 61
 
52 62
 // EndpointWalker is a client provided function which will be used to walk the Endpoints.
... ...
@@ -55,22 +68,98 @@ type EndpointWalker func(ep Endpoint) bool
55 55
 
56 56
 type svcMap map[string]net.IP
57 57
 
58
+// IpamConf contains all the ipam related configurations for a network
59
+type IpamConf struct {
60
+	// The master address pool for containers and network interfaces
61
+	PreferredPool string
62
+	// A subset of the master pool. If specified,
63
+	// this becomes the container pool
64
+	SubPool string
65
+	// Input options for IPAM Driver (optional)
66
+	Options map[string]string
67
+	// Preferred Network Gateway address (optional)
68
+	Gateway string
69
+	// Auxiliary addresses for network driver. Must be within the master pool.
70
+	// libnetwork will reserve them if they fall into the container pool
71
+	AuxAddresses map[string]string
72
+}
73
+
74
+// Validate checks whether the configuration is valid
75
+func (c *IpamConf) Validate() error {
76
+	if c.Gateway != "" && nil == net.ParseIP(c.Gateway) {
77
+		return types.BadRequestErrorf("invalid gateway address %s in Ipam configuration", c.Gateway)
78
+	}
79
+	return nil
80
+}
81
+
82
+// IpamInfo contains all the ipam related operational info for a network
83
+type IpamInfo struct {
84
+	PoolID string
85
+	Meta   map[string]string
86
+	driverapi.IPAMData
87
+}
88
+
89
+// MarshalJSON encodes IpamInfo into json message
90
+func (i *IpamInfo) MarshalJSON() ([]byte, error) {
91
+	m := map[string]interface{}{
92
+		"PoolID": i.PoolID,
93
+	}
94
+	v, err := json.Marshal(&i.IPAMData)
95
+	if err != nil {
96
+		return nil, err
97
+	}
98
+	m["IPAMData"] = string(v)
99
+
100
+	if i.Meta != nil {
101
+		m["Meta"] = i.Meta
102
+	}
103
+	return json.Marshal(m)
104
+}
105
+
106
+// UnmarshalJSON decodes json message into PoolData
107
+func (i *IpamInfo) UnmarshalJSON(data []byte) error {
108
+	var (
109
+		m   map[string]interface{}
110
+		err error
111
+	)
112
+	if err = json.Unmarshal(data, &m); err != nil {
113
+		return err
114
+	}
115
+	i.PoolID = m["PoolID"].(string)
116
+	if v, ok := m["Meta"]; ok {
117
+		b, _ := json.Marshal(v)
118
+		if err = json.Unmarshal(b, &i.Meta); err != nil {
119
+			return err
120
+		}
121
+	}
122
+	if v, ok := m["IPAMData"]; ok {
123
+		if err = json.Unmarshal([]byte(v.(string)), &i.IPAMData); err != nil {
124
+			return err
125
+		}
126
+	}
127
+	return nil
128
+}
129
+
58 130
 type network struct {
59
-	ctrlr       *controller
60
-	name        string
61
-	networkType string
62
-	id          string
63
-	driver      driverapi.Driver
64
-	enableIPv6  bool
65
-	endpointCnt uint64
66
-	endpoints   endpointTable
67
-	generic     options.Generic
68
-	dbIndex     uint64
69
-	svcRecords  svcMap
70
-	dbExists    bool
71
-	persist     bool
72
-	stopWatchCh chan struct{}
73
-	dataScope   datastore.DataScope
131
+	ctrlr        *controller
132
+	name         string
133
+	networkType  string
134
+	id           string
135
+	ipamType     string
136
+	addrSpace    string
137
+	ipamV4Config []*IpamConf
138
+	ipamV6Config []*IpamConf
139
+	ipamV4Info   []*IpamInfo
140
+	ipamV6Info   []*IpamInfo
141
+	enableIPv6   bool
142
+	epCnt        *endpointCnt
143
+	generic      options.Generic
144
+	dbIndex      uint64
145
+	svcRecords   svcMap
146
+	dbExists     bool
147
+	persist      bool
148
+	stopWatchCh  chan struct{}
149
+	drvOnce      *sync.Once
74 150
 	sync.Mutex
75 151
 }
76 152
 
... ...
@@ -92,11 +181,7 @@ func (n *network) Type() string {
92 92
 	n.Lock()
93 93
 	defer n.Unlock()
94 94
 
95
-	if n.driver == nil {
96
-		return ""
97
-	}
98
-
99
-	return n.driver.Type()
95
+	return n.networkType
100 96
 }
101 97
 
102 98
 func (n *network) Key() []string {
... ...
@@ -148,28 +233,116 @@ func (n *network) Skip() bool {
148 148
 	return !n.persist
149 149
 }
150 150
 
151
-func (n *network) DataScope() datastore.DataScope {
151
+func (n *network) New() datastore.KVObject {
152 152
 	n.Lock()
153 153
 	defer n.Unlock()
154
-	return n.dataScope
154
+
155
+	return &network{
156
+		ctrlr:   n.ctrlr,
157
+		drvOnce: &sync.Once{},
158
+	}
155 159
 }
156 160
 
157
-func (n *network) EndpointCnt() uint64 {
161
+// CopyTo deep copies to the destination IpamConfig
162
+func (c *IpamConf) CopyTo(dstC *IpamConf) error {
163
+	dstC.PreferredPool = c.PreferredPool
164
+	dstC.SubPool = c.SubPool
165
+	dstC.Gateway = c.Gateway
166
+	if c.Options != nil {
167
+		dstC.Options = make(map[string]string, len(c.Options))
168
+		for k, v := range c.Options {
169
+			dstC.Options[k] = v
170
+		}
171
+	}
172
+	if c.AuxAddresses != nil {
173
+		dstC.AuxAddresses = make(map[string]string, len(c.AuxAddresses))
174
+		for k, v := range c.AuxAddresses {
175
+			dstC.AuxAddresses[k] = v
176
+		}
177
+	}
178
+	return nil
179
+}
180
+
181
+// CopyTo deep copies to the destination IpamInfo
182
+func (i *IpamInfo) CopyTo(dstI *IpamInfo) error {
183
+	dstI.PoolID = i.PoolID
184
+	if i.Meta != nil {
185
+		dstI.Meta = make(map[string]string)
186
+		for k, v := range i.Meta {
187
+			dstI.Meta[k] = v
188
+		}
189
+	}
190
+
191
+	dstI.AddressSpace = i.AddressSpace
192
+	dstI.Pool = types.GetIPNetCopy(i.Pool)
193
+	dstI.Gateway = types.GetIPNetCopy(i.Gateway)
194
+
195
+	if i.AuxAddresses != nil {
196
+		dstI.AuxAddresses = make(map[string]*net.IPNet)
197
+		for k, v := range i.AuxAddresses {
198
+			dstI.AuxAddresses[k] = types.GetIPNetCopy(v)
199
+		}
200
+	}
201
+
202
+	return nil
203
+}
204
+
205
+func (n *network) CopyTo(o datastore.KVObject) error {
158 206
 	n.Lock()
159 207
 	defer n.Unlock()
160
-	return n.endpointCnt
208
+
209
+	dstN := o.(*network)
210
+	dstN.name = n.name
211
+	dstN.id = n.id
212
+	dstN.networkType = n.networkType
213
+	dstN.ipamType = n.ipamType
214
+	dstN.enableIPv6 = n.enableIPv6
215
+	dstN.persist = n.persist
216
+	dstN.dbIndex = n.dbIndex
217
+	dstN.dbExists = n.dbExists
218
+	dstN.drvOnce = n.drvOnce
219
+
220
+	for _, v4conf := range n.ipamV4Config {
221
+		dstV4Conf := &IpamConf{}
222
+		v4conf.CopyTo(dstV4Conf)
223
+		dstN.ipamV4Config = append(dstN.ipamV4Config, dstV4Conf)
224
+	}
225
+
226
+	for _, v4info := range n.ipamV4Info {
227
+		dstV4Info := &IpamInfo{}
228
+		v4info.CopyTo(dstV4Info)
229
+		dstN.ipamV4Info = append(dstN.ipamV4Info, dstV4Info)
230
+	}
231
+
232
+	for _, v6conf := range n.ipamV6Config {
233
+		dstV6Conf := &IpamConf{}
234
+		v6conf.CopyTo(dstV6Conf)
235
+		dstN.ipamV6Config = append(dstN.ipamV6Config, dstV6Conf)
236
+	}
237
+
238
+	for _, v6info := range n.ipamV6Info {
239
+		dstV6Info := &IpamInfo{}
240
+		v6info.CopyTo(dstV6Info)
241
+		dstN.ipamV6Info = append(dstN.ipamV6Info, dstV6Info)
242
+	}
243
+
244
+	dstN.generic = options.Generic{}
245
+	for k, v := range n.generic {
246
+		dstN.generic[k] = v
247
+	}
248
+
249
+	return nil
161 250
 }
162 251
 
163
-func (n *network) IncEndpointCnt() {
164
-	n.Lock()
165
-	n.endpointCnt++
166
-	n.Unlock()
252
+func (n *network) DataScope() string {
253
+	return n.driverScope()
167 254
 }
168 255
 
169
-func (n *network) DecEndpointCnt() {
256
+func (n *network) getEpCnt() *endpointCnt {
170 257
 	n.Lock()
171
-	n.endpointCnt--
172
-	n.Unlock()
258
+	defer n.Unlock()
259
+
260
+	return n.epCnt
173 261
 }
174 262
 
175 263
 // TODO : Can be made much more generic with the help of reflection (but has some golang limitations)
... ...
@@ -178,10 +351,41 @@ func (n *network) MarshalJSON() ([]byte, error) {
178 178
 	netMap["name"] = n.name
179 179
 	netMap["id"] = n.id
180 180
 	netMap["networkType"] = n.networkType
181
-	netMap["endpointCnt"] = n.endpointCnt
181
+	netMap["ipamType"] = n.ipamType
182
+	netMap["addrSpace"] = n.addrSpace
182 183
 	netMap["enableIPv6"] = n.enableIPv6
183
-	netMap["generic"] = n.generic
184
+	if n.generic != nil {
185
+		netMap["generic"] = n.generic
186
+	}
184 187
 	netMap["persist"] = n.persist
188
+	if len(n.ipamV4Config) > 0 {
189
+		ics, err := json.Marshal(n.ipamV4Config)
190
+		if err != nil {
191
+			return nil, err
192
+		}
193
+		netMap["ipamV4Config"] = string(ics)
194
+	}
195
+	if len(n.ipamV4Info) > 0 {
196
+		iis, err := json.Marshal(n.ipamV4Info)
197
+		if err != nil {
198
+			return nil, err
199
+		}
200
+		netMap["ipamV4Info"] = string(iis)
201
+	}
202
+	if len(n.ipamV6Config) > 0 {
203
+		ics, err := json.Marshal(n.ipamV6Config)
204
+		if err != nil {
205
+			return nil, err
206
+		}
207
+		netMap["ipamV6Config"] = string(ics)
208
+	}
209
+	if len(n.ipamV6Info) > 0 {
210
+		iis, err := json.Marshal(n.ipamV6Info)
211
+		if err != nil {
212
+			return nil, err
213
+		}
214
+		netMap["ipamV6Info"] = string(iis)
215
+	}
185 216
 	return json.Marshal(netMap)
186 217
 }
187 218
 
... ...
@@ -194,13 +398,53 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
194 194
 	n.name = netMap["name"].(string)
195 195
 	n.id = netMap["id"].(string)
196 196
 	n.networkType = netMap["networkType"].(string)
197
-	n.endpointCnt = uint64(netMap["endpointCnt"].(float64))
198 197
 	n.enableIPv6 = netMap["enableIPv6"].(bool)
199
-	if netMap["generic"] != nil {
200
-		n.generic = netMap["generic"].(map[string]interface{})
198
+
199
+	if v, ok := netMap["generic"]; ok {
200
+		n.generic = v.(map[string]interface{})
201
+		// Restore labels in their map[string]string form
202
+		if v, ok := n.generic[netlabel.GenericData]; ok {
203
+			var lmap map[string]string
204
+			ba, err := json.Marshal(v)
205
+			if err != nil {
206
+				return err
207
+			}
208
+			if err := json.Unmarshal(ba, &lmap); err != nil {
209
+				return err
210
+			}
211
+			n.generic[netlabel.GenericData] = lmap
212
+		}
213
+	}
214
+	if v, ok := netMap["persist"]; ok {
215
+		n.persist = v.(bool)
216
+	}
217
+	if v, ok := netMap["ipamType"]; ok {
218
+		n.ipamType = v.(string)
219
+	} else {
220
+		n.ipamType = ipamapi.DefaultIPAM
221
+	}
222
+	if v, ok := netMap["addrSpace"]; ok {
223
+		n.addrSpace = v.(string)
224
+	}
225
+	if v, ok := netMap["ipamV4Config"]; ok {
226
+		if err := json.Unmarshal([]byte(v.(string)), &n.ipamV4Config); err != nil {
227
+			return err
228
+		}
229
+	}
230
+	if v, ok := netMap["ipamV4Info"]; ok {
231
+		if err := json.Unmarshal([]byte(v.(string)), &n.ipamV4Info); err != nil {
232
+			return err
233
+		}
234
+	}
235
+	if v, ok := netMap["ipamV6Config"]; ok {
236
+		if err := json.Unmarshal([]byte(v.(string)), &n.ipamV6Config); err != nil {
237
+			return err
238
+		}
201 239
 	}
202
-	if netMap["persist"] != nil {
203
-		n.persist = netMap["persist"].(bool)
240
+	if v, ok := netMap["ipamV6Info"]; ok {
241
+		if err := json.Unmarshal([]byte(v.(string)), &n.ipamV6Info); err != nil {
242
+			return err
243
+		}
204 244
 	}
205 245
 	return nil
206 246
 }
... ...
@@ -228,6 +472,39 @@ func NetworkOptionPersist(persist bool) NetworkOption {
228 228
 	}
229 229
 }
230 230
 
231
+// NetworkOptionIpam function returns an option setter for the ipam configuration for this network
232
+func NetworkOptionIpam(ipamDriver string, addrSpace string, ipV4 []*IpamConf, ipV6 []*IpamConf) NetworkOption {
233
+	return func(n *network) {
234
+		if ipamDriver != "" {
235
+			n.ipamType = ipamDriver
236
+		}
237
+		n.addrSpace = addrSpace
238
+		n.ipamV4Config = ipV4
239
+		n.ipamV6Config = ipV6
240
+	}
241
+}
242
+
243
+// NetworkOptionLabels function returns an option setter for any parameter described by a map
244
+func NetworkOptionLabels(labels map[string]string) NetworkOption {
245
+	return func(n *network) {
246
+		if n.generic == nil {
247
+			n.generic = make(map[string]interface{})
248
+		}
249
+		if labels == nil {
250
+			labels = make(map[string]string)
251
+		}
252
+		// Store the options
253
+		n.generic[netlabel.GenericData] = labels
254
+		// Decode and store the endpoint options of libnetwork interest
255
+		if val, ok := labels[netlabel.EnableIPv6]; ok {
256
+			var err error
257
+			if n.enableIPv6, err = strconv.ParseBool(val); err != nil {
258
+				log.Warnf("Failed to parse %s' value: %s (%s)", netlabel.EnableIPv6, val, err.Error())
259
+			}
260
+		}
261
+	}
262
+}
263
+
231 264
 func (n *network) processOptions(options ...NetworkOption) {
232 265
 	for _, opt := range options {
233 266
 		if opt != nil {
... ...
@@ -236,95 +513,121 @@ func (n *network) processOptions(options ...NetworkOption) {
236 236
 	}
237 237
 }
238 238
 
239
-func (n *network) Delete() error {
240
-	var err error
239
+func (n *network) driverScope() string {
240
+	c := n.getController()
241 241
 
242
-	n.Lock()
243
-	ctrlr := n.ctrlr
244
-	n.Unlock()
242
+	c.Lock()
243
+	// Check if a driver for the specified network type is available
244
+	dd, ok := c.drivers[n.networkType]
245
+	c.Unlock()
246
+
247
+	if !ok {
248
+		var err error
249
+		dd, err = c.loadDriver(n.networkType)
250
+		if err != nil {
251
+			// If driver could not be resolved simply return an empty string
252
+			return ""
253
+		}
254
+	}
255
+
256
+	return dd.capability.DataScope
257
+}
245 258
 
246
-	ctrlr.Lock()
247
-	_, ok := ctrlr.networks[n.id]
248
-	ctrlr.Unlock()
259
+func (n *network) driver() (driverapi.Driver, error) {
260
+	c := n.getController()
261
+
262
+	c.Lock()
263
+	// Check if a driver for the specified network type is available
264
+	dd, ok := c.drivers[n.networkType]
265
+	c.Unlock()
249 266
 
250 267
 	if !ok {
251
-		return &UnknownNetworkError{name: n.name, id: n.id}
268
+		var err error
269
+		dd, err = c.loadDriver(n.networkType)
270
+		if err != nil {
271
+			return nil, err
272
+		}
252 273
 	}
253 274
 
254
-	numEps := n.EndpointCnt()
275
+	return dd.driver, nil
276
+}
277
+
278
+func (n *network) Delete() error {
279
+	n.Lock()
280
+	c := n.ctrlr
281
+	name := n.name
282
+	id := n.id
283
+	n.Unlock()
284
+
285
+	n, err := c.getNetworkFromStore(id)
286
+	if err != nil {
287
+		return &UnknownNetworkError{name: name, id: id}
288
+	}
289
+
290
+	numEps := n.getEpCnt().EndpointCnt()
255 291
 	if numEps != 0 {
256 292
 		return &ActiveEndpointsError{name: n.name, id: n.id}
257 293
 	}
258 294
 
259
-	// deleteNetworkFromStore performs an atomic delete operation and the network.endpointCnt field will help
260
-	// prevent any possible race between endpoint join and network delete
261
-	if err = ctrlr.deleteFromStore(n); err != nil {
262
-		if err == datastore.ErrKeyModified {
263
-			return types.InternalErrorf("operation in progress. delete failed for network %s. Please try again.")
264
-		}
295
+	if err = n.deleteNetwork(); err != nil {
265 296
 		return err
266 297
 	}
267
-
268 298
 	defer func() {
269 299
 		if err != nil {
270
-			n.dbExists = false
271
-			if e := ctrlr.updateToStore(n); e != nil {
272
-				log.Warnf("failed to recreate network in store %s : %v", n.name, e)
300
+			if e := c.addNetwork(n); e != nil {
301
+				log.Warnf("failed to rollback deleteNetwork for network %s: %v",
302
+					n.Name(), err)
273 303
 			}
274 304
 		}
275 305
 	}()
276 306
 
277
-	if err = n.deleteNetwork(); err != nil {
278
-		return err
307
+	// deleteFromStore performs an atomic delete operation and the
308
+	// network.epCnt will help prevent any possible
309
+	// race between endpoint join and network delete
310
+	if err = n.getController().deleteFromStore(n.getEpCnt()); err != nil {
311
+		return fmt.Errorf("error deleting network endpoint count from store: %v", err)
312
+	}
313
+	if err = n.getController().deleteFromStore(n); err != nil {
314
+		return fmt.Errorf("error deleting network from store: %v", err)
279 315
 	}
280 316
 
317
+	n.ipamRelease()
318
+
281 319
 	return nil
282 320
 }
283 321
 
284 322
 func (n *network) deleteNetwork() error {
285
-	n.Lock()
286
-	id := n.id
287
-	d := n.driver
288
-	n.ctrlr.Lock()
289
-	delete(n.ctrlr.networks, id)
290
-	n.ctrlr.Unlock()
291
-	n.Unlock()
323
+	d, err := n.driver()
324
+	if err != nil {
325
+		return fmt.Errorf("failed deleting network: %v", err)
326
+	}
292 327
 
293
-	if err := d.DeleteNetwork(n.id); err != nil {
328
+	if err := d.DeleteNetwork(n.ID()); err != nil {
294 329
 		// Forbidden Errors should be honored
295 330
 		if _, ok := err.(types.ForbiddenError); ok {
296
-			n.ctrlr.Lock()
297
-			n.ctrlr.networks[n.id] = n
298
-			n.ctrlr.Unlock()
299 331
 			return err
300 332
 		}
301
-		log.Warnf("driver error deleting network %s : %v", n.name, err)
333
+
334
+		if _, ok := err.(types.MaskableError); !ok {
335
+			log.Warnf("driver error deleting network %s : %v", n.name, err)
336
+		}
302 337
 	}
303
-	n.stopWatch()
338
+
304 339
 	return nil
305 340
 }
306 341
 
307 342
 func (n *network) addEndpoint(ep *endpoint) error {
308
-	var err error
309
-	n.Lock()
310
-	n.endpoints[ep.id] = ep
311
-	d := n.driver
312
-	n.Unlock()
313
-
314
-	defer func() {
315
-		if err != nil {
316
-			n.Lock()
317
-			delete(n.endpoints, ep.id)
318
-			n.Unlock()
319
-		}
320
-	}()
343
+	d, err := n.driver()
344
+	if err != nil {
345
+		return fmt.Errorf("failed to add endpoint: %v", err)
346
+	}
321 347
 
322
-	err = d.CreateEndpoint(n.id, ep.id, ep, ep.generic)
348
+	err = d.CreateEndpoint(n.id, ep.id, ep.Interface(), ep.generic)
323 349
 	if err != nil {
324
-		return types.InternalErrorf("failed to create endpoint %s on network %s: %v", ep.Name(), n.Name(), err)
350
+		return types.InternalErrorf("failed to create endpoint %s on network %s: %v",
351
+			ep.Name(), n.Name(), err)
325 352
 	}
326 353
 
327
-	n.updateSvcRecord(ep, true)
328 354
 	return nil
329 355
 }
330 356
 
... ...
@@ -338,54 +641,69 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
338 338
 		return nil, types.ForbiddenErrorf("service endpoint with name %s already exists", name)
339 339
 	}
340 340
 
341
-	ep := &endpoint{name: name,
342
-		generic: make(map[string]interface{})}
341
+	ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}}
343 342
 	ep.id = stringid.GenerateRandomID()
343
+
344
+	// Initialize ep.network with a possibly stale copy of n. We need this to get network from
345
+	// store. But once we get it from store we will have the most uptodate copy possible.
344 346
 	ep.network = n
345
-	ep.processOptions(options...)
347
+	ep.network, err = ep.getNetworkFromStore()
348
+	if err != nil {
349
+		return nil, fmt.Errorf("failed to get network during CreateEndpoint: %v", err)
350
+	}
351
+	n = ep.network
346 352
 
347
-	n.Lock()
348
-	ctrlr := n.ctrlr
349
-	n.Unlock()
353
+	ep.processOptions(options...)
350 354
 
351
-	n.IncEndpointCnt()
352
-	if err = ctrlr.updateToStore(n); err != nil {
355
+	if err = ep.assignAddress(); err != nil {
353 356
 		return nil, err
354 357
 	}
355 358
 	defer func() {
356 359
 		if err != nil {
357
-			n.DecEndpointCnt()
358
-			if err = ctrlr.updateToStore(n); err != nil {
359
-				log.Warnf("endpoint count cleanup failed when updating network for %s : %v", name, err)
360
-			}
360
+			ep.releaseAddress()
361 361
 		}
362 362
 	}()
363
+
363 364
 	if err = n.addEndpoint(ep); err != nil {
364 365
 		return nil, err
365 366
 	}
366 367
 	defer func() {
367 368
 		if err != nil {
368
-			if e := ep.Delete(); ep != nil {
369
+			if e := ep.deleteEndpoint(); e != nil {
369 370
 				log.Warnf("cleaning up endpoint failed %s : %v", name, e)
370 371
 			}
371 372
 		}
372 373
 	}()
373 374
 
374
-	if !ep.isLocalScoped() {
375
-		if err = ctrlr.updateToStore(ep); err != nil {
376
-			return nil, err
375
+	if err = n.getController().updateToStore(ep); err != nil {
376
+		return nil, err
377
+	}
378
+	defer func() {
379
+		if err != nil {
380
+			if e := n.getController().deleteFromStore(ep); e != nil {
381
+				log.Warnf("error rolling back endpoint %s from store: %v", name, e)
382
+			}
377 383
 		}
384
+	}()
385
+
386
+	// Increment endpoint count to indicate completion of endpoint addition
387
+	if err = n.getEpCnt().IncEndpointCnt(); err != nil {
388
+		return nil, err
378 389
 	}
379 390
 
380 391
 	return ep, nil
381 392
 }
382 393
 
383 394
 func (n *network) Endpoints() []Endpoint {
384
-	n.Lock()
385
-	defer n.Unlock()
386
-	list := make([]Endpoint, 0, len(n.endpoints))
387
-	for _, e := range n.endpoints {
388
-		list = append(list, e)
395
+	var list []Endpoint
396
+
397
+	endpoints, err := n.getEndpointsFromStore()
398
+	if err != nil {
399
+		log.Error(err)
400
+	}
401
+
402
+	for _, ep := range endpoints {
403
+		list = append(list, ep)
389 404
 	}
390 405
 
391 406
 	return list
... ...
@@ -426,28 +744,32 @@ func (n *network) EndpointByID(id string) (Endpoint, error) {
426 426
 	if id == "" {
427 427
 		return nil, ErrInvalidID(id)
428 428
 	}
429
-	n.Lock()
430
-	defer n.Unlock()
431
-	if e, ok := n.endpoints[id]; ok {
432
-		return e, nil
429
+
430
+	ep, err := n.getEndpointFromStore(id)
431
+	if err != nil {
432
+		return nil, ErrNoSuchEndpoint(id)
433 433
 	}
434
-	return nil, ErrNoSuchEndpoint(id)
435
-}
436 434
 
437
-func (n *network) isGlobalScoped() bool {
438
-	return n.DataScope() == datastore.GlobalScope
435
+	return ep, nil
439 436
 }
440 437
 
441
-func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) {
438
+func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) {
439
+	c := n.getController()
440
+	sr, ok := c.svcDb[n.ID()]
441
+	if !ok {
442
+		c.svcDb[n.ID()] = svcMap{}
443
+		sr = c.svcDb[n.ID()]
444
+	}
445
+
442 446
 	n.Lock()
443 447
 	var recs []etchosts.Record
444
-	if iface := ep.Iface(); iface != nil {
448
+	if iface := ep.Iface(); iface.Address() != nil {
445 449
 		if isAdd {
446
-			n.svcRecords[ep.Name()] = iface.Address().IP
447
-			n.svcRecords[ep.Name()+"."+n.name] = iface.Address().IP
450
+			sr[ep.Name()] = iface.Address().IP
451
+			sr[ep.Name()+"."+n.name] = iface.Address().IP
448 452
 		} else {
449
-			delete(n.svcRecords, ep.Name())
450
-			delete(n.svcRecords, ep.Name()+"."+n.name)
453
+			delete(sr, ep.Name())
454
+			delete(sr, ep.Name()+"."+n.name)
451 455
 		}
452 456
 
453 457
 		recs = append(recs, etchosts.Record{
... ...
@@ -468,12 +790,11 @@ func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) {
468 468
 	}
469 469
 
470 470
 	var sbList []*sandbox
471
-	n.WalkEndpoints(func(e Endpoint) bool {
472
-		if sb, hasSandbox := e.(*endpoint).getSandbox(); hasSandbox {
471
+	for _, ep := range localEps {
472
+		if sb, hasSandbox := ep.getSandbox(); hasSandbox {
473 473
 			sbList = append(sbList, sb)
474 474
 		}
475
-		return false
476
-	})
475
+	}
477 476
 
478 477
 	for _, sb := range sbList {
479 478
 		if isAdd {
... ...
@@ -489,7 +810,9 @@ func (n *network) getSvcRecords() []etchosts.Record {
489 489
 	defer n.Unlock()
490 490
 
491 491
 	var recs []etchosts.Record
492
-	for h, ip := range n.svcRecords {
492
+	sr, _ := n.ctrlr.svcDb[n.id]
493
+
494
+	for h, ip := range sr {
493 495
 		recs = append(recs, etchosts.Record{
494 496
 			Hosts: h,
495 497
 			IP:    ip.String(),
... ...
@@ -504,3 +827,268 @@ func (n *network) getController() *controller {
504 504
 	defer n.Unlock()
505 505
 	return n.ctrlr
506 506
 }
507
+
508
+func (n *network) ipamAllocate() error {
509
+	// For now also exclude bridge from using new ipam
510
+	if n.Type() == "host" || n.Type() == "null" {
511
+		return nil
512
+	}
513
+
514
+	ipam, err := n.getController().getIpamDriver(n.ipamType)
515
+	if err != nil {
516
+		return err
517
+	}
518
+
519
+	if n.addrSpace == "" {
520
+		if n.addrSpace, err = n.deriveAddressSpace(); err != nil {
521
+			return err
522
+		}
523
+	}
524
+
525
+	err = n.ipamAllocateVersion(4, ipam)
526
+	if err != nil {
527
+		return err
528
+	}
529
+
530
+	defer func() {
531
+		if err != nil {
532
+			n.ipamReleaseVersion(4, ipam)
533
+		}
534
+	}()
535
+
536
+	return n.ipamAllocateVersion(6, ipam)
537
+}
538
+
539
+func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
540
+	var (
541
+		cfgList  *[]*IpamConf
542
+		infoList *[]*IpamInfo
543
+		err      error
544
+	)
545
+
546
+	switch ipVer {
547
+	case 4:
548
+		cfgList = &n.ipamV4Config
549
+		infoList = &n.ipamV4Info
550
+	case 6:
551
+		cfgList = &n.ipamV6Config
552
+		infoList = &n.ipamV6Info
553
+	default:
554
+		return types.InternalErrorf("incorrect ip version passed to ipam allocate: %d", ipVer)
555
+	}
556
+
557
+	if len(*cfgList) == 0 {
558
+		if ipVer == 6 {
559
+			return nil
560
+		}
561
+		*cfgList = []*IpamConf{&IpamConf{}}
562
+	}
563
+
564
+	*infoList = make([]*IpamInfo, len(*cfgList))
565
+
566
+	log.Debugf("Allocating IPv%d pools for network %s (%s)", ipVer, n.Name(), n.ID())
567
+
568
+	for i, cfg := range *cfgList {
569
+		if err = cfg.Validate(); err != nil {
570
+			return err
571
+		}
572
+		d := &IpamInfo{}
573
+		(*infoList)[i] = d
574
+
575
+		d.PoolID, d.Pool, d.Meta, err = ipam.RequestPool(n.addrSpace, cfg.PreferredPool, cfg.SubPool, cfg.Options, ipVer == 6)
576
+		if err != nil {
577
+			return err
578
+		}
579
+
580
+		defer func() {
581
+			if err != nil {
582
+				if err := ipam.ReleasePool(d.PoolID); err != nil {
583
+					log.Warnf("Failed to release address pool %s after failure to create network %s (%s)", d.PoolID, n.Name(), n.ID())
584
+				}
585
+			}
586
+		}()
587
+
588
+		if gws, ok := d.Meta[netlabel.Gateway]; ok {
589
+			if d.Gateway, err = types.ParseCIDR(gws); err != nil {
590
+				return types.BadRequestErrorf("failed to parse gateway address (%v) returned by ipam driver: %v", gws, err)
591
+			}
592
+		}
593
+
594
+		// If user requested a specific gateway, libnetwork will allocate it
595
+		// irrespective of whether ipam driver returned a gateway already.
596
+		// If none of the above is true, libnetwork will allocate one.
597
+		if cfg.Gateway != "" || d.Gateway == nil {
598
+			if d.Gateway, _, err = ipam.RequestAddress(d.PoolID, net.ParseIP(cfg.Gateway), nil); err != nil {
599
+				return types.InternalErrorf("failed to allocate gateway (%v): %v", cfg.Gateway, err)
600
+			}
601
+		}
602
+
603
+		// Auxiliary addresses must be part of the master address pool
604
+		// If they fall into the container addressable pool, libnetwork will reserve them
605
+		if cfg.AuxAddresses != nil {
606
+			var ip net.IP
607
+			d.IPAMData.AuxAddresses = make(map[string]*net.IPNet, len(cfg.AuxAddresses))
608
+			for k, v := range cfg.AuxAddresses {
609
+				if ip = net.ParseIP(v); ip == nil {
610
+					return types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name())
611
+				}
612
+				if !d.Pool.Contains(ip) {
613
+					return types.ForbiddenErrorf("auxilairy address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool)
614
+				}
615
+				// Attempt reservation in the container addressable pool, silent the error if address does not belong to that pool
616
+				if d.IPAMData.AuxAddresses[k], _, err = ipam.RequestAddress(d.PoolID, ip, nil); err != nil && err != ipamapi.ErrIPOutOfRange {
617
+					return types.InternalErrorf("failed to allocate secondary ip address (%s:%s): %v", k, v, err)
618
+				}
619
+			}
620
+		}
621
+	}
622
+
623
+	return nil
624
+}
625
+
626
+func (n *network) ipamRelease() {
627
+	// For now exclude host and null
628
+	if n.Type() == "host" || n.Type() == "null" {
629
+		return
630
+	}
631
+	ipam, err := n.getController().getIpamDriver(n.ipamType)
632
+	if err != nil {
633
+		log.Warnf("Failed to retrieve ipam driver to release address pool(s) on delete of network %s (%s): %v", n.Name(), n.ID(), err)
634
+		return
635
+	}
636
+	n.ipamReleaseVersion(4, ipam)
637
+	n.ipamReleaseVersion(6, ipam)
638
+}
639
+
640
+func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) {
641
+	var infoList []*IpamInfo
642
+
643
+	switch ipVer {
644
+	case 4:
645
+		infoList = n.ipamV4Info
646
+	case 6:
647
+		infoList = n.ipamV6Info
648
+	default:
649
+		log.Warnf("incorrect ip version passed to ipam release: %d", ipVer)
650
+		return
651
+	}
652
+
653
+	if infoList == nil {
654
+		return
655
+	}
656
+
657
+	log.Debugf("releasing IPv%d pools from network %s (%s)", ipVer, n.Name(), n.ID())
658
+
659
+	for _, d := range infoList {
660
+		if d.Gateway != nil {
661
+			if err := ipam.ReleaseAddress(d.PoolID, d.Gateway.IP); err != nil {
662
+				log.Warnf("Failed to release gateway ip address %s on delete of network %s (%s): %v", d.Gateway.IP, n.Name(), n.ID(), err)
663
+			}
664
+		}
665
+		if d.IPAMData.AuxAddresses != nil {
666
+			for k, nw := range d.IPAMData.AuxAddresses {
667
+				if d.Pool.Contains(nw.IP) {
668
+					if err := ipam.ReleaseAddress(d.PoolID, nw.IP); err != nil && err != ipamapi.ErrIPOutOfRange {
669
+						log.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err)
670
+					}
671
+				}
672
+			}
673
+		}
674
+		if err := ipam.ReleasePool(d.PoolID); err != nil {
675
+			log.Warnf("Failed to release address pool %s on delete of network %s (%s): %v", d.PoolID, n.Name(), n.ID(), err)
676
+		}
677
+	}
678
+}
679
+
680
+func (n *network) getIPInfo(ipVer int) []*IpamInfo {
681
+	var info []*IpamInfo
682
+	switch ipVer {
683
+	case 4:
684
+		info = n.ipamV4Info
685
+	case 6:
686
+		info = n.ipamV6Info
687
+	default:
688
+		return nil
689
+	}
690
+	l := make([]*IpamInfo, 0, len(info))
691
+	n.Lock()
692
+	for _, d := range info {
693
+		l = append(l, d)
694
+	}
695
+	n.Unlock()
696
+	return l
697
+}
698
+
699
+func (n *network) getIPData(ipVer int) []driverapi.IPAMData {
700
+	var info []*IpamInfo
701
+	switch ipVer {
702
+	case 4:
703
+		info = n.ipamV4Info
704
+	case 6:
705
+		info = n.ipamV6Info
706
+	default:
707
+		return nil
708
+	}
709
+	l := make([]driverapi.IPAMData, 0, len(info))
710
+	n.Lock()
711
+	for _, d := range info {
712
+		l = append(l, d.IPAMData)
713
+	}
714
+	n.Unlock()
715
+	return l
716
+}
717
+
718
+func (n *network) deriveAddressSpace() (string, error) {
719
+	c := n.getController()
720
+	c.Lock()
721
+	ipd, ok := c.ipamDrivers[n.ipamType]
722
+	c.Unlock()
723
+	if !ok {
724
+		return "", types.NotFoundErrorf("could not find ipam driver %s to get default address space", n.ipamType)
725
+	}
726
+	if n.DataScope() == datastore.GlobalScope {
727
+		return ipd.defaultGlobalAddressSpace, nil
728
+	}
729
+	return ipd.defaultLocalAddressSpace, nil
730
+}
731
+
732
+func (n *network) Info() NetworkInfo {
733
+	return n
734
+}
735
+
736
+func (n *network) Labels() map[string]string {
737
+	n.Lock()
738
+	defer n.Unlock()
739
+	if n.generic != nil {
740
+		if m, ok := n.generic[netlabel.GenericData]; ok {
741
+			return m.(map[string]string)
742
+		}
743
+	}
744
+	return map[string]string{}
745
+}
746
+
747
+func (n *network) Scope() string {
748
+	return n.driverScope()
749
+}
750
+
751
+func (n *network) IpamConfig() (string, []*IpamConf, []*IpamConf) {
752
+	n.Lock()
753
+	defer n.Unlock()
754
+
755
+	v4L := make([]*IpamConf, len(n.ipamV4Config))
756
+	v6L := make([]*IpamConf, len(n.ipamV6Config))
757
+
758
+	for i, c := range n.ipamV4Config {
759
+		cc := &IpamConf{}
760
+		c.CopyTo(cc)
761
+		v4L[i] = cc
762
+	}
763
+
764
+	for i, c := range n.ipamV6Config {
765
+		cc := &IpamConf{}
766
+		c.CopyTo(cc)
767
+		v6L[i] = cc
768
+	}
769
+
770
+	return n.ipamType, v4L, v6L
771
+}
... ...
@@ -156,7 +156,7 @@ func (i *nwIface) Remove() error {
156 156
 }
157 157
 
158 158
 // Returns the sandbox's side veth interface statistics
159
-func (i *nwIface) Statistics() (*InterfaceStatistics, error) {
159
+func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) {
160 160
 	i.Lock()
161 161
 	n := i.ns
162 162
 	i.Unlock()
... ...
@@ -165,7 +165,7 @@ func (i *nwIface) Statistics() (*InterfaceStatistics, error) {
165 165
 	path := n.path
166 166
 	n.Unlock()
167 167
 
168
-	s := &InterfaceStatistics{}
168
+	s := &types.InterfaceStatistics{}
169 169
 
170 170
 	err := nsInvoke(path, func(nsFD int) error { return nil }, func(callerFD int) error {
171 171
 		// For some reason ioutil.ReadFile(netStatsFile) reads the file in
... ...
@@ -356,7 +356,7 @@ const (
356 356
 	base         = "[ ]*%s:([ ]+[0-9]+){16}"
357 357
 )
358 358
 
359
-func scanInterfaceStats(data, ifName string, i *InterfaceStatistics) error {
359
+func scanInterfaceStats(data, ifName string, i *types.InterfaceStatistics) error {
360 360
 	var (
361 361
 		bktStr string
362 362
 		bkt    uint64
... ...
@@ -2,7 +2,6 @@
2 2
 package osl
3 3
 
4 4
 import (
5
-	"fmt"
6 5
 	"net"
7 6
 
8 7
 	"github.com/docker/libnetwork/types"
... ...
@@ -150,22 +149,5 @@ type Interface interface {
150 150
 	Remove() error
151 151
 
152 152
 	// Statistics returns the statistics for this interface
153
-	Statistics() (*InterfaceStatistics, error)
154
-}
155
-
156
-// InterfaceStatistics represents the interface's statistics
157
-type InterfaceStatistics struct {
158
-	RxBytes   uint64
159
-	RxPackets uint64
160
-	RxErrors  uint64
161
-	RxDropped uint64
162
-	TxBytes   uint64
163
-	TxPackets uint64
164
-	TxErrors  uint64
165
-	TxDropped uint64
166
-}
167
-
168
-func (is *InterfaceStatistics) String() string {
169
-	return fmt.Sprintf("\nRxBytes: %d, RxPackets: %d, RxErrors: %d, RxDropped: %d, TxBytes: %d, TxPackets: %d, TxErrors: %d, TxDropped: %d",
170
-		is.RxBytes, is.RxPackets, is.RxErrors, is.RxDropped, is.TxBytes, is.TxPackets, is.TxErrors, is.TxDropped)
153
+	Statistics() (*types.InterfaceStatistics, error)
171 154
 }
... ...
@@ -5,7 +5,7 @@ import (
5 5
 )
6 6
 
7 7
 // IPLocalhost is a regex patter for localhost IP address range.
8
-const IPLocalhost = `((127\.([0-9]{1,3}.){2}[0-9]{1,3})|(::1))`
8
+const IPLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1))`
9 9
 
10 10
 var localhostIPRegexp = regexp.MustCompile(IPLocalhost)
11 11
 
... ...
@@ -28,7 +28,7 @@ type Sandbox interface {
28 28
 	// Labels returns the sandbox's labels
29 29
 	Labels() map[string]interface{}
30 30
 	// Statistics retrieves the interfaces' statistics for the sandbox
31
-	Statistics() (map[string]*osl.InterfaceStatistics, error)
31
+	Statistics() (map[string]*types.InterfaceStatistics, error)
32 32
 	// Refresh leaves all the endpoints, resets and re-apply the options,
33 33
 	// re-joins all the endpoints without destroying the osl sandbox
34 34
 	Refresh(options ...SandboxOption) error
... ...
@@ -64,6 +64,8 @@ type sandbox struct {
64 64
 	endpoints     epHeap
65 65
 	epPriority    map[string]int
66 66
 	joinLeaveDone chan struct{}
67
+	dbIndex       uint64
68
+	dbExists      bool
67 69
 	sync.Mutex
68 70
 }
69 71
 
... ...
@@ -126,8 +128,8 @@ func (sb *sandbox) Labels() map[string]interface{} {
126 126
 	return sb.config.generic
127 127
 }
128 128
 
129
-func (sb *sandbox) Statistics() (map[string]*osl.InterfaceStatistics, error) {
130
-	m := make(map[string]*osl.InterfaceStatistics)
129
+func (sb *sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) {
130
+	m := make(map[string]*types.InterfaceStatistics)
131 131
 
132 132
 	if sb.osSbox == nil {
133 133
 		return m, nil
... ...
@@ -153,15 +155,24 @@ func (sb *sandbox) Delete() error {
153 153
 		if ep.endpointInGWNetwork() {
154 154
 			continue
155 155
 		}
156
+
156 157
 		if err := ep.Leave(sb); err != nil {
157 158
 			log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
158 159
 		}
160
+
161
+		if err := ep.Delete(); err != nil {
162
+			log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
163
+		}
159 164
 	}
160 165
 
161 166
 	if sb.osSbox != nil {
162 167
 		sb.osSbox.Destroy()
163 168
 	}
164 169
 
170
+	if err := sb.storeDelete(); err != nil {
171
+		log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err)
172
+	}
173
+
165 174
 	c.Lock()
166 175
 	delete(c.sandboxes, sb.ID())
167 176
 	c.Unlock()
... ...
@@ -247,6 +258,19 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint {
247 247
 	return eps
248 248
 }
249 249
 
250
+func (sb *sandbox) getEndpoint(id string) *endpoint {
251
+	sb.Lock()
252
+	defer sb.Unlock()
253
+
254
+	for _, ep := range sb.endpoints {
255
+		if ep.id == id {
256
+			return ep
257
+		}
258
+	}
259
+
260
+	return nil
261
+}
262
+
250 263
 func (sb *sandbox) updateGateway(ep *endpoint) error {
251 264
 	sb.Lock()
252 265
 	osSbox := sb.osSbox
... ...
@@ -283,15 +307,21 @@ func (sb *sandbox) SetKey(basePath string) error {
283 283
 	}
284 284
 
285 285
 	sb.Lock()
286
-	if sb.osSbox != nil {
287
-		sb.Unlock()
288
-		return types.ForbiddenErrorf("failed to set sandbox key : already assigned")
289
-	}
286
+	osSbox := sb.osSbox
290 287
 	sb.Unlock()
291
-	osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key())
288
+
289
+	if osSbox != nil {
290
+		// If we already have an OS sandbox, release the network resources from that
291
+		// and destroy the OS snab. We are moving into a new home further down. Note that none
292
+		// of the network resources gets destroyed during the move.
293
+		sb.releaseOSSbox()
294
+	}
295
+
296
+	osSbox, err = osl.GetSandboxForExternalKey(basePath, sb.Key())
292 297
 	if err != nil {
293 298
 		return err
294 299
 	}
300
+
295 301
 	sb.Lock()
296 302
 	sb.osSbox = osSbox
297 303
 	sb.Unlock()
... ...
@@ -311,6 +341,45 @@ func (sb *sandbox) SetKey(basePath string) error {
311 311
 	return nil
312 312
 }
313 313
 
314
+func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) {
315
+	for _, i := range osSbox.Info().Interfaces() {
316
+		// Only remove the interfaces owned by this endpoint from the sandbox.
317
+		if ep.hasInterface(i.SrcName()) {
318
+			if err := i.Remove(); err != nil {
319
+				log.Debugf("Remove interface failed: %v", err)
320
+			}
321
+		}
322
+	}
323
+
324
+	ep.Lock()
325
+	joinInfo := ep.joinInfo
326
+	ep.Unlock()
327
+
328
+	// Remove non-interface routes.
329
+	for _, r := range joinInfo.StaticRoutes {
330
+		if err := osSbox.RemoveStaticRoute(r); err != nil {
331
+			log.Debugf("Remove route failed: %v", err)
332
+		}
333
+	}
334
+}
335
+
336
+func (sb *sandbox) releaseOSSbox() {
337
+	sb.Lock()
338
+	osSbox := sb.osSbox
339
+	sb.osSbox = nil
340
+	sb.Unlock()
341
+
342
+	if osSbox == nil {
343
+		return
344
+	}
345
+
346
+	for _, ep := range sb.getConnectedEndpoints() {
347
+		releaseOSSboxResources(osSbox, ep)
348
+	}
349
+
350
+	osSbox.Destroy()
351
+}
352
+
314 353
 func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
315 354
 	sb.Lock()
316 355
 	if sb.osSbox == nil {
... ...
@@ -324,12 +393,12 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
324 324
 	i := ep.iface
325 325
 	ep.Unlock()
326 326
 
327
-	if i != nil {
327
+	if i.srcName != "" {
328 328
 		var ifaceOptions []osl.IfaceOption
329 329
 
330
-		ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(&i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes))
331
-		if i.addrv6.IP.To16() != nil {
332
-			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(&i.addrv6))
330
+		ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes))
331
+		if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
332
+			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
333 333
 		}
334 334
 
335 335
 		if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
... ...
@@ -356,33 +425,21 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
356 356
 			}
357 357
 		}
358 358
 	}
359
-	return nil
359
+	return sb.storeUpdate()
360 360
 }
361 361
 
362
-func (sb *sandbox) clearNetworkResources(ep *endpoint) error {
362
+func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
363
+	ep := sb.getEndpoint(origEp.id)
364
+	if ep == nil {
365
+		return fmt.Errorf("could not find the sandbox endpoint data for endpoint %s",
366
+			ep.name)
367
+	}
368
+
363 369
 	sb.Lock()
364 370
 	osSbox := sb.osSbox
365 371
 	sb.Unlock()
366 372
 	if osSbox != nil {
367
-		for _, i := range osSbox.Info().Interfaces() {
368
-			// Only remove the interfaces owned by this endpoint from the sandbox.
369
-			if ep.hasInterface(i.SrcName()) {
370
-				if err := i.Remove(); err != nil {
371
-					log.Debugf("Remove interface failed: %v", err)
372
-				}
373
-			}
374
-		}
375
-
376
-		ep.Lock()
377
-		joinInfo := ep.joinInfo
378
-		ep.Unlock()
379
-
380
-		// Remove non-interface routes.
381
-		for _, r := range joinInfo.StaticRoutes {
382
-			if err := osSbox.RemoveStaticRoute(r); err != nil {
383
-				log.Debugf("Remove route failed: %v", err)
384
-			}
385
-		}
373
+		releaseOSSboxResources(osSbox, ep)
386 374
 	}
387 375
 
388 376
 	sb.Lock()
... ...
@@ -423,7 +480,7 @@ func (sb *sandbox) clearNetworkResources(ep *endpoint) error {
423 423
 		sb.updateGateway(gwepAfter)
424 424
 	}
425 425
 
426
-	return nil
426
+	return sb.storeUpdate()
427 427
 }
428 428
 
429 429
 const (
... ...
@@ -837,7 +894,7 @@ func (eh epHeap) Less(i, j int) bool {
837 837
 		cjp = 0
838 838
 	}
839 839
 	if cip == cjp {
840
-		return eh[i].getNetwork().Name() < eh[j].getNetwork().Name()
840
+		return eh[i].network.Name() < eh[j].network.Name()
841 841
 	}
842 842
 
843 843
 	return cip > cjp
844 844
new file mode 100644
... ...
@@ -0,0 +1,211 @@
0
+package libnetwork
1
+
2
+import (
3
+	"container/heap"
4
+	"encoding/json"
5
+
6
+	"github.com/Sirupsen/logrus"
7
+	"github.com/docker/libnetwork/datastore"
8
+	"github.com/docker/libnetwork/osl"
9
+)
10
+
11
+const (
12
+	sandboxPrefix = "sandbox"
13
+)
14
+
15
+type epState struct {
16
+	Eid string
17
+	Nid string
18
+}
19
+
20
+type sbState struct {
21
+	ID       string
22
+	Cid      string
23
+	c        *controller
24
+	dbIndex  uint64
25
+	dbExists bool
26
+	Eps      []epState
27
+}
28
+
29
+func (sbs *sbState) Key() []string {
30
+	return []string{sandboxPrefix, sbs.ID}
31
+}
32
+
33
+func (sbs *sbState) KeyPrefix() []string {
34
+	return []string{sandboxPrefix}
35
+}
36
+
37
+func (sbs *sbState) Value() []byte {
38
+	b, err := json.Marshal(sbs)
39
+	if err != nil {
40
+		return nil
41
+	}
42
+	return b
43
+}
44
+
45
+func (sbs *sbState) SetValue(value []byte) error {
46
+	return json.Unmarshal(value, sbs)
47
+}
48
+
49
+func (sbs *sbState) Index() uint64 {
50
+	sbi, err := sbs.c.SandboxByID(sbs.ID)
51
+	if err != nil {
52
+		return sbs.dbIndex
53
+	}
54
+
55
+	sb := sbi.(*sandbox)
56
+	maxIndex := sb.dbIndex
57
+	if sbs.dbIndex > maxIndex {
58
+		maxIndex = sbs.dbIndex
59
+	}
60
+
61
+	return maxIndex
62
+}
63
+
64
+func (sbs *sbState) SetIndex(index uint64) {
65
+	sbs.dbIndex = index
66
+	sbs.dbExists = true
67
+
68
+	sbi, err := sbs.c.SandboxByID(sbs.ID)
69
+	if err != nil {
70
+		return
71
+	}
72
+
73
+	sb := sbi.(*sandbox)
74
+	sb.dbIndex = index
75
+	sb.dbExists = true
76
+}
77
+
78
+func (sbs *sbState) Exists() bool {
79
+	if sbs.dbExists {
80
+		return sbs.dbExists
81
+	}
82
+
83
+	sbi, err := sbs.c.SandboxByID(sbs.ID)
84
+	if err != nil {
85
+		return false
86
+	}
87
+
88
+	sb := sbi.(*sandbox)
89
+	return sb.dbExists
90
+}
91
+
92
+func (sbs *sbState) Skip() bool {
93
+	return false
94
+}
95
+
96
+func (sbs *sbState) New() datastore.KVObject {
97
+	return &sbState{c: sbs.c}
98
+}
99
+
100
+func (sbs *sbState) CopyTo(o datastore.KVObject) error {
101
+	dstSbs := o.(*sbState)
102
+	dstSbs.c = sbs.c
103
+	dstSbs.ID = sbs.ID
104
+	dstSbs.Cid = sbs.Cid
105
+	dstSbs.dbIndex = sbs.dbIndex
106
+	dstSbs.dbExists = sbs.dbExists
107
+
108
+	for _, eps := range sbs.Eps {
109
+		dstSbs.Eps = append(dstSbs.Eps, eps)
110
+	}
111
+
112
+	return nil
113
+}
114
+
115
+func (sbs *sbState) DataScope() string {
116
+	return datastore.LocalScope
117
+}
118
+
119
+func (sb *sandbox) storeUpdate() error {
120
+	sbs := &sbState{
121
+		c:  sb.controller,
122
+		ID: sb.id,
123
+	}
124
+
125
+	for _, ep := range sb.getConnectedEndpoints() {
126
+		eps := epState{
127
+			Nid: ep.getNetwork().ID(),
128
+			Eid: ep.ID(),
129
+		}
130
+
131
+		sbs.Eps = append(sbs.Eps, eps)
132
+	}
133
+
134
+	return sb.controller.updateToStore(sbs)
135
+}
136
+
137
+func (sb *sandbox) storeDelete() error {
138
+	sbs := &sbState{
139
+		c:        sb.controller,
140
+		ID:       sb.id,
141
+		Cid:      sb.containerID,
142
+		dbIndex:  sb.dbIndex,
143
+		dbExists: sb.dbExists,
144
+	}
145
+
146
+	return sb.controller.deleteFromStore(sbs)
147
+}
148
+
149
+func (c *controller) sandboxCleanup() {
150
+	store := c.getStore(datastore.LocalScope)
151
+	if store == nil {
152
+		logrus.Errorf("Could not find local scope store while trying to cleanup sandboxes")
153
+		return
154
+	}
155
+
156
+	kvol, err := store.List(datastore.Key(sandboxPrefix), &sbState{c: c})
157
+	if err != nil && err != datastore.ErrKeyNotFound {
158
+		logrus.Errorf("failed to get sandboxes for scope %s: %v", store.Scope(), err)
159
+		return
160
+	}
161
+
162
+	// It's normal for no sandboxes to be found. Just bail out.
163
+	if err == datastore.ErrKeyNotFound {
164
+		return
165
+	}
166
+
167
+	for _, kvo := range kvol {
168
+		sbs := kvo.(*sbState)
169
+
170
+		sb := &sandbox{
171
+			id:          sbs.ID,
172
+			controller:  sbs.c,
173
+			containerID: sbs.Cid,
174
+			endpoints:   epHeap{},
175
+			epPriority:  map[string]int{},
176
+			dbIndex:     sbs.dbIndex,
177
+			dbExists:    true,
178
+		}
179
+
180
+		sb.osSbox, err = osl.NewSandbox(sb.Key(), true)
181
+		if err != nil {
182
+			logrus.Errorf("failed to create new osl sandbox while trying to build sandbox for cleanup: %v", err)
183
+			continue
184
+		}
185
+
186
+		for _, eps := range sbs.Eps {
187
+			n, err := c.getNetworkFromStore(eps.Nid)
188
+			if err != nil {
189
+				logrus.Errorf("getNetworkFromStore for nid %s failed while trying to build sandbox for cleanup: %v", eps.Nid, err)
190
+				continue
191
+			}
192
+
193
+			ep, err := n.getEndpointFromStore(eps.Eid)
194
+			if err != nil {
195
+				logrus.Errorf("getEndpointFromStore for eid %s failed while trying to build sandbox for cleanup: %v", eps.Eid, err)
196
+				continue
197
+			}
198
+
199
+			heap.Push(&sb.endpoints, ep)
200
+		}
201
+
202
+		c.Lock()
203
+		c.sandboxes[sb.id] = sb
204
+		c.Unlock()
205
+
206
+		if err := sb.Delete(); err != nil {
207
+			logrus.Errorf("failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
208
+		}
209
+	}
210
+}
... ...
@@ -1,392 +1,366 @@
1 1
 package libnetwork
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"fmt"
6
-	"time"
7 5
 
8 6
 	log "github.com/Sirupsen/logrus"
9
-	"github.com/docker/libkv/store"
10
-	"github.com/docker/libnetwork/config"
11 7
 	"github.com/docker/libnetwork/datastore"
12 8
 )
13 9
 
14
-var (
15
-	defaultBoltTimeout      = 3 * time.Second
16
-	defaultLocalStoreConfig = config.DatastoreCfg{
17
-		Embedded: true,
18
-		Client: config.DatastoreClientCfg{
19
-			Provider: "boltdb",
20
-			Address:  defaultPrefix + "/boltdb.db",
21
-			Config: &store.Config{
22
-				Bucket:            "libnetwork",
23
-				ConnectionTimeout: defaultBoltTimeout,
24
-			},
25
-		},
26
-	}
27
-)
28
-
29
-func (c *controller) validateGlobalStoreConfig() bool {
30
-	return c.cfg != nil && c.cfg.GlobalStore.Client.Provider != "" && c.cfg.GlobalStore.Client.Address != ""
31
-}
32
-
33
-func (c *controller) initGlobalStore() error {
10
+func (c *controller) initStores() error {
34 11
 	c.Lock()
35
-	cfg := c.cfg
36
-	c.Unlock()
37
-	if !c.validateGlobalStoreConfig() {
38
-		return fmt.Errorf("globalstore initialization requires a valid configuration")
39
-	}
40
-
41
-	store, err := datastore.NewDataStore(&cfg.GlobalStore)
42
-	if err != nil {
43
-		return err
12
+	if c.cfg == nil {
13
+		c.Unlock()
14
+		return nil
44 15
 	}
45
-	c.Lock()
46
-	c.globalStore = store
16
+	scopeConfigs := c.cfg.Scopes
47 17
 	c.Unlock()
48 18
 
49
-	nws, err := c.getNetworksFromStore(true)
50
-	if err == nil {
51
-		c.processNetworkUpdate(nws, nil)
52
-	} else if err != datastore.ErrKeyNotFound {
53
-		log.Warnf("failed to read networks from globalstore during init : %v", err)
19
+	for scope, scfg := range scopeConfigs {
20
+		store, err := datastore.NewDataStore(scope, scfg)
21
+		if err != nil {
22
+			return err
23
+		}
24
+		c.Lock()
25
+		c.stores = append(c.stores, store)
26
+		c.Unlock()
54 27
 	}
55
-	return c.watchNetworks()
28
+
29
+	c.startWatch()
30
+	return nil
56 31
 }
57 32
 
58
-func (c *controller) initLocalStore() error {
59
-	c.Lock()
60
-	cfg := c.cfg
61
-	c.Unlock()
62
-	localStore, err := datastore.NewDataStore(c.getLocalStoreConfig(cfg))
63
-	if err != nil {
64
-		return err
33
+func (c *controller) closeStores() {
34
+	for _, store := range c.getStores() {
35
+		store.Close()
65 36
 	}
37
+}
38
+
39
+func (c *controller) getStore(scope string) datastore.DataStore {
66 40
 	c.Lock()
67
-	c.localStore = localStore
68
-	c.Unlock()
41
+	defer c.Unlock()
69 42
 
70
-	nws, err := c.getNetworksFromStore(false)
71
-	if err == nil {
72
-		c.processNetworkUpdate(nws, nil)
73
-	} else if err != datastore.ErrKeyNotFound {
74
-		log.Warnf("failed to read networks from localstore during init : %v", err)
43
+	for _, store := range c.stores {
44
+		if store.Scope() == scope {
45
+			return store
46
+		}
75 47
 	}
48
+
76 49
 	return nil
77 50
 }
78 51
 
79
-func (c *controller) getNetworksFromStore(global bool) ([]*store.KVPair, error) {
80
-	var cs datastore.DataStore
52
+func (c *controller) getStores() []datastore.DataStore {
81 53
 	c.Lock()
82
-	if global {
83
-		cs = c.globalStore
84
-	} else {
85
-		cs = c.localStore
54
+	defer c.Unlock()
55
+
56
+	return c.stores
57
+}
58
+
59
+func (c *controller) getNetworkFromStore(nid string) (*network, error) {
60
+	for _, store := range c.getStores() {
61
+		n := &network{id: nid, ctrlr: c}
62
+		err := store.GetObject(datastore.Key(n.Key()...), n)
63
+		if err != nil && err != datastore.ErrKeyNotFound {
64
+			return nil, fmt.Errorf("could not find network %s: %v", nid, err)
65
+		}
66
+
67
+		// Continue searching in the next store if the key is not found in this store
68
+		if err == datastore.ErrKeyNotFound {
69
+			continue
70
+		}
71
+
72
+		ec := &endpointCnt{n: n}
73
+		err = store.GetObject(datastore.Key(ec.Key()...), ec)
74
+		if err != nil {
75
+			return nil, fmt.Errorf("could not find endpoint count for network %s: %v", n.Name(), err)
76
+		}
77
+
78
+		n.epCnt = ec
79
+		return n, nil
86 80
 	}
87
-	c.Unlock()
88
-	return cs.KVStore().List(datastore.Key(datastore.NetworkKeyPrefix))
81
+
82
+	return nil, fmt.Errorf("network %s not found", nid)
89 83
 }
90 84
 
91
-func (c *controller) newNetworkFromStore(n *network) error {
92
-	n.Lock()
93
-	n.ctrlr = c
94
-	n.endpoints = endpointTable{}
95
-	n.Unlock()
85
+func (c *controller) getNetworksFromStore() ([]*network, error) {
86
+	var nl []*network
87
+
88
+	for _, store := range c.getStores() {
89
+		kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix),
90
+			&network{ctrlr: c})
91
+		if err != nil && err != datastore.ErrKeyNotFound {
92
+			return nil, fmt.Errorf("failed to get networks for scope %s: %v",
93
+				store.Scope(), err)
94
+		}
95
+
96
+		// Continue searching in the next store if no keys found in this store
97
+		if err == datastore.ErrKeyNotFound {
98
+			continue
99
+		}
100
+
101
+		for _, kvo := range kvol {
102
+			n := kvo.(*network)
103
+			n.ctrlr = c
104
+
105
+			ec := &endpointCnt{n: n}
106
+			err = store.GetObject(datastore.Key(ec.Key()...), ec)
107
+			if err != nil {
108
+				return nil, fmt.Errorf("could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
109
+			}
110
+
111
+			n.epCnt = ec
112
+			nl = append(nl, n)
113
+		}
114
+	}
96 115
 
97
-	return c.addNetwork(n)
116
+	return nl, nil
98 117
 }
99 118
 
100
-func (c *controller) newEndpointFromStore(key string, ep *endpoint) error {
101
-	ep.Lock()
102
-	n := ep.network
103
-	id := ep.id
104
-	ep.Unlock()
119
+func (n *network) getEndpointFromStore(eid string) (*endpoint, error) {
120
+	for _, store := range n.ctrlr.getStores() {
121
+		ep := &endpoint{id: eid, network: n}
122
+		err := store.GetObject(datastore.Key(ep.Key()...), ep)
123
+		if err != nil && err != datastore.ErrKeyNotFound {
124
+			return nil, fmt.Errorf("could not find endpoint %s: %v", eid, err)
125
+		}
105 126
 
106
-	_, err := n.EndpointByID(id)
107
-	if err != nil {
108
-		if _, ok := err.(ErrNoSuchEndpoint); ok {
109
-			return n.addEndpoint(ep)
127
+		// Continue searching in the next store if the key is not found in this store
128
+		if err == datastore.ErrKeyNotFound {
129
+			continue
110 130
 		}
131
+
132
+		return ep, nil
111 133
 	}
112
-	return err
134
+
135
+	return nil, fmt.Errorf("endpoint %s not found", eid)
113 136
 }
114 137
 
115
-func (c *controller) updateToStore(kvObject datastore.KV) error {
116
-	if kvObject.Skip() {
117
-		return nil
138
+func (n *network) getEndpointsFromStore() ([]*endpoint, error) {
139
+	var epl []*endpoint
140
+
141
+	tmp := endpoint{network: n}
142
+	for _, store := range n.getController().getStores() {
143
+		kvol, err := store.List(datastore.Key(tmp.KeyPrefix()...), &endpoint{network: n})
144
+		if err != nil && err != datastore.ErrKeyNotFound {
145
+			return nil,
146
+				fmt.Errorf("failed to get endpoints for network %s scope %s: %v",
147
+					n.Name(), store.Scope(), err)
148
+		}
149
+
150
+		// Continue searching in the next store if no keys found in this store
151
+		if err == datastore.ErrKeyNotFound {
152
+			continue
153
+		}
154
+
155
+		for _, kvo := range kvol {
156
+			ep := kvo.(*endpoint)
157
+			ep.network = n
158
+			epl = append(epl, ep)
159
+		}
118 160
 	}
119
-	cs := c.getDataStore(kvObject.DataScope())
161
+
162
+	return epl, nil
163
+}
164
+
165
+func (c *controller) updateToStore(kvObject datastore.KVObject) error {
166
+	cs := c.getStore(kvObject.DataScope())
120 167
 	if cs == nil {
121
-		log.Debugf("datastore not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
168
+		log.Warnf("datastore for scope %s not initialized. kv object %s is not added to the store", kvObject.DataScope(), datastore.Key(kvObject.Key()...))
122 169
 		return nil
123 170
 	}
124 171
 
125
-	return cs.PutObjectAtomic(kvObject)
172
+	if err := cs.PutObjectAtomic(kvObject); err != nil {
173
+		if err == datastore.ErrKeyModified {
174
+			return err
175
+		}
176
+		return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
177
+	}
178
+
179
+	return nil
126 180
 }
127 181
 
128
-func (c *controller) deleteFromStore(kvObject datastore.KV) error {
129
-	if kvObject.Skip() {
130
-		return nil
131
-	}
132
-	cs := c.getDataStore(kvObject.DataScope())
182
+func (c *controller) deleteFromStore(kvObject datastore.KVObject) error {
183
+	cs := c.getStore(kvObject.DataScope())
133 184
 	if cs == nil {
134
-		log.Debugf("datastore not initialized. kv object %s is not deleted from datastore", datastore.Key(kvObject.Key()...))
185
+		log.Debugf("datastore for scope %s not initialized. kv object %s is not deleted from datastore", kvObject.DataScope(), datastore.Key(kvObject.Key()...))
135 186
 		return nil
136 187
 	}
137 188
 
189
+retry:
138 190
 	if err := cs.DeleteObjectAtomic(kvObject); err != nil {
191
+		if err == datastore.ErrKeyModified {
192
+			if err := cs.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
193
+				return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
194
+			}
195
+			goto retry
196
+		}
139 197
 		return err
140 198
 	}
141 199
 
142 200
 	return nil
143 201
 }
144 202
 
145
-func (c *controller) watchNetworks() error {
146
-	if !c.validateGlobalStoreConfig() {
147
-		return nil
148
-	}
203
+type netWatch struct {
204
+	localEps  map[string]*endpoint
205
+	remoteEps map[string]*endpoint
206
+	stopCh    chan struct{}
207
+}
149 208
 
209
+func (c *controller) getLocalEps(nw *netWatch) []*endpoint {
150 210
 	c.Lock()
151
-	cs := c.globalStore
152
-	c.Unlock()
211
+	defer c.Unlock()
153 212
 
154
-	networkKey := datastore.Key(datastore.NetworkKeyPrefix)
155
-	if err := ensureKeys(networkKey, cs); err != nil {
156
-		return fmt.Errorf("failed to ensure if the network keys are valid and present in store: %v", err)
157
-	}
158
-	nwPairs, err := cs.KVStore().WatchTree(networkKey, nil)
159
-	if err != nil {
160
-		return err
213
+	var epl []*endpoint
214
+	for _, ep := range nw.localEps {
215
+		epl = append(epl, ep)
161 216
 	}
162
-	go func() {
163
-		for {
164
-			select {
165
-			case nws := <-nwPairs:
166
-				c.Lock()
167
-				tmpview := networkTable{}
168
-				lview := c.networks
169
-				c.Unlock()
170
-				for k, v := range lview {
171
-					if v.isGlobalScoped() {
172
-						tmpview[k] = v
173
-					}
174
-				}
175
-				c.processNetworkUpdate(nws, &tmpview)
176
-
177
-				// Delete processing
178
-				for k := range tmpview {
179
-					c.Lock()
180
-					existing, ok := c.networks[k]
181
-					c.Unlock()
182
-					if !ok {
183
-						continue
184
-					}
185
-					tmp := network{}
186
-					if err := c.globalStore.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
187
-						continue
188
-					}
189
-					if err := existing.deleteNetwork(); err != nil {
190
-						log.Debugf("Delete failed %s: %s", existing.name, err)
191
-					}
192
-				}
193
-			}
194
-		}
195
-	}()
196
-	return nil
217
+
218
+	return epl
197 219
 }
198 220
 
199
-func (n *network) watchEndpoints() error {
200
-	if n.Skip() || !n.ctrlr.validateGlobalStoreConfig() {
201
-		return nil
202
-	}
221
+func (c *controller) watchSvcRecord(ep *endpoint) {
222
+	c.watchCh <- ep
223
+}
203 224
 
204
-	n.Lock()
205
-	cs := n.ctrlr.globalStore
206
-	tmp := endpoint{network: n}
207
-	n.stopWatchCh = make(chan struct{})
208
-	stopCh := n.stopWatchCh
209
-	n.Unlock()
225
+func (c *controller) unWatchSvcRecord(ep *endpoint) {
226
+	c.unWatchCh <- ep
227
+}
210 228
 
211
-	endpointKey := datastore.Key(tmp.KeyPrefix()...)
212
-	if err := ensureKeys(endpointKey, cs); err != nil {
213
-		return fmt.Errorf("failed to ensure if the endpoint keys are valid and present in store: %v", err)
214
-	}
215
-	epPairs, err := cs.KVStore().WatchTree(endpointKey, stopCh)
216
-	if err != nil {
217
-		return err
218
-	}
219
-	go func() {
220
-		for {
221
-			select {
222
-			case <-stopCh:
223
-				return
224
-			case eps := <-epPairs:
225
-				n.Lock()
226
-				tmpview := endpointTable{}
227
-				lview := n.endpoints
228
-				n.Unlock()
229
-				for k, v := range lview {
230
-					if v.network.isGlobalScoped() {
231
-						tmpview[k] = v
232
-					}
229
+func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan datastore.KVObject) {
230
+	for {
231
+		select {
232
+		case <-nw.stopCh:
233
+			return
234
+		case o := <-ecCh:
235
+			ec := o.(*endpointCnt)
236
+
237
+			epl, err := ec.n.getEndpointsFromStore()
238
+			if err != nil {
239
+				break
240
+			}
241
+
242
+			c.Lock()
243
+			var addEp []*endpoint
244
+
245
+			delEpMap := make(map[string]*endpoint)
246
+			for k, v := range nw.remoteEps {
247
+				delEpMap[k] = v
248
+			}
249
+
250
+			for _, lEp := range epl {
251
+				if _, ok := nw.localEps[lEp.ID()]; ok {
252
+					continue
233 253
 				}
234
-				n.ctrlr.processEndpointsUpdate(eps, &tmpview)
235
-				// Delete processing
236
-				for k := range tmpview {
237
-					n.Lock()
238
-					existing, ok := n.endpoints[k]
239
-					n.Unlock()
240
-					if !ok {
241
-						continue
242
-					}
243
-					tmp := endpoint{}
244
-					if err := cs.GetObject(datastore.Key(existing.Key()...), &tmp); err != datastore.ErrKeyNotFound {
245
-						continue
246
-					}
247
-					if err := existing.deleteEndpoint(); err != nil {
248
-						log.Debugf("Delete failed %s: %s", existing.name, err)
249
-					}
254
+
255
+				if _, ok := nw.remoteEps[lEp.ID()]; ok {
256
+					delete(delEpMap, lEp.ID())
257
+					continue
250 258
 				}
259
+
260
+				nw.remoteEps[lEp.ID()] = lEp
261
+				addEp = append(addEp, lEp)
262
+
263
+			}
264
+			c.Unlock()
265
+
266
+			for _, lEp := range addEp {
267
+				ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), true)
251 268
 			}
252
-		}
253
-	}()
254
-	return nil
255
-}
256 269
 
257
-func (n *network) stopWatch() {
258
-	n.Lock()
259
-	if n.stopWatchCh != nil {
260
-		close(n.stopWatchCh)
261
-		n.stopWatchCh = nil
270
+			for _, lEp := range delEpMap {
271
+				ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), false)
272
+
273
+			}
274
+		}
262 275
 	}
263
-	n.Unlock()
264 276
 }
265 277
 
266
-func (c *controller) processNetworkUpdate(nws []*store.KVPair, prune *networkTable) {
267
-	for _, kve := range nws {
268
-		var n network
269
-		err := json.Unmarshal(kve.Value, &n)
270
-		if err != nil {
271
-			log.Error(err)
272
-			continue
273
-		}
274
-		if prune != nil {
275
-			delete(*prune, n.id)
276
-		}
277
-		n.SetIndex(kve.LastIndex)
278
+func (c *controller) processEndpointCreate(nmap map[string]*netWatch, ep *endpoint) {
279
+	c.Lock()
280
+	nw, ok := nmap[ep.getNetwork().ID()]
281
+	c.Unlock()
282
+
283
+	if ok {
284
+		// Update the svc db for the local endpoint join right away
285
+		ep.getNetwork().updateSvcRecord(ep, c.getLocalEps(nw), true)
286
+
278 287
 		c.Lock()
279
-		existing, ok := c.networks[n.id]
288
+		nw.localEps[ep.ID()] = ep
280 289
 		c.Unlock()
281
-		if ok {
282
-			existing.Lock()
283
-			// Skip existing network update
284
-			if existing.dbIndex != n.Index() {
285
-				// Can't use SetIndex() since existing is locked.
286
-				existing.dbIndex = n.Index()
287
-				existing.dbExists = true
288
-				existing.endpointCnt = n.endpointCnt
289
-			}
290
-			existing.Unlock()
291
-			continue
292
-		}
293
-
294
-		if err = c.newNetworkFromStore(&n); err != nil {
295
-			log.Error(err)
296
-		}
290
+		return
297 291
 	}
298
-}
299 292
 
300
-func (c *controller) processEndpointUpdate(ep *endpoint) bool {
301
-	nw := ep.network
302
-	if nw == nil {
303
-		return true
293
+	nw = &netWatch{
294
+		localEps:  make(map[string]*endpoint),
295
+		remoteEps: make(map[string]*endpoint),
304 296
 	}
305
-	nw.Lock()
306
-	id := nw.id
307
-	nw.Unlock()
297
+
298
+	// Update the svc db for the local endpoint join right away
299
+	// Do this before adding this ep to localEps so that we don't
300
+	// try to update this ep's container's svc records
301
+	ep.getNetwork().updateSvcRecord(ep, c.getLocalEps(nw), true)
308 302
 
309 303
 	c.Lock()
310
-	n, ok := c.networks[id]
304
+	nw.localEps[ep.ID()] = ep
305
+	nmap[ep.getNetwork().ID()] = nw
306
+	nw.stopCh = make(chan struct{})
311 307
 	c.Unlock()
312
-	if !ok {
313
-		return true
314
-	}
315
-	existing, _ := n.EndpointByID(ep.id)
316
-	if existing == nil {
317
-		return true
318
-	}
319 308
 
320
-	ee := existing.(*endpoint)
321
-	ee.Lock()
322
-	if ee.dbIndex != ep.Index() {
323
-		// Can't use SetIndex() because ee is locked.
324
-		ee.dbIndex = ep.Index()
325
-		ee.dbExists = true
326
-		ee.sandboxID = ep.sandboxID
309
+	store := c.getStore(ep.getNetwork().DataScope())
310
+	if store == nil {
311
+		return
327 312
 	}
328
-	ee.Unlock()
329 313
 
330
-	return false
331
-}
314
+	if !store.Watchable() {
315
+		return
316
+	}
332 317
 
333
-func ensureKeys(key string, cs datastore.DataStore) error {
334
-	exists, err := cs.KVStore().Exists(key)
318
+	ch, err := store.Watch(ep.getNetwork().getEpCnt(), nw.stopCh)
335 319
 	if err != nil {
336
-		return err
337
-	}
338
-	if exists {
339
-		return nil
320
+		log.Warnf("Error creating watch for network: %v", err)
321
+		return
340 322
 	}
341
-	return cs.KVStore().Put(key, []byte{}, nil)
342
-}
343 323
 
344
-func (c *controller) getLocalStoreConfig(cfg *config.Config) *config.DatastoreCfg {
345
-	if cfg != nil && cfg.LocalStore.Client.Provider != "" && cfg.LocalStore.Client.Address != "" {
346
-		return &cfg.LocalStore
347
-	}
348
-	return &defaultLocalStoreConfig
324
+	go c.networkWatchLoop(nw, ep, ch)
349 325
 }
350 326
 
351
-func (c *controller) getDataStore(dataScope datastore.DataScope) (dataStore datastore.DataStore) {
327
+func (c *controller) processEndpointDelete(nmap map[string]*netWatch, ep *endpoint) {
352 328
 	c.Lock()
353
-	if dataScope == datastore.GlobalScope {
354
-		dataStore = c.globalStore
355
-	} else if dataScope == datastore.LocalScope {
356
-		dataStore = c.localStore
329
+	nw, ok := nmap[ep.getNetwork().ID()]
330
+
331
+	if ok {
332
+		delete(nw.localEps, ep.ID())
333
+		c.Unlock()
334
+
335
+		// Update the svc db about local endpoint leave right away
336
+		// Do this after we remove this ep from localEps so that we
337
+		// don't try to remove this svc record from this ep's container.
338
+		ep.getNetwork().updateSvcRecord(ep, c.getLocalEps(nw), false)
339
+
340
+		c.Lock()
341
+		if len(nw.localEps) == 0 {
342
+			close(nw.stopCh)
343
+			delete(nmap, ep.getNetwork().ID())
344
+		}
357 345
 	}
358 346
 	c.Unlock()
359
-	return
360 347
 }
361 348
 
362
-func (c *controller) processEndpointsUpdate(eps []*store.KVPair, prune *endpointTable) {
363
-	for _, epe := range eps {
364
-		var ep endpoint
365
-		err := json.Unmarshal(epe.Value, &ep)
366
-		if err != nil {
367
-			log.Error(err)
368
-			continue
369
-		}
370
-		if prune != nil {
371
-			delete(*prune, ep.id)
372
-		}
373
-		ep.SetIndex(epe.LastIndex)
374
-		if nid, err := ep.networkIDFromKey(epe.Key); err != nil {
375
-			log.Error(err)
376
-			continue
377
-		} else {
378
-			if n, err := c.NetworkByID(nid); err != nil {
379
-				log.Error(err)
380
-				continue
381
-			} else {
382
-				ep.network = n.(*network)
383
-			}
384
-		}
385
-		if c.processEndpointUpdate(&ep) {
386
-			err = c.newEndpointFromStore(epe.Key, &ep)
387
-			if err != nil {
388
-				log.Error(err)
389
-			}
349
+func (c *controller) watchLoop(nmap map[string]*netWatch) {
350
+	for {
351
+		select {
352
+		case ep := <-c.watchCh:
353
+			c.processEndpointCreate(nmap, ep)
354
+		case ep := <-c.unWatchCh:
355
+			c.processEndpointDelete(nmap, ep)
390 356
 		}
391 357
 	}
392 358
 }
359
+
360
+func (c *controller) startWatch() {
361
+	c.watchCh = make(chan *endpoint)
362
+	c.unWatchCh = make(chan *endpoint)
363
+	nmap := make(map[string]*netWatch)
364
+
365
+	go c.watchLoop(nmap)
366
+}
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"bytes"
6 6
 	"fmt"
7 7
 	"net"
8
+	"strconv"
8 9
 	"strings"
9 10
 )
10 11
 
... ...
@@ -17,11 +18,46 @@ type TransportPort struct {
17 17
 	Port  uint16
18 18
 }
19 19
 
20
+// Equal checks if this instance of Transportport is equal to the passed one
21
+func (t *TransportPort) Equal(o *TransportPort) bool {
22
+	if t == o {
23
+		return true
24
+	}
25
+
26
+	if o == nil {
27
+		return false
28
+	}
29
+
30
+	if t.Proto != o.Proto || t.Port != o.Port {
31
+		return false
32
+	}
33
+
34
+	return true
35
+}
36
+
20 37
 // GetCopy returns a copy of this TransportPort structure instance
21 38
 func (t *TransportPort) GetCopy() TransportPort {
22 39
 	return TransportPort{Proto: t.Proto, Port: t.Port}
23 40
 }
24 41
 
42
+// String returns the TransportPort structure in string form
43
+func (t *TransportPort) String() string {
44
+	return fmt.Sprintf("%s/%d", t.Proto.String(), t.Port)
45
+}
46
+
47
+// FromString reads the TransportPort structure from string
48
+func (t *TransportPort) FromString(s string) error {
49
+	ps := strings.Split(s, "/")
50
+	if len(ps) == 2 {
51
+		t.Proto = ParseProtocol(ps[0])
52
+		if p, err := strconv.ParseUint(ps[1], 10, 16); err == nil {
53
+			t.Port = uint16(p)
54
+			return nil
55
+		}
56
+	}
57
+	return BadRequestErrorf("invalid format for transport port: %s", s)
58
+}
59
+
25 60
 // PortBinding represent a port binding between the container and the host
26 61
 type PortBinding struct {
27 62
 	Proto       Protocol
... ...
@@ -68,6 +104,62 @@ func (p *PortBinding) GetCopy() PortBinding {
68 68
 	}
69 69
 }
70 70
 
71
+// String return the PortBinding structure in string form
72
+func (p *PortBinding) String() string {
73
+	ret := fmt.Sprintf("%s/", p.Proto)
74
+	if p.IP != nil {
75
+		ret = fmt.Sprintf("%s%s", ret, p.IP.String())
76
+	}
77
+	ret = fmt.Sprintf("%s:%d/", ret, p.Port)
78
+	if p.HostIP != nil {
79
+		ret = fmt.Sprintf("%s%s", ret, p.HostIP.String())
80
+	}
81
+	ret = fmt.Sprintf("%s:%d", ret, p.HostPort)
82
+	return ret
83
+}
84
+
85
+// FromString reads the TransportPort structure from string
86
+func (p *PortBinding) FromString(s string) error {
87
+	ps := strings.Split(s, "/")
88
+	if len(ps) != 3 {
89
+		return BadRequestErrorf("invalid format for port binding: %s", s)
90
+	}
91
+
92
+	p.Proto = ParseProtocol(ps[0])
93
+
94
+	var err error
95
+	if p.IP, p.Port, err = parseIPPort(ps[1]); err != nil {
96
+		return BadRequestErrorf("failed to parse Container IP/Port in port binding: %s", err.Error())
97
+	}
98
+
99
+	if p.HostIP, p.HostPort, err = parseIPPort(ps[2]); err != nil {
100
+		return BadRequestErrorf("failed to parse Host IP/Port in port binding: %s", err.Error())
101
+	}
102
+
103
+	return nil
104
+}
105
+
106
+func parseIPPort(s string) (net.IP, uint16, error) {
107
+	pp := strings.Split(s, ":")
108
+	if len(pp) != 2 {
109
+		return nil, 0, BadRequestErrorf("invalid format: %s", s)
110
+	}
111
+
112
+	var ip net.IP
113
+	if pp[0] != "" {
114
+		if ip = net.ParseIP(pp[0]); ip == nil {
115
+			return nil, 0, BadRequestErrorf("invalid ip: %s", pp[0])
116
+		}
117
+	}
118
+
119
+	port, err := strconv.ParseUint(pp[1], 10, 16)
120
+	if err != nil {
121
+		return nil, 0, BadRequestErrorf("invalid port: %s", pp[1])
122
+	}
123
+
124
+	return ip, uint16(port), nil
125
+}
126
+
71 127
 // Equal checks if this instance of PortBinding is equal to the passed one
72 128
 func (p *PortBinding) Equal(o *PortBinding) bool {
73 129
 	if p == o {
... ...
@@ -154,6 +246,9 @@ func ParseProtocol(s string) Protocol {
154 154
 
155 155
 // GetMacCopy returns a copy of the passed MAC address
156 156
 func GetMacCopy(from net.HardwareAddr) net.HardwareAddr {
157
+	if from == nil {
158
+		return nil
159
+	}
157 160
 	to := make(net.HardwareAddr, len(from))
158 161
 	copy(to, from)
159 162
 	return to
... ...
@@ -161,6 +256,9 @@ func GetMacCopy(from net.HardwareAddr) net.HardwareAddr {
161 161
 
162 162
 // GetIPCopy returns a copy of the passed IP address
163 163
 func GetIPCopy(from net.IP) net.IP {
164
+	if from == nil {
165
+		return nil
166
+	}
164 167
 	to := make(net.IP, len(from))
165 168
 	copy(to, from)
166 169
 	return to
... ...
@@ -222,23 +320,32 @@ func GetMinimalIPNet(nw *net.IPNet) *net.IPNet {
222 222
 
223 223
 var v4inV6MaskPrefix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
224 224
 
225
-// GetHostPartIP returns the host portion of the ip address identified by the mask.
226
-// IP address representation is not modified. If address and mask are not compatible
227
-// an error is returned.
228
-func GetHostPartIP(ip net.IP, mask net.IPMask) (net.IP, error) {
225
+// compareIPMask checks if the passed ip and mask are semantically compatible.
226
+// It returns the byte indexes for the address and mask so that caller can
227
+// do bitwise operations without modifying address representation.
228
+func compareIPMask(ip net.IP, mask net.IPMask) (is int, ms int, err error) {
229 229
 	// Find the effective starting of address and mask
230
-	is := 0
231
-	ms := 0
232 230
 	if len(ip) == net.IPv6len && ip.To4() != nil {
233 231
 		is = 12
234 232
 	}
235 233
 	if len(ip[is:]) == net.IPv4len && len(mask) == net.IPv6len && bytes.Equal(mask[:12], v4inV6MaskPrefix) {
236 234
 		ms = 12
237 235
 	}
238
-
239 236
 	// Check if address and mask are semantically compatible
240 237
 	if len(ip[is:]) != len(mask[ms:]) {
241
-		return nil, fmt.Errorf("cannot compute host portion ip address as ip and mask are not compatible: (%#v, %#v)", ip, mask)
238
+		err = fmt.Errorf("ip and mask are not compatible: (%#v, %#v)", ip, mask)
239
+	}
240
+	return
241
+}
242
+
243
+// GetHostPartIP returns the host portion of the ip address identified by the mask.
244
+// IP address representation is not modified. If address and mask are not compatible
245
+// an error is returned.
246
+func GetHostPartIP(ip net.IP, mask net.IPMask) (net.IP, error) {
247
+	// Find the effective starting of address and mask
248
+	is, ms, err := compareIPMask(ip, mask)
249
+	if err != nil {
250
+		return nil, fmt.Errorf("cannot compute host portion ip address because %s", err)
242 251
 	}
243 252
 
244 253
 	// Compute host portion
... ...
@@ -250,6 +357,34 @@ func GetHostPartIP(ip net.IP, mask net.IPMask) (net.IP, error) {
250 250
 	return out, nil
251 251
 }
252 252
 
253
+// GetBroadcastIP returns the broadcast ip address for the passed network (ip and mask).
254
+// IP address representation is not modified. If address and mask are not compatible
255
+// an error is returned.
256
+func GetBroadcastIP(ip net.IP, mask net.IPMask) (net.IP, error) {
257
+	// Find the effective starting of address and mask
258
+	is, ms, err := compareIPMask(ip, mask)
259
+	if err != nil {
260
+		return nil, fmt.Errorf("cannot compute broadcast ip address because %s", err)
261
+	}
262
+
263
+	// Compute broadcast address
264
+	out := GetIPCopy(ip)
265
+	for i := 0; i < len(mask[ms:]); i++ {
266
+		out[is+i] |= ^mask[ms+i]
267
+	}
268
+
269
+	return out, nil
270
+}
271
+
272
+// ParseCIDR returns the *net.IPNet represented by the passed CIDR notation
273
+func ParseCIDR(cidr string) (n *net.IPNet, e error) {
274
+	var i net.IP
275
+	if i, n, e = net.ParseCIDR(cidr); e == nil {
276
+		n.IP = i
277
+	}
278
+	return
279
+}
280
+
253 281
 const (
254 282
 	// NEXTHOP indicates a StaticRoute with an IP next hop.
255 283
 	NEXTHOP = iota
... ...
@@ -278,6 +413,23 @@ func (r *StaticRoute) GetCopy() *StaticRoute {
278 278
 	}
279 279
 }
280 280
 
281
+// InterfaceStatistics represents the interface's statistics
282
+type InterfaceStatistics struct {
283
+	RxBytes   uint64
284
+	RxPackets uint64
285
+	RxErrors  uint64
286
+	RxDropped uint64
287
+	TxBytes   uint64
288
+	TxPackets uint64
289
+	TxErrors  uint64
290
+	TxDropped uint64
291
+}
292
+
293
+func (is *InterfaceStatistics) String() string {
294
+	return fmt.Sprintf("\nRxBytes: %d, RxPackets: %d, RxErrors: %d, RxDropped: %d, TxBytes: %d, TxPackets: %d, TxErrors: %d, TxDropped: %d",
295
+		is.RxBytes, is.RxPackets, is.RxErrors, is.RxDropped, is.TxBytes, is.TxPackets, is.TxErrors, is.TxDropped)
296
+}
297
+
281 298
 /******************************
282 299
  * Well-known Error Interfaces
283 300
  ******************************/