Vendoring in libnetwork integrated with Docker Discovery
This commit brings in end to end integration of Docker Discovery with libnetwork multi-host networking. Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
parent
662f55d11d
commit
956fbccdaa
26 changed files with 1125 additions and 195 deletions
|
@ -22,7 +22,7 @@ clone git github.com/tchap/go-patricia v2.1.0
|
|||
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork 70409acbcd661e6a7bfe04e2b81412a465d29512
|
||||
clone git github.com/docker/libnetwork c3a9e0d8d0c53f3db251620e5f48470e267f292b
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||
|
@ -32,6 +32,7 @@ clone git github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
|
|||
clone git github.com/vishvananda/netlink 4b5dce31de6d42af5bb9811c6d265472199e0fec
|
||||
clone git github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
|
||||
clone git github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
|
||||
clone git github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
|
||||
clone git github.com/coreos/go-etcd v2.0.0
|
||||
clone git github.com/hashicorp/consul v0.5.2
|
||||
clone git github.com/boltdb/bolt v1.0
|
||||
|
|
22
vendor/src/github.com/deckarep/golang-set/.gitignore
vendored
Normal file
22
vendor/src/github.com/deckarep/golang-set/.gitignore
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
9
vendor/src/github.com/deckarep/golang-set/.travis.yml
vendored
Normal file
9
vendor/src/github.com/deckarep/golang-set/.travis.yml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
|
||||
script:
|
||||
- go test ./...
|
||||
#- go test -race ./...
|
||||
|
22
vendor/src/github.com/deckarep/golang-set/LICENSE
vendored
Normal file
22
vendor/src/github.com/deckarep/golang-set/LICENSE
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
94
vendor/src/github.com/deckarep/golang-set/README.md
vendored
Normal file
94
vendor/src/github.com/deckarep/golang-set/README.md
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
[](https://travis-ci.org/deckarep/golang-set)
|
||||
[](http://godoc.org/github.com/deckarep/golang-set)
|
||||
|
||||
## golang-set
|
||||
|
||||
|
||||
The missing set collection for the Go language. Until Go has sets built-in...use this.
|
||||
|
||||
Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set from Python.
|
||||
You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository
|
||||
and carry-on and to the rest that find this useful please contribute in helping me make it better by:
|
||||
|
||||
* Helping to make more idiomatic improvements to the code.
|
||||
* Helping to increase the performance of it. ~~(So far, no attempt has been made, but since it uses a map internally, I expect it to be mostly performant.)~~
|
||||
* Helping to make the unit-tests more robust and kick-ass.
|
||||
* Helping to fill in the [documentation.](http://godoc.org/github.com/deckarep/golang-set)
|
||||
* Simply offering feedback and suggestions. (Positive, constructive feedback is appreciated.)
|
||||
|
||||
I have to give some credit for helping seed the idea with this post on [stackoverflow.](http://programmers.stackexchange.com/questions/177428/sets-data-structure-in-golang)
|
||||
|
||||
*Update* - as of 3/9/2014, you can use a compile-time generic version of this package in the [gen](http://clipperhouse.github.io/gen/) framework. This framework allows you to use the golang-set in a completely generic and type-safe way by allowing you to generate a supporting .go file based on your custom types.
|
||||
|
||||
## Features (as of 9/22/2014)
|
||||
|
||||
* a CartesionProduct() method has been added with unit-tests: [Read more about the cartesion product](http://en.wikipedia.org/wiki/Cartesian_product)
|
||||
|
||||
## Features (as of 9/15/2014)
|
||||
|
||||
* a PowerSet() method has been added with unit-tests: [Read more about the Power set](http://en.wikipedia.org/wiki/Power_set)
|
||||
|
||||
## Features (as of 4/22/2014)
|
||||
|
||||
* One common interface to both implementations
|
||||
* Two set implementations to choose from
|
||||
* a thread-safe implementation designed for concurrent use
|
||||
* a non-thread-safe implementation designed for performance
|
||||
* 75 benchmarks for both implementations
|
||||
* 35 unit tests for both implementations
|
||||
* 14 concurrent tests for the thread-safe implementation
|
||||
|
||||
|
||||
|
||||
Please see the unit test file for additional usage examples. The Python set documentation will also do a better job than I can of explaining how a set typically [works.](http://docs.python.org/2/library/sets.html) Please keep in mind
|
||||
however that the Python set is a built-in type and supports additional features and syntax that make it awesome.
|
||||
|
||||
## Examples but not exhaustive:
|
||||
|
||||
```go
|
||||
requiredClasses := mapset.NewSet()
|
||||
requiredClasses.Add("Cooking")
|
||||
requiredClasses.Add("English")
|
||||
requiredClasses.Add("Math")
|
||||
requiredClasses.Add("Biology")
|
||||
|
||||
scienceSlice := []interface{}{"Biology", "Chemistry"}
|
||||
scienceClasses := mapset.NewSetFromSlice(scienceSlice)
|
||||
|
||||
electiveClasses := mapset.NewSet()
|
||||
electiveClasses.Add("Welding")
|
||||
electiveClasses.Add("Music")
|
||||
electiveClasses.Add("Automotive")
|
||||
|
||||
bonusClasses := mapset.NewSet()
|
||||
bonusClasses.Add("Go Programming")
|
||||
bonusClasses.Add("Python Programming")
|
||||
|
||||
//Show me all the available classes I can take
|
||||
allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
|
||||
fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming}
|
||||
|
||||
|
||||
//Is cooking considered a science class?
|
||||
fmt.Println(scienceClasses.Contains("Cooking")) //false
|
||||
|
||||
//Show me all classes that are not science classes, since I hate science.
|
||||
fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding}
|
||||
|
||||
//Which science classes are also required classes?
|
||||
fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
|
||||
|
||||
//How many bonus classes do you offer?
|
||||
fmt.Println(bonusClasses.Cardinality()) //2
|
||||
|
||||
//Do you have the following classes? Welding, Automotive and English?
|
||||
fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true
|
||||
```
|
||||
|
||||
Thanks!
|
||||
|
||||
-Ralph
|
||||
|
||||
[](https://bitdeli.com/free "Bitdeli Badge")
|
||||
|
||||
[](https://github.com/igrigorik/ga-beacon)
|
168
vendor/src/github.com/deckarep/golang-set/set.go
vendored
Normal file
168
vendor/src/github.com/deckarep/golang-set/set.go
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package mapset implements a simple and generic set collection.
|
||||
// Items stored within it are unordered and unique. It supports
|
||||
// typical set operations: membership testing, intersection, union,
|
||||
// difference, symmetric difference and cloning.
|
||||
//
|
||||
// Package mapset provides two implementations. The default
|
||||
// implementation is safe for concurrent access. There is a non-threadsafe
|
||||
// implementation which is slightly more performant.
|
||||
package mapset
|
||||
|
||||
type Set interface {
|
||||
// Adds an element to the set. Returns whether
|
||||
// the item was added.
|
||||
Add(i interface{}) bool
|
||||
|
||||
// Returns the number of elements in the set.
|
||||
Cardinality() int
|
||||
|
||||
// Removes all elements from the set, leaving
|
||||
// the emtpy set.
|
||||
Clear()
|
||||
|
||||
// Returns a clone of the set using the same
|
||||
// implementation, duplicating all keys.
|
||||
Clone() Set
|
||||
|
||||
// Returns whether the given items
|
||||
// are all in the set.
|
||||
Contains(i ...interface{}) bool
|
||||
|
||||
// Returns the difference between this set
|
||||
// and other. The returned set will contain
|
||||
// all elements of this set that are not also
|
||||
// elements of other.
|
||||
//
|
||||
// Note that the argument to Difference
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Difference will
|
||||
// panic.
|
||||
Difference(other Set) Set
|
||||
|
||||
// Determines if two sets are equal to each
|
||||
// other. If they have the same cardinality
|
||||
// and contain the same elements, they are
|
||||
// considered equal. The order in which
|
||||
// the elements were added is irrelevant.
|
||||
//
|
||||
// Note that the argument to Equal must be
|
||||
// of the same type as the receiver of the
|
||||
// method. Otherwise, Equal will panic.
|
||||
Equal(other Set) bool
|
||||
|
||||
// Returns a new set containing only the elements
|
||||
// that exist only in both sets.
|
||||
//
|
||||
// Note that the argument to Intersect
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, Intersect will
|
||||
// panic.
|
||||
Intersect(other Set) Set
|
||||
|
||||
// Determines if every element in the other set
|
||||
// is in this set.
|
||||
//
|
||||
// Note that the argument to IsSubset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSubset will
|
||||
// panic.
|
||||
IsSubset(other Set) bool
|
||||
|
||||
// Determines if every element in this set is in
|
||||
// the other set.
|
||||
//
|
||||
// Note that the argument to IsSuperset
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, IsSuperset will
|
||||
// panic.
|
||||
IsSuperset(other Set) bool
|
||||
|
||||
// Returns a channel of elements that you can
|
||||
// range over.
|
||||
Iter() <-chan interface{}
|
||||
|
||||
// Remove a single element from the set.
|
||||
Remove(i interface{})
|
||||
|
||||
// Provides a convenient string representation
|
||||
// of the current state of the set.
|
||||
String() string
|
||||
|
||||
// Returns a new set with all elements which are
|
||||
// in either this set or the other set but not in both.
|
||||
//
|
||||
// Note that the argument to SymmetricDifference
|
||||
// must be of the same type as the receiver
|
||||
// of the method. Otherwise, SymmetricDifference
|
||||
// will panic.
|
||||
SymmetricDifference(other Set) Set
|
||||
|
||||
// Returns a new set with all elements in both sets.
|
||||
//
|
||||
// Note that the argument to Union must be of the
|
||||
// same type as the receiver of the method.
|
||||
// Otherwise, IsSuperset will panic.
|
||||
Union(other Set) Set
|
||||
|
||||
// Returns all subsets of a given set (Power Set).
|
||||
PowerSet() Set
|
||||
|
||||
// Returns the Cartesian Product of two sets.
|
||||
CartesianProduct(other Set) Set
|
||||
|
||||
// Returns the members of the set as a slice.
|
||||
ToSlice() []interface{}
|
||||
}
|
||||
|
||||
// Creates and returns a reference to an empty set.
|
||||
func NewSet() Set {
|
||||
set := newThreadSafeSet()
|
||||
return &set
|
||||
}
|
||||
|
||||
// Creates and returns a reference to a set from an existing slice
|
||||
func NewSetFromSlice(s []interface{}) Set {
|
||||
a := NewSet()
|
||||
for _, item := range s {
|
||||
a.Add(item)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func NewThreadUnsafeSet() Set {
|
||||
set := newThreadUnsafeSet()
|
||||
return &set
|
||||
}
|
||||
|
||||
func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
|
||||
a := NewThreadUnsafeSet()
|
||||
for _, item := range s {
|
||||
a.Add(item)
|
||||
}
|
||||
return a
|
||||
}
|
204
vendor/src/github.com/deckarep/golang-set/threadsafe.go
vendored
Normal file
204
vendor/src/github.com/deckarep/golang-set/threadsafe.go
vendored
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
import "sync"
|
||||
|
||||
type threadSafeSet struct {
|
||||
s threadUnsafeSet
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func newThreadSafeSet() threadSafeSet {
|
||||
return threadSafeSet{s: newThreadUnsafeSet()}
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Add(i interface{}) bool {
|
||||
set.Lock()
|
||||
ret := set.s.Add(i)
|
||||
set.Unlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Contains(i ...interface{}) bool {
|
||||
set.RLock()
|
||||
ret := set.s.Contains(i...)
|
||||
set.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsSubset(other Set) bool {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := set.s.IsSubset(&o.s)
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) IsSuperset(other Set) bool {
|
||||
return other.IsSubset(set)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Union(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeUnion}
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Intersect(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeIntersection}
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Difference(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeDifference}
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) SymmetricDifference(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
|
||||
return &threadSafeSet{s: *unsafeDifference}
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Clear() {
|
||||
set.Lock()
|
||||
set.s = newThreadUnsafeSet()
|
||||
set.Unlock()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Remove(i interface{}) {
|
||||
set.Lock()
|
||||
delete(set.s, i)
|
||||
set.Unlock()
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Cardinality() int {
|
||||
set.RLock()
|
||||
defer set.RUnlock()
|
||||
return len(set.s)
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Iter() <-chan interface{} {
|
||||
ch := make(chan interface{})
|
||||
go func() {
|
||||
set.RLock()
|
||||
|
||||
for elem := range set.s {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
set.RUnlock()
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Equal(other Set) bool {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
ret := set.s.Equal(&o.s)
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) Clone() Set {
|
||||
set.RLock()
|
||||
|
||||
unsafeClone := set.s.Clone().(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeClone}
|
||||
set.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) String() string {
|
||||
set.RLock()
|
||||
ret := set.s.String()
|
||||
set.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) PowerSet() Set {
|
||||
set.RLock()
|
||||
ret := set.s.PowerSet()
|
||||
set.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) CartesianProduct(other Set) Set {
|
||||
o := other.(*threadSafeSet)
|
||||
|
||||
set.RLock()
|
||||
o.RLock()
|
||||
|
||||
unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
|
||||
ret := &threadSafeSet{s: *unsafeCartProduct}
|
||||
set.RUnlock()
|
||||
o.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (set *threadSafeSet) ToSlice() []interface{} {
|
||||
set.RLock()
|
||||
keys := make([]interface{}, 0, set.Cardinality())
|
||||
for elem := range set.s {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
set.RUnlock()
|
||||
return keys
|
||||
}
|
246
vendor/src/github.com/deckarep/golang-set/threadunsafe.go
vendored
Normal file
246
vendor/src/github.com/deckarep/golang-set/threadunsafe.go
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package mapset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type threadUnsafeSet map[interface{}]struct{}
|
||||
|
||||
type orderedPair struct {
|
||||
first interface{}
|
||||
second interface{}
|
||||
}
|
||||
|
||||
func newThreadUnsafeSet() threadUnsafeSet {
|
||||
return make(threadUnsafeSet)
|
||||
}
|
||||
|
||||
func (pair *orderedPair) Equal(other orderedPair) bool {
|
||||
if pair.first == other.first &&
|
||||
pair.second == other.second {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Add(i interface{}) bool {
|
||||
_, found := (*set)[i]
|
||||
(*set)[i] = struct{}{}
|
||||
return !found //False if it existed already
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
|
||||
for _, val := range i {
|
||||
if _, ok := (*set)[val]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) IsSubset(other Set) bool {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
for elem := range *set {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) IsSuperset(other Set) bool {
|
||||
return other.IsSubset(set)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Union(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
|
||||
unionedSet := newThreadUnsafeSet()
|
||||
|
||||
for elem := range *set {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
for elem := range *o {
|
||||
unionedSet.Add(elem)
|
||||
}
|
||||
return &unionedSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Intersect(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
|
||||
intersection := newThreadUnsafeSet()
|
||||
// loop over smaller set
|
||||
if set.Cardinality() < other.Cardinality() {
|
||||
for elem := range *set {
|
||||
if other.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for elem := range *o {
|
||||
if set.Contains(elem) {
|
||||
intersection.Add(elem)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &intersection
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Difference(other Set) Set {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
|
||||
difference := newThreadUnsafeSet()
|
||||
for elem := range *set {
|
||||
if !other.Contains(elem) {
|
||||
difference.Add(elem)
|
||||
}
|
||||
}
|
||||
return &difference
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
|
||||
aDiff := set.Difference(other)
|
||||
bDiff := other.Difference(set)
|
||||
return aDiff.Union(bDiff)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Clear() {
|
||||
*set = newThreadUnsafeSet()
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Remove(i interface{}) {
|
||||
delete(*set, i)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Cardinality() int {
|
||||
return len(*set)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Iter() <-chan interface{} {
|
||||
ch := make(chan interface{})
|
||||
go func() {
|
||||
for elem := range *set {
|
||||
ch <- elem
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Equal(other Set) bool {
|
||||
_ = other.(*threadUnsafeSet)
|
||||
|
||||
if set.Cardinality() != other.Cardinality() {
|
||||
return false
|
||||
}
|
||||
for elem := range *set {
|
||||
if !other.Contains(elem) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) Clone() Set {
|
||||
clonedSet := newThreadUnsafeSet()
|
||||
for elem := range *set {
|
||||
clonedSet.Add(elem)
|
||||
}
|
||||
return &clonedSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) String() string {
|
||||
items := make([]string, 0, len(*set))
|
||||
|
||||
for elem := range *set {
|
||||
items = append(items, fmt.Sprintf("%v", elem))
|
||||
}
|
||||
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||
}
|
||||
|
||||
func (pair orderedPair) String() string {
|
||||
return fmt.Sprintf("(%v, %v)", pair.first, pair.second)
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) PowerSet() Set {
|
||||
powSet := NewThreadUnsafeSet()
|
||||
nullset := newThreadUnsafeSet()
|
||||
powSet.Add(&nullset)
|
||||
|
||||
for es := range *set {
|
||||
u := newThreadUnsafeSet()
|
||||
j := powSet.Iter()
|
||||
for er := range j {
|
||||
p := newThreadUnsafeSet()
|
||||
if reflect.TypeOf(er).Name() == "" {
|
||||
k := er.(*threadUnsafeSet)
|
||||
for ek := range *(k) {
|
||||
p.Add(ek)
|
||||
}
|
||||
} else {
|
||||
p.Add(er)
|
||||
}
|
||||
p.Add(es)
|
||||
u.Add(&p)
|
||||
}
|
||||
|
||||
powSet = powSet.Union(&u)
|
||||
}
|
||||
|
||||
return powSet
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
|
||||
o := other.(*threadUnsafeSet)
|
||||
cartProduct := NewThreadUnsafeSet()
|
||||
|
||||
for i := range *set {
|
||||
for j := range *o {
|
||||
elem := orderedPair{first: i, second: j}
|
||||
cartProduct.Add(elem)
|
||||
}
|
||||
}
|
||||
|
||||
return cartProduct
|
||||
}
|
||||
|
||||
func (set *threadUnsafeSet) ToSlice() []interface{} {
|
||||
keys := make([]interface{}, 0, set.Cardinality())
|
||||
for elem := range *set {
|
||||
keys = append(keys, elem)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/BurntSushi/toml"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/discovery"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
)
|
||||
|
@ -27,8 +28,9 @@ type DaemonCfg struct {
|
|||
|
||||
// ClusterCfg represents cluster configuration
|
||||
type ClusterCfg struct {
|
||||
Discovery string
|
||||
Watcher discovery.Watcher
|
||||
Address string
|
||||
Discovery string
|
||||
Heartbeat uint64
|
||||
}
|
||||
|
||||
|
@ -108,6 +110,20 @@ func OptionKVProviderURL(url string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// OptionDiscoveryWatcher function returns an option setter for discovery watcher
|
||||
func OptionDiscoveryWatcher(watcher discovery.Watcher) Option {
|
||||
return func(c *Config) {
|
||||
c.Cluster.Watcher = watcher
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDiscoveryAddress function returns an option setter for self discovery address
|
||||
func OptionDiscoveryAddress(address string) Option {
|
||||
return func(c *Config) {
|
||||
c.Cluster.Address = address
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessOptions processes options and stores it in config
|
||||
func (c *Config) ProcessOptions(options ...Option) {
|
||||
for _, opt := range options {
|
||||
|
|
|
@ -47,9 +47,11 @@ import (
|
|||
"container/heap"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/discovery"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/libnetwork/config"
|
||||
|
@ -126,6 +128,7 @@ type controller struct {
|
|||
sandboxes sandboxTable
|
||||
cfg *config.Config
|
||||
globalStore, localStore datastore.DataStore
|
||||
discovery hostdiscovery.HostDiscovery
|
||||
extKeyListener net.Listener
|
||||
sync.Mutex
|
||||
}
|
||||
|
@ -157,7 +160,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||
// But it cannot fail creating the Controller
|
||||
log.Debugf("Failed to Initialize Datastore due to %v. Operating in non-clustered mode", err)
|
||||
}
|
||||
if err := c.initDiscovery(); err != nil {
|
||||
if err := c.initDiscovery(cfg.Cluster.Watcher); err != nil {
|
||||
// Failing to initalize discovery is a bad situation to be in.
|
||||
// But it cannot fail creating the Controller
|
||||
log.Debugf("Failed to Initialize Discovery : %v", err)
|
||||
|
@ -185,19 +188,57 @@ func (c *controller) validateHostDiscoveryConfig() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (c *controller) initDiscovery() error {
|
||||
func (c *controller) initDiscovery(watcher discovery.Watcher) error {
|
||||
if c.cfg == nil {
|
||||
return fmt.Errorf("discovery initialization requires a valid configuration")
|
||||
}
|
||||
|
||||
hostDiscovery := hostdiscovery.NewHostDiscovery()
|
||||
return hostDiscovery.StartDiscovery(&c.cfg.Cluster, c.hostJoinCallback, c.hostLeaveCallback)
|
||||
c.discovery = hostdiscovery.NewHostDiscovery(watcher)
|
||||
return c.discovery.Watch(c.hostJoinCallback, c.hostLeaveCallback)
|
||||
}
|
||||
|
||||
func (c *controller) hostJoinCallback(hosts []net.IP) {
|
||||
func (c *controller) hostJoinCallback(nodes []net.IP) {
|
||||
c.processNodeDiscovery(nodes, true)
|
||||
}
|
||||
|
||||
func (c *controller) hostLeaveCallback(hosts []net.IP) {
|
||||
func (c *controller) hostLeaveCallback(nodes []net.IP) {
|
||||
c.processNodeDiscovery(nodes, false)
|
||||
}
|
||||
|
||||
func (c *controller) processNodeDiscovery(nodes []net.IP, add bool) {
|
||||
c.Lock()
|
||||
drivers := []*driverData{}
|
||||
for _, d := range c.drivers {
|
||||
drivers = append(drivers, d)
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
for _, d := range drivers {
|
||||
c.pushNodeDiscovery(d, nodes, add)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controller) pushNodeDiscovery(d *driverData, nodes []net.IP, add bool) {
|
||||
var self net.IP
|
||||
if c.cfg != nil {
|
||||
addr := strings.Split(c.cfg.Cluster.Address, ":")
|
||||
self = net.ParseIP(addr[0])
|
||||
}
|
||||
if d == nil || d.capability.DataScope != datastore.GlobalScope || nodes == nil {
|
||||
return
|
||||
}
|
||||
for _, node := range nodes {
|
||||
nodeData := driverapi.NodeDiscoveryData{Address: node.String(), Self: node.Equal(self)}
|
||||
var err error
|
||||
if add {
|
||||
err = d.driver.DiscoverNew(driverapi.NodeDiscovery, nodeData)
|
||||
} else {
|
||||
err = d.driver.DiscoverDelete(driverapi.NodeDiscovery, nodeData)
|
||||
}
|
||||
if err != nil {
|
||||
log.Debugf("discovery notification error : %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controller) Config() config.Config {
|
||||
|
@ -219,9 +260,15 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver,
|
|||
c.Unlock()
|
||||
return driverapi.ErrActiveRegistration(networkType)
|
||||
}
|
||||
c.drivers[networkType] = &driverData{driver, capability}
|
||||
dData := &driverData{driver, capability}
|
||||
c.drivers[networkType] = dData
|
||||
hd := c.discovery
|
||||
c.Unlock()
|
||||
|
||||
if hd != nil {
|
||||
c.pushNodeDiscovery(dData, hd.Fetch(), true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -487,6 +534,16 @@ func (c *controller) loadDriver(networkType string) (*driverData, error) {
|
|||
return dd, nil
|
||||
}
|
||||
|
||||
func (c *controller) getDriver(networkType string) (*driverData, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
dd, ok := c.drivers[networkType]
|
||||
if !ok {
|
||||
return nil, types.NotFoundErrorf("driver %s not found", networkType)
|
||||
}
|
||||
return dd, nil
|
||||
}
|
||||
|
||||
func (c *controller) Stop() {
|
||||
if c.localStore != nil {
|
||||
c.localStore.KVStore().Close()
|
||||
|
|
|
@ -40,6 +40,12 @@ type Driver interface {
|
|||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
Leave(nid, eid string) error
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, Example:a new node joining a cluster
|
||||
DiscoverNew(dType DiscoveryType, data interface{}) error
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, Example:a node leaving a cluster
|
||||
DiscoverDelete(dType DiscoveryType, data interface{}) error
|
||||
|
||||
// Type returns the the type of this driver, the network type this driver manages
|
||||
Type() string
|
||||
}
|
||||
|
@ -106,3 +112,17 @@ type DriverCallback interface {
|
|||
type Capability struct {
|
||||
DataScope datastore.DataScope
|
||||
}
|
||||
|
||||
// DiscoveryType represents the type of discovery element the DiscoverNew function is invoked on
|
||||
type DiscoveryType int
|
||||
|
||||
const (
|
||||
// NodeDiscovery represents Node join/leave events provided by discovery
|
||||
NodeDiscovery = iota + 1
|
||||
)
|
||||
|
||||
// NodeDiscoveryData represents the structure backing the node discovery data json string
|
||||
type NodeDiscoveryData struct {
|
||||
Address string
|
||||
Self bool
|
||||
}
|
||||
|
|
|
@ -1375,6 +1375,16 @@ func (d *driver) Type() string {
|
|||
return networkType
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
|
||||
if epOptions == nil {
|
||||
return nil, nil
|
||||
|
|
|
@ -65,3 +65,13 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -65,3 +65,13 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package overlay
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
@ -73,12 +74,8 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
|||
}
|
||||
|
||||
d.peerDbAdd(nid, eid, ep.addr.IP, ep.mac,
|
||||
d.serfInstance.LocalMember().Addr, true)
|
||||
d.notifyCh <- ovNotify{
|
||||
action: "join",
|
||||
nid: nid,
|
||||
eid: eid,
|
||||
}
|
||||
net.ParseIP(d.bindAddress), true)
|
||||
d.pushLocalEndpointEvent("join", nid, eid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -156,23 +156,8 @@ func (n *network) initSandbox() error {
|
|||
return fmt.Errorf("could not create bridge inside the network sandbox: %v", err)
|
||||
}
|
||||
|
||||
vxlanName, err := createVxlan(n.vxlanID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := sbox.AddInterface(vxlanName, "vxlan",
|
||||
sbox.InterfaceOptions().Master("bridge1")); err != nil {
|
||||
return fmt.Errorf("could not add vxlan interface inside the network sandbox: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
n.vxlanName = vxlanName
|
||||
|
||||
n.setSandbox(sbox)
|
||||
|
||||
n.driver.peerDbUpdateSandbox(n.id)
|
||||
|
||||
var nlSock *nl.NetlinkSocket
|
||||
sbox.InvokeFunc(func() {
|
||||
nlSock, err = nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH)
|
||||
|
@ -182,7 +167,27 @@ func (n *network) initSandbox() error {
|
|||
})
|
||||
|
||||
go n.watchMiss(nlSock)
|
||||
return n.initVxlan()
|
||||
}
|
||||
|
||||
func (n *network) initVxlan() error {
|
||||
var vxlanName string
|
||||
n.Lock()
|
||||
sbox := n.sbox
|
||||
n.Unlock()
|
||||
|
||||
vxlanName, err := createVxlan(n.vxlanID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sbox.AddInterface(vxlanName, "vxlan",
|
||||
sbox.InterfaceOptions().Master("bridge1")); err != nil {
|
||||
return fmt.Errorf("could not add vxlan interface inside the network sandbox: %v", err)
|
||||
}
|
||||
|
||||
n.vxlanName = vxlanName
|
||||
n.driver.peerDbUpdateSandbox(n.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -35,46 +35,12 @@ func (l *logWriter) Write(p []byte) (int, error) {
|
|||
return len(p), nil
|
||||
}
|
||||
|
||||
func getBindAddr(ifaceName string) (string, error) {
|
||||
iface, err := net.InterfaceByName(ifaceName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to find interface %s: %v", ifaceName, err)
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get interface addresses: %v", err)
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
addr, ok := a.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
addrIP := addr.IP
|
||||
|
||||
if addrIP.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
return addrIP.String(), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to get bind address")
|
||||
}
|
||||
|
||||
func (d *driver) serfInit() error {
|
||||
var err error
|
||||
|
||||
config := serf.DefaultConfig()
|
||||
config.Init()
|
||||
if d.ifaceName != "" {
|
||||
bindAddr, err := getBindAddr(d.ifaceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getBindAddr error: %v", err)
|
||||
}
|
||||
config.MemberlistConfig.BindAddr = bindAddr
|
||||
}
|
||||
config.MemberlistConfig.BindAddr = d.bindAddress
|
||||
|
||||
d.eventCh = make(chan serf.Event, 4)
|
||||
config.EventCh = d.eventCh
|
||||
|
@ -93,13 +59,6 @@ func (d *driver) serfInit() error {
|
|||
}
|
||||
}()
|
||||
|
||||
if d.neighIP != "" {
|
||||
if _, err = s.Join([]string{d.neighIP}, false); err != nil {
|
||||
return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
||||
d.neighIP, err)
|
||||
}
|
||||
}
|
||||
|
||||
d.serfInstance = s
|
||||
|
||||
d.notifyCh = make(chan ovNotify)
|
||||
|
@ -109,6 +68,17 @@ func (d *driver) serfInit() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) serfJoin(neighIP string) error {
|
||||
if neighIP == "" {
|
||||
return fmt.Errorf("no neighbor to join")
|
||||
}
|
||||
if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
||||
return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
||||
neighIP, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) notifyEvent(event ovNotify) {
|
||||
n := d.network(event.nid)
|
||||
ep := n.endpoint(event.eid)
|
||||
|
@ -246,3 +216,13 @@ func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) isSerfAlive() bool {
|
||||
d.Lock()
|
||||
serfInstance := d.serfInstance
|
||||
d.Unlock()
|
||||
if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/config"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
|
@ -29,7 +30,7 @@ type driver struct {
|
|||
eventCh chan serf.Event
|
||||
notifyCh chan ovNotify
|
||||
exitCh chan chan struct{}
|
||||
ifaceName string
|
||||
bindAddress string
|
||||
neighIP string
|
||||
config map[string]interface{}
|
||||
peerDb peerNetworkMap
|
||||
|
@ -38,7 +39,8 @@ type driver struct {
|
|||
store datastore.DataStore
|
||||
ipAllocator *idm.Idm
|
||||
vxlanIdm *idm.Idm
|
||||
sync.Once
|
||||
once sync.Once
|
||||
joinOnce sync.Once
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
|
@ -107,15 +109,7 @@ func (d *driver) configure() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
d.Do(func() {
|
||||
if ifaceName, ok := d.config[netlabel.OverlayBindInterface]; ok {
|
||||
d.ifaceName = ifaceName.(string)
|
||||
}
|
||||
|
||||
if neighIP, ok := d.config[netlabel.OverlayNeighborIP]; ok {
|
||||
d.neighIP = neighIP.(string)
|
||||
}
|
||||
|
||||
d.once.Do(func() {
|
||||
provider, provOk := d.config[netlabel.KVProvider]
|
||||
provURL, urlOk := d.config[netlabel.KVProviderURL]
|
||||
|
||||
|
@ -148,12 +142,6 @@ func (d *driver) configure() error {
|
|||
err = fmt.Errorf("failed to initalize ipam id manager: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = d.serfInit()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("initializing serf instance failed: %v", err)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return err
|
||||
|
@ -162,3 +150,68 @@ func (d *driver) configure() error {
|
|||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) nodeJoin(node string, self bool) {
|
||||
if self && !d.isSerfAlive() {
|
||||
d.Lock()
|
||||
d.bindAddress = node
|
||||
d.Unlock()
|
||||
err := d.serfInit()
|
||||
if err != nil {
|
||||
logrus.Errorf("initializing serf instance failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
if !self {
|
||||
d.neighIP = node
|
||||
}
|
||||
neighIP := d.neighIP
|
||||
d.Unlock()
|
||||
|
||||
if d.serfInstance != nil && neighIP != "" {
|
||||
var err error
|
||||
d.joinOnce.Do(func() {
|
||||
err = d.serfJoin(neighIP)
|
||||
if err == nil {
|
||||
d.pushLocalDb()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("joining serf neighbor %s failed: %v", node, err)
|
||||
d.Lock()
|
||||
d.joinOnce = sync.Once{}
|
||||
d.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
||||
if !d.isSerfAlive() {
|
||||
return
|
||||
}
|
||||
d.notifyCh <- ovNotify{
|
||||
action: "join",
|
||||
nid: nid,
|
||||
eid: eid,
|
||||
}
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
if dType == driverapi.NodeDiscovery {
|
||||
nodeData, ok := data.(driverapi.NodeDiscoveryData)
|
||||
if !ok || nodeData.Address == "" {
|
||||
return fmt.Errorf("invalid discovery data")
|
||||
}
|
||||
d.nodeJoin(nodeData.Address, nodeData.Self)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -56,7 +56,23 @@ func (pKey *peerKey) Scan(state fmt.ScanState, verb rune) error {
|
|||
|
||||
var peerDbWg sync.WaitGroup
|
||||
|
||||
func (d *driver) peerDbWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
||||
func (d *driver) peerDbWalk(f func(string, *peerKey, *peerEntry) bool) error {
|
||||
d.peerDb.Lock()
|
||||
nids := []string{}
|
||||
for nid := range d.peerDb.mp {
|
||||
nids = append(nids, nid)
|
||||
}
|
||||
d.peerDb.Unlock()
|
||||
|
||||
for _, nid := range nids {
|
||||
d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
return f(nid, pKey, pEntry)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
||||
d.peerDb.Lock()
|
||||
pMap, ok := d.peerDb.mp[nid]
|
||||
if !ok {
|
||||
|
@ -89,7 +105,7 @@ func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.
|
|||
found bool
|
||||
)
|
||||
|
||||
err := d.peerDbWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
if pKey.peerIP.Equal(peerIP) {
|
||||
peerMac = pKey.peerMac
|
||||
vtep = pEntry.vtep
|
||||
|
@ -280,3 +296,12 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP,
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) pushLocalDb() {
|
||||
d.peerDbWalk(func(nid string, pKey *peerKey, pEntry *peerEntry) bool {
|
||||
if pEntry.isLocal {
|
||||
d.pushLocalEndpointEvent("join", nid, pEntry.eid)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,7 +4,11 @@ with a remote driver.
|
|||
*/
|
||||
package api
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
)
|
||||
|
||||
// Response is the basic response structure used in all responses.
|
||||
type Response struct {
|
||||
|
@ -143,3 +147,14 @@ type LeaveRequest struct {
|
|||
type LeaveResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// DiscoveryNotification represents a discovery notification
|
||||
type DiscoveryNotification struct {
|
||||
DiscoveryType driverapi.DiscoveryType
|
||||
DiscoveryData interface{}
|
||||
}
|
||||
|
||||
// DiscoveryResponse is used by libnetwork to log any plugin error processing the discovery notifications
|
||||
type DiscoveryResponse struct {
|
||||
Response
|
||||
}
|
||||
|
|
|
@ -247,6 +247,30 @@ func (d *driver) Type() string {
|
|||
return d.networkType
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
if dType != driverapi.NodeDiscovery {
|
||||
return fmt.Errorf("Unknown discovery type : %v", dType)
|
||||
}
|
||||
notif := &api.DiscoveryNotification{
|
||||
DiscoveryType: dType,
|
||||
DiscoveryData: data,
|
||||
}
|
||||
return d.call("DiscoverNew", notif, &api.DiscoveryResponse{})
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
if dType != driverapi.NodeDiscovery {
|
||||
return fmt.Errorf("Unknown discovery type : %v", dType)
|
||||
}
|
||||
notif := &api.DiscoveryNotification{
|
||||
DiscoveryType: dType,
|
||||
DiscoveryData: data,
|
||||
}
|
||||
return d.call("DiscoverDelete", notif, &api.DiscoveryResponse{})
|
||||
}
|
||||
|
||||
func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) {
|
||||
var routes = make([]*types.StaticRoute, len(r.StaticRoutes))
|
||||
for i, inRoute := range r.StaticRoutes {
|
||||
|
|
|
@ -52,3 +52,13 @@ func (d *driver) Leave(nid, eid string) error {
|
|||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,73 +1,48 @@
|
|||
// +build libnetwork_discovery
|
||||
|
||||
package hostdiscovery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
mapset "github.com/deckarep/golang-set"
|
||||
"github.com/docker/libnetwork/config"
|
||||
"github.com/docker/swarm/discovery"
|
||||
// Anonymous import will be removed after we upgrade to latest swarm
|
||||
_ "github.com/docker/swarm/discovery/file"
|
||||
// Anonymous import will be removed after we upgrade to latest swarm
|
||||
_ "github.com/docker/swarm/discovery/kv"
|
||||
// Anonymous import will be removed after we upgrade to latest swarm
|
||||
_ "github.com/docker/swarm/discovery/nodes"
|
||||
// Anonymous import will be removed after we upgrade to latest swarm
|
||||
_ "github.com/docker/swarm/discovery/token"
|
||||
"github.com/docker/docker/pkg/discovery"
|
||||
// Including KV
|
||||
_ "github.com/docker/docker/pkg/discovery/kv"
|
||||
"github.com/docker/libkv/store/consul"
|
||||
"github.com/docker/libkv/store/etcd"
|
||||
"github.com/docker/libkv/store/zookeeper"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const defaultHeartbeat = time.Duration(10) * time.Second
|
||||
const TTLFactor = 3
|
||||
|
||||
type hostDiscovery struct {
|
||||
discovery discovery.Discovery
|
||||
nodes mapset.Set
|
||||
stopChan chan struct{}
|
||||
watcher discovery.Watcher
|
||||
nodes mapset.Set
|
||||
stopChan chan struct{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewHostDiscovery function creates a host discovery object
|
||||
func NewHostDiscovery() HostDiscovery {
|
||||
return &hostDiscovery{nodes: mapset.NewSet(), stopChan: make(chan struct{})}
|
||||
func init() {
|
||||
consul.Register()
|
||||
etcd.Register()
|
||||
zookeeper.Register()
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) StartDiscovery(cfg *config.ClusterCfg, joinCallback JoinCallback, leaveCallback LeaveCallback) error {
|
||||
if cfg == nil {
|
||||
return fmt.Errorf("discovery requires a valid configuration")
|
||||
}
|
||||
|
||||
hb := time.Duration(cfg.Heartbeat) * time.Second
|
||||
if hb == 0 {
|
||||
hb = defaultHeartbeat
|
||||
}
|
||||
d, err := discovery.New(cfg.Discovery, hb, TTLFactor*hb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ip := net.ParseIP(cfg.Address); ip == nil {
|
||||
return errors.New("address config should be either ipv4 or ipv6 address")
|
||||
}
|
||||
|
||||
if err := d.Register(cfg.Address + ":0"); err != nil {
|
||||
return err
|
||||
}
|
||||
// NewHostDiscovery function creates a host discovery object
|
||||
func NewHostDiscovery(watcher discovery.Watcher) HostDiscovery {
|
||||
return &hostDiscovery{watcher: watcher, nodes: mapset.NewSet(), stopChan: make(chan struct{})}
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) Watch(joinCallback JoinCallback, leaveCallback LeaveCallback) error {
|
||||
h.Lock()
|
||||
h.discovery = d
|
||||
d := h.watcher
|
||||
h.Unlock()
|
||||
|
||||
if d == nil {
|
||||
return types.BadRequestErrorf("invalid discovery watcher")
|
||||
}
|
||||
discoveryCh, errCh := d.Watch(h.stopChan)
|
||||
go h.monitorDiscovery(discoveryCh, errCh, joinCallback, leaveCallback)
|
||||
go h.sustainHeartbeat(d, hb, cfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -77,7 +52,9 @@ func (h *hostDiscovery) monitorDiscovery(ch <-chan discovery.Entries, errCh <-ch
|
|||
case entries := <-ch:
|
||||
h.processCallback(entries, joinCallback, leaveCallback)
|
||||
case err := <-errCh:
|
||||
log.Errorf("discovery error: %v", err)
|
||||
if err != nil {
|
||||
log.Errorf("discovery error: %v", err)
|
||||
}
|
||||
case <-h.stopChan:
|
||||
return
|
||||
}
|
||||
|
@ -87,26 +64,13 @@ func (h *hostDiscovery) monitorDiscovery(ch <-chan discovery.Entries, errCh <-ch
|
|||
func (h *hostDiscovery) StopDiscovery() error {
|
||||
h.Lock()
|
||||
stopChan := h.stopChan
|
||||
h.discovery = nil
|
||||
h.watcher = nil
|
||||
h.Unlock()
|
||||
|
||||
close(stopChan)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) sustainHeartbeat(d discovery.Discovery, hb time.Duration, config *config.ClusterCfg) {
|
||||
for {
|
||||
select {
|
||||
case <-h.stopChan:
|
||||
return
|
||||
case <-time.After(hb):
|
||||
if err := d.Register(config.Address + ":0"); err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) processCallback(entries discovery.Entries, joinCallback JoinCallback, leaveCallback LeaveCallback) {
|
||||
updated := hosts(entries)
|
||||
h.Lock()
|
||||
|
@ -135,14 +99,14 @@ func diff(existing mapset.Set, updated mapset.Set) (added []net.IP, removed []ne
|
|||
return
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) Fetch() ([]net.IP, error) {
|
||||
func (h *hostDiscovery) Fetch() []net.IP {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
ips := []net.IP{}
|
||||
for _, ipstr := range h.nodes.ToSlice() {
|
||||
ips = append(ips, net.ParseIP(ipstr.(string)))
|
||||
}
|
||||
return ips, nil
|
||||
return ips
|
||||
}
|
||||
|
||||
func hosts(entries discovery.Entries) mapset.Set {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package hostdiscovery
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/config"
|
||||
)
|
||||
import "net"
|
||||
|
||||
// JoinCallback provides a callback event for new node joining the cluster
|
||||
type JoinCallback func(entries []net.IP)
|
||||
|
@ -14,10 +10,10 @@ type LeaveCallback func(entries []net.IP)
|
|||
|
||||
// HostDiscovery primary interface
|
||||
type HostDiscovery interface {
|
||||
// StartDiscovery initiates the discovery process and provides appropriate callbacks
|
||||
StartDiscovery(*config.ClusterCfg, JoinCallback, LeaveCallback) error
|
||||
//Watch Node join and leave cluster events
|
||||
Watch(joinCallback JoinCallback, leaveCallback LeaveCallback) error
|
||||
// StopDiscovery stops the discovery perocess
|
||||
StopDiscovery() error
|
||||
// Fetch returns a list of host IPs that are currently discovered
|
||||
Fetch() ([]net.IP, error)
|
||||
Fetch() []net.IP
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
// +build !libnetwork_discovery
|
||||
|
||||
package hostdiscovery
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/config"
|
||||
)
|
||||
|
||||
type hostDiscovery struct{}
|
||||
|
||||
// NewHostDiscovery function creates a host discovery object
|
||||
func NewHostDiscovery() HostDiscovery {
|
||||
return &hostDiscovery{}
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) StartDiscovery(cfg *config.ClusterCfg, joinCallback JoinCallback, leaveCallback LeaveCallback) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) StopDiscovery() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *hostDiscovery) Fetch() ([]net.IP, error) {
|
||||
return []net.IP{}, nil
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
title = "LibNetwork Configuration file"
|
||||
|
||||
[cluster]
|
||||
discovery = "token://08469efb104bce980931ed24c8eb03a2"
|
||||
Address = "1.1.1.1"
|
||||
discovery = "consul://localhost:8500"
|
||||
Address = "6.5.5.5"
|
||||
Heartbeat = 3
|
||||
|
|
Loading…
Add table
Reference in a new issue