Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
| ... | ... |
@@ -3,7 +3,7 @@ |
| 3 | 3 |
# LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When |
| 4 | 4 |
# updating the binary version, consider updating github.com/docker/libnetwork |
| 5 | 5 |
# in vendor.conf accordingly |
| 6 |
-LIBNETWORK_COMMIT=3ac297bc7fd0afec9051bbb47024c9bc1d75bf5b |
|
| 6 |
+LIBNETWORK_COMMIT=f30a35b091cc2a431ef9856c75c343f75bb5f2e2 |
|
| 7 | 7 |
|
| 8 | 8 |
install_proxy() {
|
| 9 | 9 |
case "$1" in |
| ... | ... |
@@ -37,7 +37,7 @@ github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b |
| 37 | 37 |
#get libnetwork packages |
| 38 | 38 |
|
| 39 | 39 |
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly |
| 40 |
-github.com/docker/libnetwork d00ceed44cc447c77f25cdf5d59e83163bdcb4c9 |
|
| 40 |
+github.com/docker/libnetwork f30a35b091cc2a431ef9856c75c343f75bb5f2e2 |
|
| 41 | 41 |
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 |
| 42 | 42 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 43 | 43 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -15,6 +15,17 @@ There are many networking solutions available to suit a broad range of use-cases |
| 15 | 15 |
|
| 16 | 16 |
|
| 17 | 17 |
```go |
| 18 |
+import ( |
|
| 19 |
+ "fmt" |
|
| 20 |
+ "log" |
|
| 21 |
+ |
|
| 22 |
+ "github.com/docker/docker/pkg/reexec" |
|
| 23 |
+ "github.com/docker/libnetwork" |
|
| 24 |
+ "github.com/docker/libnetwork/config" |
|
| 25 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 26 |
+ "github.com/docker/libnetwork/options" |
|
| 27 |
+) |
|
| 28 |
+ |
|
| 18 | 29 |
func main() {
|
| 19 | 30 |
if reexec.Init() {
|
| 20 | 31 |
return |
| ... | ... |
@@ -194,7 +194,7 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
| 194 | 194 |
func (c *controller) agentSetup(clusterProvider cluster.Provider) error {
|
| 195 | 195 |
agent := c.getAgent() |
| 196 | 196 |
|
| 197 |
- // If the agent is already present there is no need to try to initilize it again |
|
| 197 |
+ // If the agent is already present there is no need to try to initialize it again |
|
| 198 | 198 |
if agent != nil {
|
| 199 | 199 |
return nil |
| 200 | 200 |
} |
| ... | ... |
@@ -372,7 +372,7 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial |
| 372 | 372 |
h.Lock() |
| 373 | 373 |
} |
| 374 | 374 |
|
| 375 |
- // Previous atomic push was succesfull. Save private copy to local copy |
|
| 375 |
+ // Previous atomic push was successful. Save private copy to local copy |
|
| 376 | 376 |
h.unselected = nh.unselected |
| 377 | 377 |
h.head = nh.head |
| 378 | 378 |
h.dbExists = nh.dbExists |
| 379 | 379 |
deleted file mode 100644 |
| ... | ... |
@@ -1,29 +0,0 @@ |
| 1 |
-package common |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "runtime" |
|
| 5 |
- "strings" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func callerInfo(i int) string {
|
|
| 9 |
- ptr, _, _, ok := runtime.Caller(i) |
|
| 10 |
- fName := "unknown" |
|
| 11 |
- if ok {
|
|
| 12 |
- f := runtime.FuncForPC(ptr) |
|
| 13 |
- if f != nil {
|
|
| 14 |
- // f.Name() is like: github.com/docker/libnetwork/common.MethodName |
|
| 15 |
- tmp := strings.Split(f.Name(), ".") |
|
| 16 |
- if len(tmp) > 0 {
|
|
| 17 |
- fName = tmp[len(tmp)-1] |
|
| 18 |
- } |
|
| 19 |
- } |
|
| 20 |
- } |
|
| 21 |
- |
|
| 22 |
- return fName |
|
| 23 |
-} |
|
| 24 |
- |
|
| 25 |
-// CallerName returns the name of the function at the specified level |
|
| 26 |
-// level == 0 means current method name |
|
| 27 |
-func CallerName(level int) string {
|
|
| 28 |
- return callerInfo(2 + level) |
|
| 29 |
-} |
| 30 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,135 +0,0 @@ |
| 1 |
-package common |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "sync" |
|
| 5 |
- |
|
| 6 |
- mapset "github.com/deckarep/golang-set" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-// SetMatrix is a map of Sets |
|
| 10 |
-type SetMatrix interface {
|
|
| 11 |
- // Get returns the members of the set for a specific key as a slice. |
|
| 12 |
- Get(key string) ([]interface{}, bool)
|
|
| 13 |
- // Contains is used to verify if an element is in a set for a specific key |
|
| 14 |
- // returns true if the element is in the set |
|
| 15 |
- // returns true if there is a set for the key |
|
| 16 |
- Contains(key string, value interface{}) (bool, bool)
|
|
| 17 |
- // Insert inserts the value in the set of a key |
|
| 18 |
- // returns true if the value is inserted (was not already in the set), false otherwise |
|
| 19 |
- // returns also the length of the set for the key |
|
| 20 |
- Insert(key string, value interface{}) (bool, int)
|
|
| 21 |
- // Remove removes the value in the set for a specific key |
|
| 22 |
- // returns true if the value is deleted, false otherwise |
|
| 23 |
- // returns also the length of the set for the key |
|
| 24 |
- Remove(key string, value interface{}) (bool, int)
|
|
| 25 |
- // Cardinality returns the number of elements in the set for a key |
|
| 26 |
- // returns false if the set is not present |
|
| 27 |
- Cardinality(key string) (int, bool) |
|
| 28 |
- // String returns the string version of the set, empty otherwise |
|
| 29 |
- // returns false if the set is not present |
|
| 30 |
- String(key string) (string, bool) |
|
| 31 |
- // Returns all the keys in the map |
|
| 32 |
- Keys() []string |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-type setMatrix struct {
|
|
| 36 |
- matrix map[string]mapset.Set |
|
| 37 |
- |
|
| 38 |
- sync.Mutex |
|
| 39 |
-} |
|
| 40 |
- |
|
| 41 |
-// NewSetMatrix creates a new set matrix object |
|
| 42 |
-func NewSetMatrix() SetMatrix {
|
|
| 43 |
- s := &setMatrix{}
|
|
| 44 |
- s.init() |
|
| 45 |
- return s |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-func (s *setMatrix) init() {
|
|
| 49 |
- s.matrix = make(map[string]mapset.Set) |
|
| 50 |
-} |
|
| 51 |
- |
|
| 52 |
-func (s *setMatrix) Get(key string) ([]interface{}, bool) {
|
|
| 53 |
- s.Lock() |
|
| 54 |
- defer s.Unlock() |
|
| 55 |
- set, ok := s.matrix[key] |
|
| 56 |
- if !ok {
|
|
| 57 |
- return nil, ok |
|
| 58 |
- } |
|
| 59 |
- return set.ToSlice(), ok |
|
| 60 |
-} |
|
| 61 |
- |
|
| 62 |
-func (s *setMatrix) Contains(key string, value interface{}) (bool, bool) {
|
|
| 63 |
- s.Lock() |
|
| 64 |
- defer s.Unlock() |
|
| 65 |
- set, ok := s.matrix[key] |
|
| 66 |
- if !ok {
|
|
| 67 |
- return false, ok |
|
| 68 |
- } |
|
| 69 |
- return set.Contains(value), ok |
|
| 70 |
-} |
|
| 71 |
- |
|
| 72 |
-func (s *setMatrix) Insert(key string, value interface{}) (bool, int) {
|
|
| 73 |
- s.Lock() |
|
| 74 |
- defer s.Unlock() |
|
| 75 |
- set, ok := s.matrix[key] |
|
| 76 |
- if !ok {
|
|
| 77 |
- s.matrix[key] = mapset.NewSet() |
|
| 78 |
- s.matrix[key].Add(value) |
|
| 79 |
- return true, 1 |
|
| 80 |
- } |
|
| 81 |
- |
|
| 82 |
- return set.Add(value), set.Cardinality() |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-func (s *setMatrix) Remove(key string, value interface{}) (bool, int) {
|
|
| 86 |
- s.Lock() |
|
| 87 |
- defer s.Unlock() |
|
| 88 |
- set, ok := s.matrix[key] |
|
| 89 |
- if !ok {
|
|
| 90 |
- return false, 0 |
|
| 91 |
- } |
|
| 92 |
- |
|
| 93 |
- var removed bool |
|
| 94 |
- if set.Contains(value) {
|
|
| 95 |
- set.Remove(value) |
|
| 96 |
- removed = true |
|
| 97 |
- // If the set is empty remove it from the matrix |
|
| 98 |
- if set.Cardinality() == 0 {
|
|
| 99 |
- delete(s.matrix, key) |
|
| 100 |
- } |
|
| 101 |
- } |
|
| 102 |
- |
|
| 103 |
- return removed, set.Cardinality() |
|
| 104 |
-} |
|
| 105 |
- |
|
| 106 |
-func (s *setMatrix) Cardinality(key string) (int, bool) {
|
|
| 107 |
- s.Lock() |
|
| 108 |
- defer s.Unlock() |
|
| 109 |
- set, ok := s.matrix[key] |
|
| 110 |
- if !ok {
|
|
| 111 |
- return 0, ok |
|
| 112 |
- } |
|
| 113 |
- |
|
| 114 |
- return set.Cardinality(), ok |
|
| 115 |
-} |
|
| 116 |
- |
|
| 117 |
-func (s *setMatrix) String(key string) (string, bool) {
|
|
| 118 |
- s.Lock() |
|
| 119 |
- defer s.Unlock() |
|
| 120 |
- set, ok := s.matrix[key] |
|
| 121 |
- if !ok {
|
|
| 122 |
- return "", ok |
|
| 123 |
- } |
|
| 124 |
- return set.String(), ok |
|
| 125 |
-} |
|
| 126 |
- |
|
| 127 |
-func (s *setMatrix) Keys() []string {
|
|
| 128 |
- s.Lock() |
|
| 129 |
- defer s.Unlock() |
|
| 130 |
- keys := make([]string, 0, len(s.matrix)) |
|
| 131 |
- for k := range s.matrix {
|
|
| 132 |
- keys = append(keys, k) |
|
| 133 |
- } |
|
| 134 |
- return keys |
|
| 135 |
-} |
| ... | ... |
@@ -121,7 +121,7 @@ type NetworkController interface {
|
| 121 | 121 |
// Stop network controller |
| 122 | 122 |
Stop() |
| 123 | 123 |
|
| 124 |
- // ReloadCondfiguration updates the controller configuration |
|
| 124 |
+ // ReloadConfiguration updates the controller configuration |
|
| 125 | 125 |
ReloadConfiguration(cfgOptions ...config.Option) error |
| 126 | 126 |
|
| 127 | 127 |
// SetClusterProvider sets cluster provider |
| ... | ... |
@@ -1107,6 +1107,8 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S |
| 1107 | 1107 |
sb.config.hostsPath = filepath.Join(c.cfg.Daemon.DataDir, "/network/files/hosts") |
| 1108 | 1108 |
sb.config.resolvConfPath = filepath.Join(c.cfg.Daemon.DataDir, "/network/files/resolv.conf") |
| 1109 | 1109 |
sb.id = "ingress_sbox" |
| 1110 |
+ } else if sb.loadBalancerNID != "" {
|
|
| 1111 |
+ sb.id = "lb_" + sb.loadBalancerNID |
|
| 1110 | 1112 |
} |
| 1111 | 1113 |
c.Unlock() |
| 1112 | 1114 |
|
| ... | ... |
@@ -185,7 +185,7 @@ func Key(key ...string) string {
|
| 185 | 185 |
func ParseKey(key string) ([]string, error) {
|
| 186 | 186 |
chain := strings.Split(strings.Trim(key, "/"), "/") |
| 187 | 187 |
|
| 188 |
- // The key must atleast be equal to the rootChain in order to be considered as valid |
|
| 188 |
+ // The key must at least be equal to the rootChain in order to be considered as valid |
|
| 189 | 189 |
if len(chain) <= len(rootChain) || !reflect.DeepEqual(chain[0:len(rootChain)], rootChain) {
|
| 190 | 190 |
return nil, types.BadRequestErrorf("invalid Key : %s", key)
|
| 191 | 191 |
} |
| ... | ... |
@@ -589,7 +589,7 @@ func (ds *datastore) DeleteObject(kvObject KVObject) error {
|
| 589 | 589 |
defer ds.Unlock() |
| 590 | 590 |
} |
| 591 | 591 |
|
| 592 |
- // cleaup the cache first |
|
| 592 |
+ // cleanup the cache first |
|
| 593 | 593 |
if ds.cache != nil {
|
| 594 | 594 |
// If persistent store is skipped, sequencing needs to |
| 595 | 595 |
// happen in cache. |
| ... | ... |
@@ -645,7 +645,7 @@ func (ds *datastore) DeleteTree(kvObject KVObject) error {
|
| 645 | 645 |
defer ds.Unlock() |
| 646 | 646 |
} |
| 647 | 647 |
|
| 648 |
- // cleaup the cache first |
|
| 648 |
+ // cleanup the cache first |
|
| 649 | 649 |
if ds.cache != nil {
|
| 650 | 650 |
// If persistent store is skipped, sequencing needs to |
| 651 | 651 |
// happen in cache. |
| ... | ... |
@@ -8,8 +8,8 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
var ( |
| 11 |
- // ErrNotImplmented exported |
|
| 12 |
- ErrNotImplmented = errors.New("Functionality not implemented")
|
|
| 11 |
+ // ErrNotImplemented exported |
|
| 12 |
+ ErrNotImplemented = errors.New("Functionality not implemented")
|
|
| 13 | 13 |
) |
| 14 | 14 |
|
| 15 | 15 |
// MockData exported |
| ... | ... |
@@ -65,7 +65,7 @@ func (s *MockStore) Exists(key string) (bool, error) {
|
| 65 | 65 |
|
| 66 | 66 |
// List gets a range of values at "directory" |
| 67 | 67 |
func (s *MockStore) List(prefix string) ([]*store.KVPair, error) {
|
| 68 |
- return nil, ErrNotImplmented |
|
| 68 |
+ return nil, ErrNotImplemented |
|
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 | 71 |
// DeleteTree deletes a range of values at "directory" |
| ... | ... |
@@ -76,17 +76,17 @@ func (s *MockStore) DeleteTree(prefix string) error {
|
| 76 | 76 |
|
| 77 | 77 |
// Watch a single key for modifications |
| 78 | 78 |
func (s *MockStore) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) {
|
| 79 |
- return nil, ErrNotImplmented |
|
| 79 |
+ return nil, ErrNotImplemented |
|
| 80 | 80 |
} |
| 81 | 81 |
|
| 82 | 82 |
// WatchTree triggers a watch on a range of values at "directory" |
| 83 | 83 |
func (s *MockStore) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) {
|
| 84 |
- return nil, ErrNotImplmented |
|
| 84 |
+ return nil, ErrNotImplemented |
|
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 | 87 |
// NewLock exposed |
| 88 | 88 |
func (s *MockStore) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
|
| 89 |
- return nil, ErrNotImplmented |
|
| 89 |
+ return nil, ErrNotImplemented |
|
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 | 92 |
// AtomicPut put a value at "key" if the key has not been |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"sync/atomic" |
| 10 | 10 |
|
| 11 | 11 |
stackdump "github.com/docker/docker/pkg/signal" |
| 12 |
- "github.com/docker/libnetwork/common" |
|
| 12 |
+ "github.com/docker/libnetwork/internal/caller" |
|
| 13 | 13 |
"github.com/sirupsen/logrus" |
| 14 | 14 |
) |
| 15 | 15 |
|
| ... | ... |
@@ -127,7 +127,7 @@ func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 127 | 127 |
rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path))
|
| 128 | 128 |
|
| 129 | 129 |
// audit logs |
| 130 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 130 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 131 | 131 |
log.Info("command not implemented done")
|
| 132 | 132 |
|
| 133 | 133 |
HTTPReply(w, rsp, json) |
| ... | ... |
@@ -138,7 +138,7 @@ func help(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 138 | 138 |
_, json := ParseHTTPFormOptions(r) |
| 139 | 139 |
|
| 140 | 140 |
// audit logs |
| 141 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 141 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 142 | 142 |
log.Info("help done")
|
| 143 | 143 |
|
| 144 | 144 |
n, ok := ctx.(*Server) |
| ... | ... |
@@ -156,7 +156,7 @@ func ready(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 156 | 156 |
_, json := ParseHTTPFormOptions(r) |
| 157 | 157 |
|
| 158 | 158 |
// audit logs |
| 159 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 159 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 160 | 160 |
log.Info("ready done")
|
| 161 | 161 |
HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), json)
|
| 162 | 162 |
} |
| ... | ... |
@@ -166,7 +166,7 @@ func stackTrace(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 166 | 166 |
_, json := ParseHTTPFormOptions(r) |
| 167 | 167 |
|
| 168 | 168 |
// audit logs |
| 169 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 169 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 170 | 170 |
log.Info("stack trace")
|
| 171 | 171 |
|
| 172 | 172 |
path, err := stackdump.DumpStacks("/tmp/")
|
| ... | ... |
@@ -75,10 +75,10 @@ type Driver interface {
|
| 75 | 75 |
// DecodeTableEntry passes the driver a key, value pair from table it registered |
| 76 | 76 |
// with libnetwork. Driver should return {object ID, map[string]string} tuple.
|
| 77 | 77 |
// If DecodeTableEntry is called for a table associated with NetworkObject or |
| 78 |
- // EndpointObject the return object ID should be the network id or endppoint id |
|
| 78 |
+ // EndpointObject the return object ID should be the network id or endpoint id |
|
| 79 | 79 |
// associated with that entry. map should have information about the object that |
| 80 | 80 |
// can be presented to the user. |
| 81 |
- // For exampe: overlay driver returns the VTEP IP of the host that has the endpoint |
|
| 81 |
+ // For example: overlay driver returns the VTEP IP of the host that has the endpoint |
|
| 82 | 82 |
// which is shown in 'network inspect --verbose' |
| 83 | 83 |
DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) |
| 84 | 84 |
|
| ... | ... |
@@ -97,7 +97,7 @@ type NetworkInfo interface {
|
| 97 | 97 |
TableEventRegister(tableName string, objType ObjectType) error |
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 |
-// InterfaceInfo provides a go interface for drivers to retrive |
|
| 100 |
+// InterfaceInfo provides a go interface for drivers to retrieve |
|
| 101 | 101 |
// network information to interface resources. |
| 102 | 102 |
type InterfaceInfo interface {
|
| 103 | 103 |
// SetMacAddress allows the driver to set the mac address to the endpoint interface |
| ... | ... |
@@ -104,7 +104,7 @@ type containerConfiguration struct {
|
| 104 | 104 |
ChildEndpoints []string |
| 105 | 105 |
} |
| 106 | 106 |
|
| 107 |
-// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity |
|
| 107 |
+// connectivityConfiguration represents the user specified configuration regarding the external connectivity |
|
| 108 | 108 |
type connectivityConfiguration struct {
|
| 109 | 109 |
PortBindings []types.PortBinding |
| 110 | 110 |
ExposedPorts []types.TransportPort |
| ... | ... |
@@ -84,7 +84,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 84 | 84 |
} |
| 85 | 85 |
v4gw, _, err := net.ParseCIDR(s.GwIP) |
| 86 | 86 |
if err != nil {
|
| 87 |
- return fmt.Errorf("gatway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
|
| 87 |
+ return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
|
| 88 | 88 |
} |
| 89 | 89 |
err = jinfo.SetGateway(v4gw) |
| 90 | 90 |
if err != nil {
|
| ... | ... |
@@ -101,7 +101,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 101 | 101 |
} |
| 102 | 102 |
v6gw, _, err := net.ParseCIDR(s.GwIP) |
| 103 | 103 |
if err != nil {
|
| 104 |
- return fmt.Errorf("gatway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
|
| 104 |
+ return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
|
| 105 | 105 |
} |
| 106 | 106 |
err = jinfo.SetGatewayIPv6(v6gw) |
| 107 | 107 |
if err != nil {
|
| ... | ... |
@@ -68,7 +68,7 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
|
| 68 | 68 |
err = d.storeUpdate(config) |
| 69 | 69 |
if err != nil {
|
| 70 | 70 |
d.deleteNetwork(config.ID) |
| 71 |
- logrus.Debugf("encoutered an error rolling back a network create for %s : %v", config.ID, err)
|
|
| 71 |
+ logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
|
|
| 72 | 72 |
return err |
| 73 | 73 |
} |
| 74 | 74 |
|
| ... | ... |
@@ -92,7 +92,7 @@ func (d *driver) createNetwork(config *configuration) error {
|
| 92 | 92 |
return err |
| 93 | 93 |
} |
| 94 | 94 |
config.CreatedSlaveLink = true |
| 95 |
- // notify the user in logs they have limited comunicatins |
|
| 95 |
+ // notify the user in logs they have limited communications |
|
| 96 | 96 |
if config.Parent == getDummyName(stringid.TruncateID(config.ID)) {
|
| 97 | 97 |
logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s",
|
| 98 | 98 |
config.Parent) |
| ... | ... |
@@ -30,7 +30,7 @@ func createIPVlan(containerIfName, parent, ipvlanMode string) (string, error) {
|
| 30 | 30 |
// Get the link for the master index (Example: the docker host eth iface) |
| 31 | 31 |
parentLink, err := ns.NlHandle().LinkByName(parent) |
| 32 | 32 |
if err != nil {
|
| 33 |
- return "", fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", ipvlanType, parent, err)
|
|
| 33 |
+ return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, parent, err)
|
|
| 34 | 34 |
} |
| 35 | 35 |
// Create an ipvlan link |
| 36 | 36 |
ipvlan := &netlink.IPVlan{
|
| ... | ... |
@@ -169,7 +169,7 @@ func createDummyLink(dummyName, truncNetID string) error {
|
| 169 | 169 |
} |
| 170 | 170 |
parentDummyLink, err := ns.NlHandle().LinkByName(dummyName) |
| 171 | 171 |
if err != nil {
|
| 172 |
- return fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", ipvlanType, dummyName, err)
|
|
| 172 |
+ return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, dummyName, err)
|
|
| 173 | 173 |
} |
| 174 | 174 |
// bring the new netlink iface up |
| 175 | 175 |
if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil {
|
| ... | ... |
@@ -31,7 +31,7 @@ func (d *driver) deleteNetwork(nid string) {
|
| 31 | 31 |
d.Unlock() |
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 |
-// getNetworks Safely returns a slice of existng networks |
|
| 34 |
+// getNetworks Safely returns a slice of existing networks |
|
| 35 | 35 |
func (d *driver) getNetworks() []*network {
|
| 36 | 36 |
d.Lock() |
| 37 | 37 |
defer d.Unlock() |
| ... | ... |
@@ -46,7 +46,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 46 | 46 |
} |
| 47 | 47 |
v4gw, _, err := net.ParseCIDR(s.GwIP) |
| 48 | 48 |
if err != nil {
|
| 49 |
- return fmt.Errorf("gatway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
|
| 49 |
+ return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
|
| 50 | 50 |
} |
| 51 | 51 |
err = jinfo.SetGateway(v4gw) |
| 52 | 52 |
if err != nil {
|
| ... | ... |
@@ -63,7 +63,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 63 | 63 |
} |
| 64 | 64 |
v6gw, _, err := net.ParseCIDR(s.GwIP) |
| 65 | 65 |
if err != nil {
|
| 66 |
- return fmt.Errorf("gatway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
|
| 66 |
+ return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
|
| 67 | 67 |
} |
| 68 | 68 |
err = jinfo.SetGatewayIPv6(v6gw) |
| 69 | 69 |
if err != nil {
|
| ... | ... |
@@ -72,7 +72,7 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo
|
| 72 | 72 |
err = d.storeUpdate(config) |
| 73 | 73 |
if err != nil {
|
| 74 | 74 |
d.deleteNetwork(config.ID) |
| 75 |
- logrus.Debugf("encoutered an error rolling back a network create for %s : %v", config.ID, err)
|
|
| 75 |
+ logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
|
|
| 76 | 76 |
return err |
| 77 | 77 |
} |
| 78 | 78 |
|
| ... | ... |
@@ -96,7 +96,7 @@ func (d *driver) createNetwork(config *configuration) error {
|
| 96 | 96 |
return err |
| 97 | 97 |
} |
| 98 | 98 |
config.CreatedSlaveLink = true |
| 99 |
- // notify the user in logs they have limited comunicatins |
|
| 99 |
+ // notify the user in logs they have limited communications |
|
| 100 | 100 |
if config.Parent == getDummyName(stringid.TruncateID(config.ID)) {
|
| 101 | 101 |
logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s",
|
| 102 | 102 |
config.Parent) |
| ... | ... |
@@ -30,7 +30,7 @@ func createMacVlan(containerIfName, parent, macvlanMode string) (string, error) |
| 30 | 30 |
// Get the link for the master index (Example: the docker host eth iface) |
| 31 | 31 |
parentLink, err := ns.NlHandle().LinkByName(parent) |
| 32 | 32 |
if err != nil {
|
| 33 |
- return "", fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", macvlanType, parent, err)
|
|
| 33 |
+ return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, parent, err)
|
|
| 34 | 34 |
} |
| 35 | 35 |
// Create a macvlan link |
| 36 | 36 |
macvlan := &netlink.Macvlan{
|
| ... | ... |
@@ -173,7 +173,7 @@ func createDummyLink(dummyName, truncNetID string) error {
|
| 173 | 173 |
} |
| 174 | 174 |
parentDummyLink, err := ns.NlHandle().LinkByName(dummyName) |
| 175 | 175 |
if err != nil {
|
| 176 |
- return fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", macvlanType, dummyName, err)
|
|
| 176 |
+ return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, dummyName, err)
|
|
| 177 | 177 |
} |
| 178 | 178 |
// bring the new netlink iface up |
| 179 | 179 |
if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil {
|
| ... | ... |
@@ -601,7 +601,7 @@ func (n *network) maxMTU() int {
|
| 601 | 601 |
mtu -= vxlanEncap |
| 602 | 602 |
if n.secure {
|
| 603 | 603 |
// In case of encryption account for the |
| 604 |
- // esp packet espansion and padding |
|
| 604 |
+ // esp packet expansion and padding |
|
| 605 | 605 |
mtu -= pktExpansion |
| 606 | 606 |
mtu -= (mtu % 4) |
| 607 | 607 |
} |
| ... | ... |
@@ -47,18 +47,10 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 47 | 47 |
return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 |
- if err := n.joinSandbox(false); err != nil {
|
|
| 50 |
+ if err := n.joinSandbox(s, false, true); err != nil {
|
|
| 51 | 51 |
return fmt.Errorf("network sandbox join failed: %v", err)
|
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
- if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 55 |
- return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- // joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the |
|
| 59 |
- // overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox |
|
| 60 |
- n.incEndpointCount() |
|
| 61 |
- |
|
| 62 | 54 |
sbox := n.sandbox() |
| 63 | 55 |
|
| 64 | 56 |
overlayIfName, containerIfName, err := createVethPair() |
| ... | ... |
@@ -39,7 +39,7 @@ var ( |
| 39 | 39 |
type networkTable map[string]*network |
| 40 | 40 |
|
| 41 | 41 |
type subnet struct {
|
| 42 |
- once *sync.Once |
|
| 42 |
+ sboxInit bool |
|
| 43 | 43 |
vxlanName string |
| 44 | 44 |
brName string |
| 45 | 45 |
vni uint32 |
| ... | ... |
@@ -63,7 +63,7 @@ type network struct {
|
| 63 | 63 |
endpoints endpointTable |
| 64 | 64 |
driver *driver |
| 65 | 65 |
joinCnt int |
| 66 |
- once *sync.Once |
|
| 66 |
+ sboxInit bool |
|
| 67 | 67 |
initEpoch int |
| 68 | 68 |
initErr error |
| 69 | 69 |
subnets []*subnet |
| ... | ... |
@@ -150,7 +150,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 150 | 150 |
id: id, |
| 151 | 151 |
driver: d, |
| 152 | 152 |
endpoints: endpointTable{},
|
| 153 |
- once: &sync.Once{},
|
|
| 154 | 153 |
subnets: []*subnet{},
|
| 155 | 154 |
} |
| 156 | 155 |
|
| ... | ... |
@@ -193,7 +192,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 193 | 193 |
s := &subnet{
|
| 194 | 194 |
subnetIP: ipd.Pool, |
| 195 | 195 |
gwIP: ipd.Gateway, |
| 196 |
- once: &sync.Once{},
|
|
| 197 | 196 |
} |
| 198 | 197 |
|
| 199 | 198 |
if len(vnis) != 0 {
|
| ... | ... |
@@ -277,7 +275,7 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 277 | 277 |
logrus.Warnf("Failed to delete overlay endpoint %.7s from local store: %v", ep.id, err)
|
| 278 | 278 |
} |
| 279 | 279 |
} |
| 280 |
- // flush the peerDB entries |
|
| 280 |
+ |
|
| 281 | 281 |
doPeerFlush = true |
| 282 | 282 |
delete(d.networks, nid) |
| 283 | 283 |
|
| ... | ... |
@@ -304,29 +302,54 @@ func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
| 304 | 304 |
return nil |
| 305 | 305 |
} |
| 306 | 306 |
|
| 307 |
-func (n *network) incEndpointCount() {
|
|
| 308 |
- n.Lock() |
|
| 309 |
- defer n.Unlock() |
|
| 310 |
- n.joinCnt++ |
|
| 311 |
-} |
|
| 312 |
- |
|
| 313 |
-func (n *network) joinSandbox(restore bool) error {
|
|
| 307 |
+func (n *network) joinSandbox(s *subnet, restore bool, incJoinCount bool) error {
|
|
| 314 | 308 |
// If there is a race between two go routines here only one will win |
| 315 | 309 |
// the other will wait. |
| 316 |
- n.once.Do(func() {
|
|
| 317 |
- // save the error status of initSandbox in n.initErr so that |
|
| 318 |
- // all the racing go routines are able to know the status. |
|
| 310 |
+ networkOnce.Do(networkOnceInit) |
|
| 311 |
+ |
|
| 312 |
+ n.Lock() |
|
| 313 |
+ // If non-restore initialization occurred and was successful then |
|
| 314 |
+ // tell the peerDB to initialize the sandbox with all the peers |
|
| 315 |
+ // previously received from networkdb. But only do this after |
|
| 316 |
+ // unlocking the network. Otherwise we could deadlock with |
|
| 317 |
+ // on the peerDB channel while peerDB is waiting for the network lock. |
|
| 318 |
+ var doInitPeerDB bool |
|
| 319 |
+ defer func() {
|
|
| 320 |
+ n.Unlock() |
|
| 321 |
+ if doInitPeerDB {
|
|
| 322 |
+ n.driver.initSandboxPeerDB(n.id) |
|
| 323 |
+ } |
|
| 324 |
+ }() |
|
| 325 |
+ |
|
| 326 |
+ if !n.sboxInit {
|
|
| 319 | 327 |
n.initErr = n.initSandbox(restore) |
| 320 |
- }) |
|
| 328 |
+ doInitPeerDB = n.initErr == nil && !restore |
|
| 329 |
+ // If there was an error, we cannot recover it |
|
| 330 |
+ n.sboxInit = true |
|
| 331 |
+ } |
|
| 321 | 332 |
|
| 322 |
- return n.initErr |
|
| 323 |
-} |
|
| 333 |
+ if n.initErr != nil {
|
|
| 334 |
+ return fmt.Errorf("network sandbox join failed: %v", n.initErr)
|
|
| 335 |
+ } |
|
| 324 | 336 |
|
| 325 |
-func (n *network) joinSubnetSandbox(s *subnet, restore bool) error {
|
|
| 326 |
- s.once.Do(func() {
|
|
| 327 |
- s.initErr = n.initSubnetSandbox(s, restore) |
|
| 328 |
- }) |
|
| 329 |
- return s.initErr |
|
| 337 |
+ subnetErr := s.initErr |
|
| 338 |
+ if !s.sboxInit {
|
|
| 339 |
+ subnetErr = n.initSubnetSandbox(s, restore) |
|
| 340 |
+ // We can recover from these errors, but not on restore |
|
| 341 |
+ if restore || subnetErr == nil {
|
|
| 342 |
+ s.initErr = subnetErr |
|
| 343 |
+ s.sboxInit = true |
|
| 344 |
+ } |
|
| 345 |
+ } |
|
| 346 |
+ if subnetErr != nil {
|
|
| 347 |
+ return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), subnetErr)
|
|
| 348 |
+ } |
|
| 349 |
+ |
|
| 350 |
+ if incJoinCount {
|
|
| 351 |
+ n.joinCnt++ |
|
| 352 |
+ } |
|
| 353 |
+ |
|
| 354 |
+ return nil |
|
| 330 | 355 |
} |
| 331 | 356 |
|
| 332 | 357 |
func (n *network) leaveSandbox() {
|
| ... | ... |
@@ -337,15 +360,14 @@ func (n *network) leaveSandbox() {
|
| 337 | 337 |
return |
| 338 | 338 |
} |
| 339 | 339 |
|
| 340 |
- // We are about to destroy sandbox since the container is leaving the network |
|
| 341 |
- // Reinitialize the once variable so that we will be able to trigger one time |
|
| 342 |
- // sandbox initialization(again) when another container joins subsequently. |
|
| 343 |
- n.once = &sync.Once{}
|
|
| 340 |
+ n.destroySandbox() |
|
| 341 |
+ |
|
| 342 |
+ n.sboxInit = false |
|
| 343 |
+ n.initErr = nil |
|
| 344 | 344 |
for _, s := range n.subnets {
|
| 345 |
- s.once = &sync.Once{}
|
|
| 345 |
+ s.sboxInit = false |
|
| 346 |
+ s.initErr = nil |
|
| 346 | 347 |
} |
| 347 |
- |
|
| 348 |
- n.destroySandbox() |
|
| 349 | 348 |
} |
| 350 | 349 |
|
| 351 | 350 |
// to be called while holding network lock |
| ... | ... |
@@ -478,7 +500,7 @@ func (n *network) generateVxlanName(s *subnet) string {
|
| 478 | 478 |
id = n.id[:5] |
| 479 | 479 |
} |
| 480 | 480 |
|
| 481 |
- return "vx-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + id
|
|
| 481 |
+ return fmt.Sprintf("vx-%06x-%v", s.vni, id)
|
|
| 482 | 482 |
} |
| 483 | 483 |
|
| 484 | 484 |
func (n *network) generateBridgeName(s *subnet) string {
|
| ... | ... |
@@ -491,7 +513,7 @@ func (n *network) generateBridgeName(s *subnet) string {
|
| 491 | 491 |
} |
| 492 | 492 |
|
| 493 | 493 |
func (n *network) getBridgeNamePrefix(s *subnet) string {
|
| 494 |
- return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s))
|
|
| 494 |
+ return fmt.Sprintf("ov-%06x", s.vni)
|
|
| 495 | 495 |
} |
| 496 | 496 |
|
| 497 | 497 |
func checkOverlap(nw *net.IPNet) error {
|
| ... | ... |
@@ -513,7 +535,7 @@ func checkOverlap(nw *net.IPNet) error {
|
| 513 | 513 |
} |
| 514 | 514 |
|
| 515 | 515 |
func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error {
|
| 516 |
- sbox := n.sandbox() |
|
| 516 |
+ sbox := n.sbox |
|
| 517 | 517 |
|
| 518 | 518 |
// restore overlay osl sandbox |
| 519 | 519 |
Ifaces := make(map[string][]osl.IfaceOption) |
| ... | ... |
@@ -542,7 +564,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 542 | 542 |
deleteInterfaceBySubnet(n.getBridgeNamePrefix(s), s) |
| 543 | 543 |
} |
| 544 | 544 |
// Try to delete the vxlan interface by vni if already present |
| 545 |
- deleteVxlanByVNI("", n.vxlanID(s))
|
|
| 545 |
+ deleteVxlanByVNI("", s.vni)
|
|
| 546 | 546 |
|
| 547 | 547 |
if err := checkOverlap(s.subnetIP); err != nil {
|
| 548 | 548 |
return err |
| ... | ... |
@@ -556,24 +578,24 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 556 | 556 |
// it must a stale namespace from previous |
| 557 | 557 |
// life. Destroy it completely and reclaim resourced. |
| 558 | 558 |
networkMu.Lock() |
| 559 |
- path, ok := vniTbl[n.vxlanID(s)] |
|
| 559 |
+ path, ok := vniTbl[s.vni] |
|
| 560 | 560 |
networkMu.Unlock() |
| 561 | 561 |
|
| 562 | 562 |
if ok {
|
| 563 |
- deleteVxlanByVNI(path, n.vxlanID(s)) |
|
| 563 |
+ deleteVxlanByVNI(path, s.vni) |
|
| 564 | 564 |
if err := syscall.Unmount(path, syscall.MNT_FORCE); err != nil {
|
| 565 | 565 |
logrus.Errorf("unmount of %s failed: %v", path, err)
|
| 566 | 566 |
} |
| 567 | 567 |
os.Remove(path) |
| 568 | 568 |
|
| 569 | 569 |
networkMu.Lock() |
| 570 |
- delete(vniTbl, n.vxlanID(s)) |
|
| 570 |
+ delete(vniTbl, s.vni) |
|
| 571 | 571 |
networkMu.Unlock() |
| 572 | 572 |
} |
| 573 | 573 |
} |
| 574 | 574 |
|
| 575 | 575 |
// create a bridge and vxlan device for this subnet and move it to the sandbox |
| 576 |
- sbox := n.sandbox() |
|
| 576 |
+ sbox := n.sbox |
|
| 577 | 577 |
|
| 578 | 578 |
if err := sbox.AddInterface(brName, "br", |
| 579 | 579 |
sbox.InterfaceOptions().Address(s.gwIP), |
| ... | ... |
@@ -581,13 +603,30 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 581 | 581 |
return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err)
|
| 582 | 582 |
} |
| 583 | 583 |
|
| 584 |
- err := createVxlan(vxlanName, n.vxlanID(s), n.maxMTU()) |
|
| 584 |
+ err := createVxlan(vxlanName, s.vni, n.maxMTU()) |
|
| 585 | 585 |
if err != nil {
|
| 586 | 586 |
return err |
| 587 | 587 |
} |
| 588 | 588 |
|
| 589 | 589 |
if err := sbox.AddInterface(vxlanName, "vxlan", |
| 590 | 590 |
sbox.InterfaceOptions().Master(brName)); err != nil {
|
| 591 |
+ // If adding vxlan device to the overlay namespace fails, remove the bridge interface we |
|
| 592 |
+ // already added to the namespace. This allows the caller to try the setup again. |
|
| 593 |
+ for _, iface := range sbox.Info().Interfaces() {
|
|
| 594 |
+ if iface.SrcName() == brName {
|
|
| 595 |
+ if ierr := iface.Remove(); ierr != nil {
|
|
| 596 |
+ logrus.Errorf("removing bridge failed from ov ns %v failed, %v", n.sbox.Key(), ierr)
|
|
| 597 |
+ } |
|
| 598 |
+ } |
|
| 599 |
+ } |
|
| 600 |
+ |
|
| 601 |
+ // Also, delete the vxlan interface. Since a global vni id is associated |
|
| 602 |
+ // with the vxlan interface, an orphaned vxlan interface will result in |
|
| 603 |
+ // failure of vxlan device creation if the vni is assigned to some other |
|
| 604 |
+ // network. |
|
| 605 |
+ if deleteErr := deleteInterface(vxlanName); deleteErr != nil {
|
|
| 606 |
+ logrus.Warnf("could not delete vxlan interface, %s, error %v, after config error, %v", vxlanName, deleteErr, err)
|
|
| 607 |
+ } |
|
| 591 | 608 |
return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.String(), err)
|
| 592 | 609 |
} |
| 593 | 610 |
|
| ... | ... |
@@ -619,6 +658,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 619 | 619 |
return nil |
| 620 | 620 |
} |
| 621 | 621 |
|
| 622 |
+// Must be called with the network lock |
|
| 622 | 623 |
func (n *network) initSubnetSandbox(s *subnet, restore bool) error {
|
| 623 | 624 |
brName := n.generateBridgeName(s) |
| 624 | 625 |
vxlanName := n.generateVxlanName(s) |
| ... | ... |
@@ -633,10 +673,8 @@ func (n *network) initSubnetSandbox(s *subnet, restore bool) error {
|
| 633 | 633 |
} |
| 634 | 634 |
} |
| 635 | 635 |
|
| 636 |
- n.Lock() |
|
| 637 | 636 |
s.vxlanName = vxlanName |
| 638 | 637 |
s.brName = brName |
| 639 |
- n.Unlock() |
|
| 640 | 638 |
|
| 641 | 639 |
return nil |
| 642 | 640 |
} |
| ... | ... |
@@ -677,11 +715,7 @@ func (n *network) cleanupStaleSandboxes() {
|
| 677 | 677 |
} |
| 678 | 678 |
|
| 679 | 679 |
func (n *network) initSandbox(restore bool) error {
|
| 680 |
- n.Lock() |
|
| 681 | 680 |
n.initEpoch++ |
| 682 |
- n.Unlock() |
|
| 683 |
- |
|
| 684 |
- networkOnce.Do(networkOnceInit) |
|
| 685 | 681 |
|
| 686 | 682 |
if !restore {
|
| 687 | 683 |
if hostMode {
|
| ... | ... |
@@ -711,12 +745,7 @@ func (n *network) initSandbox(restore bool) error {
|
| 711 | 711 |
} |
| 712 | 712 |
|
| 713 | 713 |
// this is needed to let the peerAdd configure the sandbox |
| 714 |
- n.setSandbox(sbox) |
|
| 715 |
- |
|
| 716 |
- if !restore {
|
|
| 717 |
- // Initialize the sandbox with all the peers previously received from networkdb |
|
| 718 |
- n.driver.initSandboxPeerDB(n.id) |
|
| 719 |
- } |
|
| 714 |
+ n.sbox = sbox |
|
| 720 | 715 |
|
| 721 | 716 |
// If we are in swarm mode, we don't need anymore the watchMiss routine. |
| 722 | 717 |
// This will save 1 thread and 1 netlink socket per network |
| ... | ... |
@@ -734,7 +763,7 @@ func (n *network) initSandbox(restore bool) error {
|
| 734 | 734 |
tv := syscall.NsecToTimeval(soTimeout.Nanoseconds()) |
| 735 | 735 |
err = nlSock.SetReceiveTimeout(&tv) |
| 736 | 736 |
}) |
| 737 |
- n.setNetlinkSocket(nlSock) |
|
| 737 |
+ n.nlSocket = nlSock |
|
| 738 | 738 |
|
| 739 | 739 |
if err == nil {
|
| 740 | 740 |
go n.watchMiss(nlSock, key) |
| ... | ... |
@@ -836,7 +865,6 @@ func (d *driver) restoreNetworkFromStore(nid string) *network {
|
| 836 | 836 |
if n != nil {
|
| 837 | 837 |
n.driver = d |
| 838 | 838 |
n.endpoints = endpointTable{}
|
| 839 |
- n.once = &sync.Once{}
|
|
| 840 | 839 |
d.networks[nid] = n |
| 841 | 840 |
} |
| 842 | 841 |
return n |
| ... | ... |
@@ -844,11 +872,11 @@ func (d *driver) restoreNetworkFromStore(nid string) *network {
|
| 844 | 844 |
|
| 845 | 845 |
func (d *driver) network(nid string) *network {
|
| 846 | 846 |
d.Lock() |
| 847 |
- defer d.Unlock() |
|
| 848 | 847 |
n, ok := d.networks[nid] |
| 849 | 848 |
if !ok {
|
| 850 | 849 |
n = d.restoreNetworkFromStore(nid) |
| 851 | 850 |
} |
| 851 |
+ d.Unlock() |
|
| 852 | 852 |
|
| 853 | 853 |
return n |
| 854 | 854 |
} |
| ... | ... |
@@ -869,26 +897,12 @@ func (d *driver) getNetworkFromStore(nid string) *network {
|
| 869 | 869 |
func (n *network) sandbox() osl.Sandbox {
|
| 870 | 870 |
n.Lock() |
| 871 | 871 |
defer n.Unlock() |
| 872 |
- |
|
| 873 | 872 |
return n.sbox |
| 874 | 873 |
} |
| 875 | 874 |
|
| 876 |
-func (n *network) setSandbox(sbox osl.Sandbox) {
|
|
| 877 |
- n.Lock() |
|
| 878 |
- n.sbox = sbox |
|
| 879 |
- n.Unlock() |
|
| 880 |
-} |
|
| 881 |
- |
|
| 882 |
-func (n *network) setNetlinkSocket(nlSk *nl.NetlinkSocket) {
|
|
| 883 |
- n.Lock() |
|
| 884 |
- n.nlSocket = nlSk |
|
| 885 |
- n.Unlock() |
|
| 886 |
-} |
|
| 887 |
- |
|
| 888 | 875 |
func (n *network) vxlanID(s *subnet) uint32 {
|
| 889 | 876 |
n.Lock() |
| 890 | 877 |
defer n.Unlock() |
| 891 |
- |
|
| 892 | 878 |
return s.vni |
| 893 | 879 |
} |
| 894 | 880 |
|
| ... | ... |
@@ -997,7 +1011,6 @@ func (n *network) SetValue(value []byte) error {
|
| 997 | 997 |
subnetIP: subnetIP, |
| 998 | 998 |
gwIP: gwIP, |
| 999 | 999 |
vni: vni, |
| 1000 |
- once: &sync.Once{},
|
|
| 1001 | 1000 |
} |
| 1002 | 1001 |
n.subnets = append(n.subnets, s) |
| 1003 | 1002 |
} else {
|
| ... | ... |
@@ -1023,7 +1036,10 @@ func (n *network) writeToStore() error {
|
| 1023 | 1023 |
} |
| 1024 | 1024 |
|
| 1025 | 1025 |
func (n *network) releaseVxlanID() ([]uint32, error) {
|
| 1026 |
- if len(n.subnets) == 0 {
|
|
| 1026 |
+ n.Lock() |
|
| 1027 |
+ nSubnets := len(n.subnets) |
|
| 1028 |
+ n.Unlock() |
|
| 1029 |
+ if nSubnets == 0 {
|
|
| 1027 | 1030 |
return nil, nil |
| 1028 | 1031 |
} |
| 1029 | 1032 |
|
| ... | ... |
@@ -1039,14 +1055,17 @@ func (n *network) releaseVxlanID() ([]uint32, error) {
|
| 1039 | 1039 |
} |
| 1040 | 1040 |
} |
| 1041 | 1041 |
var vnis []uint32 |
| 1042 |
+ n.Lock() |
|
| 1042 | 1043 |
for _, s := range n.subnets {
|
| 1043 | 1044 |
if n.driver.vxlanIdm != nil {
|
| 1044 |
- vni := n.vxlanID(s) |
|
| 1045 |
- vnis = append(vnis, vni) |
|
| 1046 |
- n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 1045 |
+ vnis = append(vnis, s.vni) |
|
| 1047 | 1046 |
} |
| 1047 |
+ s.vni = 0 |
|
| 1048 |
+ } |
|
| 1049 |
+ n.Unlock() |
|
| 1048 | 1050 |
|
| 1049 |
- n.setVxlanID(s, 0) |
|
| 1051 |
+ for _, vni := range vnis {
|
|
| 1052 |
+ n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 1050 | 1053 |
} |
| 1051 | 1054 |
|
| 1052 | 1055 |
return vnis, nil |
| ... | ... |
@@ -1054,7 +1073,7 @@ func (n *network) releaseVxlanID() ([]uint32, error) {
|
| 1054 | 1054 |
|
| 1055 | 1055 |
func (n *network) obtainVxlanID(s *subnet) error {
|
| 1056 | 1056 |
//return if the subnet already has a vxlan id assigned |
| 1057 |
- if s.vni != 0 {
|
|
| 1057 |
+ if n.vxlanID(s) != 0 {
|
|
| 1058 | 1058 |
return nil |
| 1059 | 1059 |
} |
| 1060 | 1060 |
|
| ... | ... |
@@ -1067,7 +1086,7 @@ func (n *network) obtainVxlanID(s *subnet) error {
|
| 1067 | 1067 |
return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
|
| 1068 | 1068 |
} |
| 1069 | 1069 |
|
| 1070 |
- if s.vni == 0 {
|
|
| 1070 |
+ if n.vxlanID(s) == 0 {
|
|
| 1071 | 1071 |
vxlanID, err := n.driver.vxlanIdm.GetID(true) |
| 1072 | 1072 |
if err != nil {
|
| 1073 | 1073 |
return fmt.Errorf("failed to allocate vxlan id: %v", err)
|
| ... | ... |
@@ -105,17 +105,6 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 105 | 105 |
logrus.Warnf("Failure during overlay endpoints restore: %v", err)
|
| 106 | 106 |
} |
| 107 | 107 |
|
| 108 |
- // If an error happened when the network join the sandbox during the endpoints restore |
|
| 109 |
- // we should reset it now along with the once variable, so that subsequent endpoint joins |
|
| 110 |
- // outside of the restore path can potentially fix the network join and succeed. |
|
| 111 |
- for nid, n := range d.networks {
|
|
| 112 |
- if n.initErr != nil {
|
|
| 113 |
- logrus.Infof("resetting init error and once variable for network %s after unsuccessful endpoint restore: %v", nid, n.initErr)
|
|
| 114 |
- n.initErr = nil |
|
| 115 |
- n.once = &sync.Once{}
|
|
| 116 |
- } |
|
| 117 |
- } |
|
| 118 |
- |
|
| 119 | 108 |
return dc.RegisterDriver(networkType, d, c) |
| 120 | 109 |
} |
| 121 | 110 |
|
| ... | ... |
@@ -151,14 +140,10 @@ func (d *driver) restoreEndpoints() error {
|
| 151 | 151 |
return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
|
| 152 | 152 |
} |
| 153 | 153 |
|
| 154 |
- if err := n.joinSandbox(true); err != nil {
|
|
| 154 |
+ if err := n.joinSandbox(s, true, true); err != nil {
|
|
| 155 | 155 |
return fmt.Errorf("restore network sandbox failed: %v", err)
|
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 |
- if err := n.joinSubnetSandbox(s, true); err != nil {
|
|
| 159 |
- return fmt.Errorf("restore subnet sandbox failed for %q: %v", s.subnetIP.String(), err)
|
|
| 160 |
- } |
|
| 161 |
- |
|
| 162 | 158 |
Ifaces := make(map[string][]osl.IfaceOption) |
| 163 | 159 |
vethIfaceOption := make([]osl.IfaceOption, 1) |
| 164 | 160 |
vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName)) |
| ... | ... |
@@ -166,10 +151,10 @@ func (d *driver) restoreEndpoints() error {
|
| 166 | 166 |
|
| 167 | 167 |
err := n.sbox.Restore(Ifaces, nil, nil, nil) |
| 168 | 168 |
if err != nil {
|
| 169 |
+ n.leaveSandbox() |
|
| 169 | 170 |
return fmt.Errorf("failed to restore overlay sandbox: %v", err)
|
| 170 | 171 |
} |
| 171 | 172 |
|
| 172 |
- n.incEndpointCount() |
|
| 173 | 173 |
d.peerAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true) |
| 174 | 174 |
} |
| 175 | 175 |
return nil |
| ... | ... |
@@ -7,7 +7,8 @@ import ( |
| 7 | 7 |
"sync" |
| 8 | 8 |
"syscall" |
| 9 | 9 |
|
| 10 |
- "github.com/docker/libnetwork/common" |
|
| 10 |
+ "github.com/docker/libnetwork/internal/caller" |
|
| 11 |
+ "github.com/docker/libnetwork/internal/setmatrix" |
|
| 11 | 12 |
"github.com/docker/libnetwork/osl" |
| 12 | 13 |
"github.com/sirupsen/logrus" |
| 13 | 14 |
) |
| ... | ... |
@@ -59,7 +60,7 @@ func (p *peerEntryDB) UnMarshalDB() peerEntry {
|
| 59 | 59 |
|
| 60 | 60 |
type peerMap struct {
|
| 61 | 61 |
// set of peerEntry, note they have to be objects and not pointers to maintain the proper equality checks |
| 62 |
- mp common.SetMatrix |
|
| 62 |
+ mp setmatrix.SetMatrix |
|
| 63 | 63 |
sync.Mutex |
| 64 | 64 |
} |
| 65 | 65 |
|
| ... | ... |
@@ -170,7 +171,7 @@ func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask |
| 170 | 170 |
pMap, ok := d.peerDb.mp[nid] |
| 171 | 171 |
if !ok {
|
| 172 | 172 |
d.peerDb.mp[nid] = &peerMap{
|
| 173 |
- mp: common.NewSetMatrix(), |
|
| 173 |
+ mp: setmatrix.NewSetMatrix(), |
|
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
pMap = d.peerDb.mp[nid] |
| ... | ... |
@@ -297,7 +298,7 @@ func (d *driver) peerOpRoutine(ctx context.Context, ch chan *peerOperation) {
|
| 297 | 297 |
} |
| 298 | 298 |
|
| 299 | 299 |
func (d *driver) peerInit(nid string) {
|
| 300 |
- callerName := common.CallerName(1) |
|
| 300 |
+ callerName := caller.Name(1) |
|
| 301 | 301 |
d.peerOpCh <- &peerOperation{
|
| 302 | 302 |
opType: peerOperationINIT, |
| 303 | 303 |
networkID: nid, |
| ... | ... |
@@ -331,7 +332,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
| 331 | 331 |
l2Miss: l2Miss, |
| 332 | 332 |
l3Miss: l3Miss, |
| 333 | 333 |
localPeer: localPeer, |
| 334 |
- callerName: common.CallerName(1), |
|
| 334 |
+ callerName: caller.Name(1), |
|
| 335 | 335 |
} |
| 336 | 336 |
} |
| 337 | 337 |
|
| ... | ... |
@@ -384,7 +385,7 @@ func (d *driver) peerAddOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask |
| 384 | 384 |
return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
| 385 | 385 |
} |
| 386 | 386 |
|
| 387 |
- if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 387 |
+ if err := n.joinSandbox(s, false, false); err != nil {
|
|
| 388 | 388 |
return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
| 389 | 389 |
} |
| 390 | 390 |
|
| ... | ... |
@@ -422,7 +423,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas |
| 422 | 422 |
peerIPMask: peerIPMask, |
| 423 | 423 |
peerMac: peerMac, |
| 424 | 424 |
vtepIP: vtep, |
| 425 |
- callerName: common.CallerName(1), |
|
| 425 |
+ callerName: caller.Name(1), |
|
| 426 | 426 |
localPeer: localPeer, |
| 427 | 427 |
} |
| 428 | 428 |
} |
| ... | ... |
@@ -491,7 +492,7 @@ func (d *driver) peerFlush(nid string) {
|
| 491 | 491 |
d.peerOpCh <- &peerOperation{
|
| 492 | 492 |
opType: peerOperationFLUSH, |
| 493 | 493 |
networkID: nid, |
| 494 |
- callerName: common.CallerName(1), |
|
| 494 |
+ callerName: caller.Name(1), |
|
| 495 | 495 |
} |
| 496 | 496 |
} |
| 497 | 497 |
|
| ... | ... |
@@ -150,7 +150,7 @@ type JoinRequest struct {
|
| 150 | 150 |
Options map[string]interface{}
|
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 |
-// InterfaceName is the struct represetation of a pair of devices with source |
|
| 153 |
+// InterfaceName is the struct representation of a pair of devices with source |
|
| 154 | 154 |
// and destination, for the purposes of putting an endpoint into a container. |
| 155 | 155 |
type InterfaceName struct {
|
| 156 | 156 |
SrcName string |
| ... | ... |
@@ -54,7 +54,7 @@ type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capabili |
| 54 | 54 |
// DriverNotifyFunc defines the notify function signature when a new network driver gets registered. |
| 55 | 55 |
type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error |
| 56 | 56 |
|
| 57 |
-// New retruns a new driver registry handle. |
|
| 57 |
+// New returns a new driver registry handle. |
|
| 58 | 58 |
func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg plugingetter.PluginGetter) (*DrvRegistry, error) {
|
| 59 | 59 |
r := &DrvRegistry{
|
| 60 | 60 |
drivers: make(driverTable), |
| 61 | 61 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,29 @@ |
| 0 |
+package caller |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "runtime" |
|
| 4 |
+ "strings" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func callerInfo(i int) string {
|
|
| 8 |
+ ptr, _, _, ok := runtime.Caller(i) |
|
| 9 |
+ fName := "unknown" |
|
| 10 |
+ if ok {
|
|
| 11 |
+ f := runtime.FuncForPC(ptr) |
|
| 12 |
+ if f != nil {
|
|
| 13 |
+ // f.Name() is like: github.com/docker/libnetwork/caller.MethodName |
|
| 14 |
+ tmp := strings.Split(f.Name(), ".") |
|
| 15 |
+ if len(tmp) > 0 {
|
|
| 16 |
+ fName = tmp[len(tmp)-1] |
|
| 17 |
+ } |
|
| 18 |
+ } |
|
| 19 |
+ } |
|
| 20 |
+ |
|
| 21 |
+ return fName |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+// Name returns the name of the function at the specified level |
|
| 25 |
+// level == 0 means current method name |
|
| 26 |
+func Name(level int) string {
|
|
| 27 |
+ return callerInfo(2 + level) |
|
| 28 |
+} |
| 0 | 29 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,135 @@ |
| 0 |
+package setmatrix |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "sync" |
|
| 4 |
+ |
|
| 5 |
+ mapset "github.com/deckarep/golang-set" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// SetMatrix is a map of Sets |
|
| 9 |
+type SetMatrix interface {
|
|
| 10 |
+ // Get returns the members of the set for a specific key as a slice. |
|
| 11 |
+ Get(key string) ([]interface{}, bool)
|
|
| 12 |
+ // Contains is used to verify if an element is in a set for a specific key |
|
| 13 |
+ // returns true if the element is in the set |
|
| 14 |
+ // returns true if there is a set for the key |
|
| 15 |
+ Contains(key string, value interface{}) (bool, bool)
|
|
| 16 |
+ // Insert inserts the value in the set of a key |
|
| 17 |
+ // returns true if the value is inserted (was not already in the set), false otherwise |
|
| 18 |
+ // returns also the length of the set for the key |
|
| 19 |
+ Insert(key string, value interface{}) (bool, int)
|
|
| 20 |
+ // Remove removes the value in the set for a specific key |
|
| 21 |
+ // returns true if the value is deleted, false otherwise |
|
| 22 |
+ // returns also the length of the set for the key |
|
| 23 |
+ Remove(key string, value interface{}) (bool, int)
|
|
| 24 |
+ // Cardinality returns the number of elements in the set for a key |
|
| 25 |
+ // returns false if the set is not present |
|
| 26 |
+ Cardinality(key string) (int, bool) |
|
| 27 |
+ // String returns the string version of the set, empty otherwise |
|
| 28 |
+ // returns false if the set is not present |
|
| 29 |
+ String(key string) (string, bool) |
|
| 30 |
+ // Returns all the keys in the map |
|
| 31 |
+ Keys() []string |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+type setMatrix struct {
|
|
| 35 |
+ matrix map[string]mapset.Set |
|
| 36 |
+ |
|
| 37 |
+ sync.Mutex |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// NewSetMatrix creates a new set matrix object |
|
| 41 |
+func NewSetMatrix() SetMatrix {
|
|
| 42 |
+ s := &setMatrix{}
|
|
| 43 |
+ s.init() |
|
| 44 |
+ return s |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func (s *setMatrix) init() {
|
|
| 48 |
+ s.matrix = make(map[string]mapset.Set) |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func (s *setMatrix) Get(key string) ([]interface{}, bool) {
|
|
| 52 |
+ s.Lock() |
|
| 53 |
+ defer s.Unlock() |
|
| 54 |
+ set, ok := s.matrix[key] |
|
| 55 |
+ if !ok {
|
|
| 56 |
+ return nil, ok |
|
| 57 |
+ } |
|
| 58 |
+ return set.ToSlice(), ok |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+func (s *setMatrix) Contains(key string, value interface{}) (bool, bool) {
|
|
| 62 |
+ s.Lock() |
|
| 63 |
+ defer s.Unlock() |
|
| 64 |
+ set, ok := s.matrix[key] |
|
| 65 |
+ if !ok {
|
|
| 66 |
+ return false, ok |
|
| 67 |
+ } |
|
| 68 |
+ return set.Contains(value), ok |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+func (s *setMatrix) Insert(key string, value interface{}) (bool, int) {
|
|
| 72 |
+ s.Lock() |
|
| 73 |
+ defer s.Unlock() |
|
| 74 |
+ set, ok := s.matrix[key] |
|
| 75 |
+ if !ok {
|
|
| 76 |
+ s.matrix[key] = mapset.NewSet() |
|
| 77 |
+ s.matrix[key].Add(value) |
|
| 78 |
+ return true, 1 |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ return set.Add(value), set.Cardinality() |
|
| 82 |
+} |
|
| 83 |
+ |
|
| 84 |
+func (s *setMatrix) Remove(key string, value interface{}) (bool, int) {
|
|
| 85 |
+ s.Lock() |
|
| 86 |
+ defer s.Unlock() |
|
| 87 |
+ set, ok := s.matrix[key] |
|
| 88 |
+ if !ok {
|
|
| 89 |
+ return false, 0 |
|
| 90 |
+ } |
|
| 91 |
+ |
|
| 92 |
+ var removed bool |
|
| 93 |
+ if set.Contains(value) {
|
|
| 94 |
+ set.Remove(value) |
|
| 95 |
+ removed = true |
|
| 96 |
+ // If the set is empty remove it from the matrix |
|
| 97 |
+ if set.Cardinality() == 0 {
|
|
| 98 |
+ delete(s.matrix, key) |
|
| 99 |
+ } |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ return removed, set.Cardinality() |
|
| 103 |
+} |
|
| 104 |
+ |
|
| 105 |
+func (s *setMatrix) Cardinality(key string) (int, bool) {
|
|
| 106 |
+ s.Lock() |
|
| 107 |
+ defer s.Unlock() |
|
| 108 |
+ set, ok := s.matrix[key] |
|
| 109 |
+ if !ok {
|
|
| 110 |
+ return 0, ok |
|
| 111 |
+ } |
|
| 112 |
+ |
|
| 113 |
+ return set.Cardinality(), ok |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+func (s *setMatrix) String(key string) (string, bool) {
|
|
| 117 |
+ s.Lock() |
|
| 118 |
+ defer s.Unlock() |
|
| 119 |
+ set, ok := s.matrix[key] |
|
| 120 |
+ if !ok {
|
|
| 121 |
+ return "", ok |
|
| 122 |
+ } |
|
| 123 |
+ return set.String(), ok |
|
| 124 |
+} |
|
| 125 |
+ |
|
| 126 |
+func (s *setMatrix) Keys() []string {
|
|
| 127 |
+ s.Lock() |
|
| 128 |
+ defer s.Unlock() |
|
| 129 |
+ keys := make([]string, 0, len(s.matrix)) |
|
| 130 |
+ for k := range s.matrix {
|
|
| 131 |
+ keys = append(keys, k) |
|
| 132 |
+ } |
|
| 133 |
+ return keys |
|
| 134 |
+} |
| ... | ... |
@@ -477,7 +477,7 @@ func raw(args ...string) ([]byte, error) {
|
| 477 | 477 |
return filterOutput(startTime, output, args...), err |
| 478 | 478 |
} |
| 479 | 479 |
|
| 480 |
-// RawCombinedOutput inernally calls the Raw function and returns a non nil |
|
| 480 |
+// RawCombinedOutput internally calls the Raw function and returns a non nil |
|
| 481 | 481 |
// error if Raw returned a non nil error or a non empty output |
| 482 | 482 |
func RawCombinedOutput(args ...string) error {
|
| 483 | 483 |
if output, err := Raw(args...); err != nil || len(output) != 0 {
|
| ... | ... |
@@ -100,7 +100,7 @@ func fillService(s *Service) nl.NetlinkRequestData {
|
| 100 | 100 |
return cmdAttr |
| 101 | 101 |
} |
| 102 | 102 |
|
| 103 |
-func fillDestinaton(d *Destination) nl.NetlinkRequestData {
|
|
| 103 |
+func fillDestination(d *Destination) nl.NetlinkRequestData {
|
|
| 104 | 104 |
cmdAttr := nl.NewRtAttr(ipvsCmdAttrDest, nil) |
| 105 | 105 |
|
| 106 | 106 |
nl.NewRtAttrChild(cmdAttr, ipvsDestAttrAddress, rawIPData(d.Address)) |
| ... | ... |
@@ -134,7 +134,7 @@ func (i *Handle) doCmdwithResponse(s *Service, d *Destination, cmd uint8) ([][]b |
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
} else {
|
| 137 |
- req.AddData(fillDestinaton(d)) |
|
| 137 |
+ req.AddData(fillDestination(d)) |
|
| 138 | 138 |
} |
| 139 | 139 |
|
| 140 | 140 |
res, err := execute(i.sock, req, 0) |
| ... | ... |
@@ -9,11 +9,11 @@ import ( |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/pkg/stringid" |
| 12 |
- "github.com/docker/libnetwork/common" |
|
| 13 | 12 |
"github.com/docker/libnetwork/config" |
| 14 | 13 |
"github.com/docker/libnetwork/datastore" |
| 15 | 14 |
"github.com/docker/libnetwork/driverapi" |
| 16 | 15 |
"github.com/docker/libnetwork/etchosts" |
| 16 |
+ "github.com/docker/libnetwork/internal/setmatrix" |
|
| 17 | 17 |
"github.com/docker/libnetwork/ipamapi" |
| 18 | 18 |
"github.com/docker/libnetwork/netlabel" |
| 19 | 19 |
"github.com/docker/libnetwork/netutils" |
| ... | ... |
@@ -88,7 +88,7 @@ type NetworkInfo interface {
|
| 88 | 88 |
type EndpointWalker func(ep Endpoint) bool |
| 89 | 89 |
|
| 90 | 90 |
// ipInfo is the reverse mapping from IP to service name to serve the PTR query. |
| 91 |
-// extResolver is set if an externl server resolves a service name to this IP. |
|
| 91 |
+// extResolver is set if an external server resolves a service name to this IP. |
|
| 92 | 92 |
// Its an indication to defer PTR queries also to that external server. |
| 93 | 93 |
type ipInfo struct {
|
| 94 | 94 |
name string |
| ... | ... |
@@ -104,9 +104,9 @@ type svcMapEntry struct {
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 | 106 |
type svcInfo struct {
|
| 107 |
- svcMap common.SetMatrix |
|
| 108 |
- svcIPv6Map common.SetMatrix |
|
| 109 |
- ipMap common.SetMatrix |
|
| 107 |
+ svcMap setmatrix.SetMatrix |
|
| 108 |
+ svcIPv6Map setmatrix.SetMatrix |
|
| 109 |
+ ipMap setmatrix.SetMatrix |
|
| 110 | 110 |
service map[string][]servicePorts |
| 111 | 111 |
} |
| 112 | 112 |
|
| ... | ... |
@@ -1353,7 +1353,7 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool |
| 1353 | 1353 |
} |
| 1354 | 1354 |
} |
| 1355 | 1355 |
|
| 1356 |
-func addIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1356 |
+func addIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1357 | 1357 |
reverseIP := netutils.ReverseIP(ip.String()) |
| 1358 | 1358 |
ipMap.Insert(reverseIP, ipInfo{
|
| 1359 | 1359 |
name: name, |
| ... | ... |
@@ -1361,7 +1361,7 @@ func addIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
| 1361 | 1361 |
}) |
| 1362 | 1362 |
} |
| 1363 | 1363 |
|
| 1364 |
-func delIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1364 |
+func delIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) {
|
|
| 1365 | 1365 |
reverseIP := netutils.ReverseIP(ip.String()) |
| 1366 | 1366 |
ipMap.Remove(reverseIP, ipInfo{
|
| 1367 | 1367 |
name: name, |
| ... | ... |
@@ -1369,14 +1369,14 @@ func delIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) {
|
| 1369 | 1369 |
}) |
| 1370 | 1370 |
} |
| 1371 | 1371 |
|
| 1372 |
-func addNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1372 |
+func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1373 | 1373 |
svcMap.Insert(name, svcMapEntry{
|
| 1374 | 1374 |
ip: epIP.String(), |
| 1375 | 1375 |
serviceID: serviceID, |
| 1376 | 1376 |
}) |
| 1377 | 1377 |
} |
| 1378 | 1378 |
|
| 1379 |
-func delNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1379 |
+func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
|
|
| 1380 | 1380 |
svcMap.Remove(name, svcMapEntry{
|
| 1381 | 1381 |
ip: epIP.String(), |
| 1382 | 1382 |
serviceID: serviceID, |
| ... | ... |
@@ -1399,9 +1399,9 @@ func (n *network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP |
| 1399 | 1399 |
sr, ok := c.svcRecords[n.ID()] |
| 1400 | 1400 |
if !ok {
|
| 1401 | 1401 |
sr = svcInfo{
|
| 1402 |
- svcMap: common.NewSetMatrix(), |
|
| 1403 |
- svcIPv6Map: common.NewSetMatrix(), |
|
| 1404 |
- ipMap: common.NewSetMatrix(), |
|
| 1402 |
+ svcMap: setmatrix.NewSetMatrix(), |
|
| 1403 |
+ svcIPv6Map: setmatrix.NewSetMatrix(), |
|
| 1404 |
+ ipMap: setmatrix.NewSetMatrix(), |
|
| 1405 | 1405 |
} |
| 1406 | 1406 |
c.svcRecords[n.ID()] = sr |
| 1407 | 1407 |
} |
| ... | ... |
@@ -1654,7 +1654,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
| 1654 | 1654 |
return types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name())
|
| 1655 | 1655 |
} |
| 1656 | 1656 |
if !d.Pool.Contains(ip) {
|
| 1657 |
- return types.ForbiddenErrorf("auxilairy address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool)
|
|
| 1657 |
+ return types.ForbiddenErrorf("auxiliary address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool)
|
|
| 1658 | 1658 |
} |
| 1659 | 1659 |
// Attempt reservation in the container addressable pool, silent the error if address does not belong to that pool |
| 1660 | 1660 |
if d.IPAMData.AuxAddresses[k], _, err = ipam.RequestAddress(d.PoolID, ip, nil); err != nil && err != ipamapi.ErrIPOutOfRange {
|
| ... | ... |
@@ -2036,7 +2036,7 @@ func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) {
|
| 2036 | 2036 |
|
| 2037 | 2037 |
logrus.Debugf("Service name To resolve: %v", name)
|
| 2038 | 2038 |
|
| 2039 |
- // There are DNS implementaions that allow SRV queries for names not in |
|
| 2039 |
+ // There are DNS implementations that allow SRV queries for names not in |
|
| 2040 | 2040 |
// the format defined by RFC 2782. Hence specific validations checks are |
| 2041 | 2041 |
// not done |
| 2042 | 2042 |
parts := strings.Split(name, ".") |
| ... | ... |
@@ -2126,7 +2126,7 @@ func (n *network) lbEndpointName() string {
|
| 2126 | 2126 |
func (n *network) createLoadBalancerSandbox() (retErr error) {
|
| 2127 | 2127 |
sandboxName := n.lbSandboxName() |
| 2128 | 2128 |
// Mark the sandbox to be a load balancer |
| 2129 |
- sbOptions := []SandboxOption{OptionLoadBalancer()}
|
|
| 2129 |
+ sbOptions := []SandboxOption{OptionLoadBalancer(n.id)}
|
|
| 2130 | 2130 |
if n.ingress {
|
| 2131 | 2131 |
sbOptions = append(sbOptions, OptionIngress()) |
| 2132 | 2132 |
} |
| ... | ... |
@@ -243,7 +243,7 @@ func (nDB *NetworkDB) clusterLeave() error {
|
| 243 | 243 |
} |
| 244 | 244 |
|
| 245 | 245 |
func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, f func()) {
|
| 246 |
- // Use a random stagger to avoid syncronizing |
|
| 246 |
+ // Use a random stagger to avoid synchronizing |
|
| 247 | 247 |
randStagger := time.Duration(uint64(rnd.Int63()) % uint64(stagger)) |
| 248 | 248 |
select {
|
| 249 | 249 |
case <-time.After(randStagger): |
| ... | ... |
@@ -58,7 +58,7 @@ type NetworkDB struct {
|
| 58 | 58 |
// List of all peer nodes which have left |
| 59 | 59 |
leftNodes map[string]*node |
| 60 | 60 |
|
| 61 |
- // A multi-dimensional map of network/node attachmemts. The |
|
| 61 |
+ // A multi-dimensional map of network/node attachments. The |
|
| 62 | 62 |
// first key is a node name and the second key is a network ID |
| 63 | 63 |
// for the network that node is participating in. |
| 64 | 64 |
networks map[string]map[string]*network |
| ... | ... |
@@ -153,7 +153,7 @@ type network struct {
|
| 153 | 153 |
entriesNumber int |
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 |
-// Config represents the configuration of the networdb instance and |
|
| 156 |
+// Config represents the configuration of the networkdb instance and |
|
| 157 | 157 |
// can be passed by the caller. |
| 158 | 158 |
type Config struct {
|
| 159 | 159 |
// NodeID is the node unique identifier of the node when is part of the cluster |
| ... | ... |
@@ -48,7 +48,7 @@ type MessageType int32 |
| 48 | 48 |
|
| 49 | 49 |
const ( |
| 50 | 50 |
MessageTypeInvalid MessageType = 0 |
| 51 |
- // NetworEvent message type is used to communicate network |
|
| 51 |
+ // NetworkEvent message type is used to communicate network |
|
| 52 | 52 |
// attachments on the node. |
| 53 | 53 |
MessageTypeNetworkEvent MessageType = 1 |
| 54 | 54 |
// TableEvent message type is used to communicate any table |
| ... | ... |
@@ -66,7 +66,7 @@ const ( |
| 66 | 66 |
// which is a pack of many message of above types, packed into |
| 67 | 67 |
// a single compound message. |
| 68 | 68 |
MessageTypeCompound MessageType = 5 |
| 69 |
- // NodeEvent message type is used to communicare node |
|
| 69 |
+ // NodeEvent message type is used to communicate node |
|
| 70 | 70 |
// join/leave events in the cluster |
| 71 | 71 |
MessageTypeNodeEvent MessageType = 6 |
| 72 | 72 |
) |
| ... | ... |
@@ -19,7 +19,7 @@ enum MessageType {
|
| 19 | 19 |
|
| 20 | 20 |
INVALID = 0 [(gogoproto.enumvalue_customname) = "MessageTypeInvalid"]; |
| 21 | 21 |
|
| 22 |
- // NetworEvent message type is used to communicate network |
|
| 22 |
+ // NetworkEvent message type is used to communicate network |
|
| 23 | 23 |
// attachments on the node. |
| 24 | 24 |
NETWORK_EVENT = 1 [(gogoproto.enumvalue_customname) = "MessageTypeNetworkEvent"]; |
| 25 | 25 |
|
| ... | ... |
@@ -42,7 +42,7 @@ enum MessageType {
|
| 42 | 42 |
// a single compound message. |
| 43 | 43 |
COMPOUND = 5 [(gogoproto.enumvalue_customname) = "MessageTypeCompound"]; |
| 44 | 44 |
|
| 45 |
- // NodeEvent message type is used to communicare node |
|
| 45 |
+ // NodeEvent message type is used to communicate node |
|
| 46 | 46 |
// join/leave events in the cluster |
| 47 | 47 |
NODE_EVENT = 6 [(gogoproto.enumvalue_customname) = "MessageTypeNodeEvent"]; |
| 48 | 48 |
} |
| ... | ... |
@@ -6,8 +6,8 @@ import ( |
| 6 | 6 |
"net/http" |
| 7 | 7 |
"strings" |
| 8 | 8 |
|
| 9 |
- "github.com/docker/libnetwork/common" |
|
| 10 | 9 |
"github.com/docker/libnetwork/diagnostic" |
| 10 |
+ "github.com/docker/libnetwork/internal/caller" |
|
| 11 | 11 |
"github.com/sirupsen/logrus" |
| 12 | 12 |
) |
| 13 | 13 |
|
| ... | ... |
@@ -37,7 +37,7 @@ func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 37 | 37 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 38 | 38 |
|
| 39 | 39 |
// audit logs |
| 40 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 40 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 41 | 41 |
log.Info("join cluster")
|
| 42 | 42 |
|
| 43 | 43 |
if len(r.Form["members"]) < 1 {
|
| ... | ... |
@@ -70,7 +70,7 @@ func dbPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 70 | 70 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 71 | 71 |
|
| 72 | 72 |
// audit logs |
| 73 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 73 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 74 | 74 |
log.Info("network peers")
|
| 75 | 75 |
|
| 76 | 76 |
if len(r.Form["nid"]) < 1 {
|
| ... | ... |
@@ -104,7 +104,7 @@ func dbClusterPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 104 | 104 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 105 | 105 |
|
| 106 | 106 |
// audit logs |
| 107 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 107 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 108 | 108 |
log.Info("cluster peers")
|
| 109 | 109 |
|
| 110 | 110 |
nDB, ok := ctx.(*NetworkDB) |
| ... | ... |
@@ -127,7 +127,7 @@ func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 127 | 127 |
unsafe, json := diagnostic.ParseHTTPFormOptions(r) |
| 128 | 128 |
|
| 129 | 129 |
// audit logs |
| 130 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 130 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 131 | 131 |
log.Info("create entry")
|
| 132 | 132 |
|
| 133 | 133 |
if len(r.Form["tname"]) < 1 || |
| ... | ... |
@@ -176,7 +176,7 @@ func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 176 | 176 |
unsafe, json := diagnostic.ParseHTTPFormOptions(r) |
| 177 | 177 |
|
| 178 | 178 |
// audit logs |
| 179 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 179 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 180 | 180 |
log.Info("update entry")
|
| 181 | 181 |
|
| 182 | 182 |
if len(r.Form["tname"]) < 1 || |
| ... | ... |
@@ -224,7 +224,7 @@ func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 224 | 224 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 225 | 225 |
|
| 226 | 226 |
// audit logs |
| 227 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 227 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 228 | 228 |
log.Info("delete entry")
|
| 229 | 229 |
|
| 230 | 230 |
if len(r.Form["tname"]) < 1 || |
| ... | ... |
@@ -261,7 +261,7 @@ func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 261 | 261 |
unsafe, json := diagnostic.ParseHTTPFormOptions(r) |
| 262 | 262 |
|
| 263 | 263 |
// audit logs |
| 264 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 264 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 265 | 265 |
log.Info("get entry")
|
| 266 | 266 |
|
| 267 | 267 |
if len(r.Form["tname"]) < 1 || |
| ... | ... |
@@ -307,7 +307,7 @@ func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 307 | 307 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 308 | 308 |
|
| 309 | 309 |
// audit logs |
| 310 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 310 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 311 | 311 |
log.Info("join network")
|
| 312 | 312 |
|
| 313 | 313 |
if len(r.Form["nid"]) < 1 {
|
| ... | ... |
@@ -339,7 +339,7 @@ func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 339 | 339 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 340 | 340 |
|
| 341 | 341 |
// audit logs |
| 342 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 342 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 343 | 343 |
log.Info("leave network")
|
| 344 | 344 |
|
| 345 | 345 |
if len(r.Form["nid"]) < 1 {
|
| ... | ... |
@@ -371,7 +371,7 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 371 | 371 |
unsafe, json := diagnostic.ParseHTTPFormOptions(r) |
| 372 | 372 |
|
| 373 | 373 |
// audit logs |
| 374 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 374 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 375 | 375 |
log.Info("get table")
|
| 376 | 376 |
|
| 377 | 377 |
if len(r.Form["tname"]) < 1 || |
| ... | ... |
@@ -419,7 +419,7 @@ func dbNetworkStats(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
| 419 | 419 |
_, json := diagnostic.ParseHTTPFormOptions(r) |
| 420 | 420 |
|
| 421 | 421 |
// audit logs |
| 422 |
- log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()})
|
|
| 422 |
+ log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
|
| 423 | 423 |
log.Info("network stats")
|
| 424 | 424 |
|
| 425 | 425 |
if len(r.Form["nid"]) < 1 {
|
| ... | ... |
@@ -289,6 +289,16 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If |
| 289 | 289 |
|
| 290 | 290 |
// Configure the interface now this is moved in the proper namespace. |
| 291 | 291 |
if err := configureInterface(nlh, iface, i); err != nil {
|
| 292 |
+ // If configuring the device fails move it back to the host namespace |
|
| 293 |
+ // and change the name back to the source name. This allows the caller |
|
| 294 |
+ // to properly cleanup the interface. Its important especially for |
|
| 295 |
+ // interfaces with global attributes, ex: vni id for vxlan interfaces. |
|
| 296 |
+ if nerr := nlh.LinkSetName(iface, i.SrcName()); nerr != nil {
|
|
| 297 |
+ logrus.Errorf("renaming interface (%s->%s) failed, %v after config error %v", i.DstName(), i.SrcName(), nerr, err)
|
|
| 298 |
+ } |
|
| 299 |
+ if nerr := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); nerr != nil {
|
|
| 300 |
+ logrus.Errorf("moving inteface %s to host ns failed, %v, after config error %v", i.SrcName(), nerr, err)
|
|
| 301 |
+ } |
|
| 292 | 302 |
return err |
| 293 | 303 |
} |
| 294 | 304 |
|
| ... | ... |
@@ -2,7 +2,7 @@ package kernel |
| 2 | 2 |
|
| 3 | 3 |
type conditionalCheck func(val1, val2 string) bool |
| 4 | 4 |
|
| 5 |
-// OSValue represents a tuple, value defired, check function when to apply the value |
|
| 5 |
+// OSValue represents a tuple, value defined, check function when to apply the value |
|
| 6 | 6 |
type OSValue struct {
|
| 7 | 7 |
Value string |
| 8 | 8 |
CheckFn conditionalCheck |
| ... | ... |
@@ -394,10 +394,13 @@ func (n *networkNamespace) InvokeFunc(f func()) error {
|
| 394 | 394 |
// InitOSContext initializes OS context while configuring network resources |
| 395 | 395 |
func InitOSContext() func() {
|
| 396 | 396 |
runtime.LockOSThread() |
| 397 |
+ if err := ns.SetNamespace(); err != nil {
|
|
| 398 |
+ logrus.Error(err) |
|
| 399 |
+ } |
|
| 397 | 400 |
return runtime.UnlockOSThread |
| 398 | 401 |
} |
| 399 | 402 |
|
| 400 |
-func nsInvoke(path string, prefunc, postfunc func(int) error) error {
|
|
| 403 |
+func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error {
|
|
| 401 | 404 |
defer InitOSContext()() |
| 402 | 405 |
|
| 403 | 406 |
newNs, err := netns.GetFromPath(path) |
| ... | ... |
@@ -412,14 +415,10 @@ func nsInvoke(path string, prefunc, postfunc func(int) error) error {
|
| 412 | 412 |
return fmt.Errorf("failed in prefunc: %v", err)
|
| 413 | 413 |
} |
| 414 | 414 |
|
| 415 |
- // save the current namespace (host namespace) |
|
| 416 |
- curNs, _ := netns.Get() |
|
| 417 | 415 |
if err = netns.Set(newNs); err != nil {
|
| 418 | 416 |
return err |
| 419 | 417 |
} |
| 420 |
- defer curNs.Close() |
|
| 421 |
- // will restore the previous namespace before unlocking the thread |
|
| 422 |
- defer netns.Set(curNs) |
|
| 418 |
+ defer ns.SetNamespace() |
|
| 423 | 419 |
|
| 424 | 420 |
// Invoked after the namespace switch. |
| 425 | 421 |
return postfunc(ns.ParseHandlerInt()) |
| ... | ... |
@@ -652,10 +651,7 @@ func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) {
|
| 652 | 652 |
for _, t := range types {
|
| 653 | 653 |
switch t {
|
| 654 | 654 |
case SandboxTypeLoadBalancer: |
| 655 |
- nsInvoke(n.nsPath(), |
|
| 656 |
- func(nsFD int) error { return nil },
|
|
| 657 |
- func(callerFD int) error { kernel.ApplyOSTweaks(loadBalancerConfig); return nil },
|
|
| 658 |
- ) |
|
| 655 |
+ kernel.ApplyOSTweaks(loadBalancerConfig) |
|
| 659 | 656 |
} |
| 660 | 657 |
} |
| 661 | 658 |
} |
| ... | ... |
@@ -14,6 +14,11 @@ import ( |
| 14 | 14 |
"github.com/sirupsen/logrus" |
| 15 | 15 |
) |
| 16 | 16 |
|
| 17 |
+const ( |
|
| 18 |
+ // DefaultResolvConf points to the default file used for dns configuration on a linux machine |
|
| 19 |
+ DefaultResolvConf = "/etc/resolv.conf" |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 17 | 22 |
var ( |
| 18 | 23 |
// Note: the default IPv4 & IPv6 resolvers are set to Google's Public DNS |
| 19 | 24 |
defaultIPv4Dns = []string{"nameserver 8.8.8.8", "nameserver 8.8.4.4"}
|
| ... | ... |
@@ -50,15 +55,7 @@ type File struct {
|
| 50 | 50 |
|
| 51 | 51 |
// Get returns the contents of /etc/resolv.conf and its hash |
| 52 | 52 |
func Get() (*File, error) {
|
| 53 |
- resolv, err := ioutil.ReadFile("/etc/resolv.conf")
|
|
| 54 |
- if err != nil {
|
|
| 55 |
- return nil, err |
|
| 56 |
- } |
|
| 57 |
- hash, err := ioutils.HashData(bytes.NewReader(resolv)) |
|
| 58 |
- if err != nil {
|
|
| 59 |
- return nil, err |
|
| 60 |
- } |
|
| 61 |
- return &File{Content: resolv, Hash: hash}, nil
|
|
| 53 |
+ return GetSpecific(DefaultResolvConf) |
|
| 62 | 54 |
} |
| 63 | 55 |
|
| 64 | 56 |
// GetSpecific returns the contents of the user specified resolv.conf file and its hash |
| ... | ... |
@@ -35,7 +35,7 @@ type Resolver interface {
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
// DNSBackend represents a backend DNS resolver used for DNS name |
| 38 |
-// resolution. All the queries to the resolver are forwared to the |
|
| 38 |
+// resolution. All the queries to the resolver are forwarded to the |
|
| 39 | 39 |
// backend resolver. |
| 40 | 40 |
type DNSBackend interface {
|
| 41 | 41 |
// ResolveName resolves a service name to an IPv4 or IPv6 address by searching |
| ... | ... |
@@ -84,6 +84,7 @@ type sandbox struct {
|
| 84 | 84 |
ingress bool |
| 85 | 85 |
ndotsSet bool |
| 86 | 86 |
oslTypes []osl.SandboxType // slice of properties of this sandbox |
| 87 |
+ loadBalancerNID string // NID that this SB is a load balancer for |
|
| 87 | 88 |
sync.Mutex |
| 88 | 89 |
// This mutex is used to serialize service related operation for an endpoint |
| 89 | 90 |
// The lock is here because the endpoint is saved into the store so is not unique |
| ... | ... |
@@ -467,7 +468,7 @@ func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) {
|
| 467 | 467 |
|
| 468 | 468 |
logrus.Debugf("Service name To resolve: %v", name)
|
| 469 | 469 |
|
| 470 |
- // There are DNS implementaions that allow SRV queries for names not in |
|
| 470 |
+ // There are DNS implementations that allow SRV queries for names not in |
|
| 471 | 471 |
// the format defined by RFC 2782. Hence specific validations checks are |
| 472 | 472 |
// not done |
| 473 | 473 |
parts := strings.Split(name, ".") |
| ... | ... |
@@ -1098,8 +1099,8 @@ func OptionDNSOptions(options string) SandboxOption {
|
| 1098 | 1098 |
} |
| 1099 | 1099 |
} |
| 1100 | 1100 |
|
| 1101 |
-// OptionUseDefaultSandbox function returns an option setter for using default sandbox to |
|
| 1102 |
-// be passed to container Create method. |
|
| 1101 |
+// OptionUseDefaultSandbox function returns an option setter for using default sandbox |
|
| 1102 |
+// (host namespace) to be passed to container Create method. |
|
| 1103 | 1103 |
func OptionUseDefaultSandbox() SandboxOption {
|
| 1104 | 1104 |
return func(sb *sandbox) {
|
| 1105 | 1105 |
sb.config.useDefaultSandBox = true |
| ... | ... |
@@ -1169,8 +1170,9 @@ func OptionIngress() SandboxOption {
|
| 1169 | 1169 |
|
| 1170 | 1170 |
// OptionLoadBalancer function returns an option setter for marking a |
| 1171 | 1171 |
// sandbox as a load balancer sandbox. |
| 1172 |
-func OptionLoadBalancer() SandboxOption {
|
|
| 1172 |
+func OptionLoadBalancer(nid string) SandboxOption {
|
|
| 1173 | 1173 |
return func(sb *sandbox) {
|
| 1174 |
+ sb.loadBalancerNID = nid |
|
| 1174 | 1175 |
sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeLoadBalancer) |
| 1175 | 1176 |
} |
| 1176 | 1177 |
} |
| ... | ... |
@@ -81,7 +81,9 @@ func (sb *sandbox) buildHostsFile() error {
|
| 81 | 81 |
} |
| 82 | 82 |
|
| 83 | 83 |
// This is for the host mode networking |
| 84 |
- if sb.config.originHostsPath != "" {
|
|
| 84 |
+ if sb.config.useDefaultSandBox && len(sb.config.extraHosts) == 0 {
|
|
| 85 |
+ // We are working under the assumption that the origin file option had been properly expressed by the upper layer |
|
| 86 |
+ // if not here we are going to error out |
|
| 85 | 87 |
if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) {
|
| 86 | 88 |
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err)
|
| 87 | 89 |
} |
| ... | ... |
@@ -190,8 +192,13 @@ func (sb *sandbox) setupDNS() error {
|
| 190 | 190 |
return err |
| 191 | 191 |
} |
| 192 | 192 |
|
| 193 |
- // This is for the host mode networking |
|
| 194 |
- if sb.config.originResolvConfPath != "" {
|
|
| 193 |
+ // When the user specify a conainter in the host namespace and do no have any dns option specified |
|
| 194 |
+ // we just copy the host resolv.conf from the host itself |
|
| 195 |
+ if sb.config.useDefaultSandBox && |
|
| 196 |
+ len(sb.config.dnsList) == 0 && len(sb.config.dnsSearchList) == 0 && len(sb.config.dnsOptionsList) == 0 {
|
|
| 197 |
+ |
|
| 198 |
+ // We are working under the assumption that the origin file option had been properly expressed by the upper layer |
|
| 199 |
+ // if not here we are going to error out |
|
| 195 | 200 |
if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil {
|
| 196 | 201 |
if !os.IsNotExist(err) {
|
| 197 | 202 |
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err)
|
| ... | ... |
@@ -204,7 +211,12 @@ func (sb *sandbox) setupDNS() error {
|
| 204 | 204 |
return nil |
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 |
- currRC, err := resolvconf.Get() |
|
| 207 |
+ originResolvConfPath := sb.config.originResolvConfPath |
|
| 208 |
+ if originResolvConfPath == "" {
|
|
| 209 |
+ // if not specified fallback to default /etc/resolv.conf |
|
| 210 |
+ originResolvConfPath = resolvconf.DefaultResolvConf |
|
| 211 |
+ } |
|
| 212 |
+ currRC, err := resolvconf.GetSpecific(originResolvConfPath) |
|
| 208 | 213 |
if err != nil {
|
| 209 | 214 |
if !os.IsNotExist(err) {
|
| 210 | 215 |
return err |
| ... | ... |
@@ -241,7 +253,7 @@ func (sb *sandbox) setupDNS() error {
|
| 241 | 241 |
sb.setExternalResolvers(newRC.Content, types.IPv4, false) |
| 242 | 242 |
} else {
|
| 243 | 243 |
// If the host resolv.conf file has 127.0.0.x container should |
| 244 |
- // use the host restolver for queries. This is supported by the |
|
| 244 |
+ // use the host resolver for queries. This is supported by the |
|
| 245 | 245 |
// docker embedded DNS server. Hence save the external resolvers |
| 246 | 246 |
// before filtering it out. |
| 247 | 247 |
sb.setExternalResolvers(currRC.Content, types.IPv4, true) |
| ... | ... |
@@ -271,7 +283,7 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
|
| 271 | 271 |
) |
| 272 | 272 |
|
| 273 | 273 |
// This is for the host mode networking |
| 274 |
- if sb.config.originResolvConfPath != "" {
|
|
| 274 |
+ if sb.config.useDefaultSandBox {
|
|
| 275 | 275 |
return nil |
| 276 | 276 |
} |
| 277 | 277 |
|
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"net" |
| 6 | 6 |
"sync" |
| 7 | 7 |
|
| 8 |
- "github.com/docker/libnetwork/common" |
|
| 8 |
+ "github.com/docker/libnetwork/internal/setmatrix" |
|
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
var ( |
| ... | ... |
@@ -54,7 +54,7 @@ type service struct {
|
| 54 | 54 |
// associated with it. At stable state the endpoint ID expected is 1 |
| 55 | 55 |
// but during transition and service change it is possible to have |
| 56 | 56 |
// temporary more than 1 |
| 57 |
- ipToEndpoint common.SetMatrix |
|
| 57 |
+ ipToEndpoint setmatrix.SetMatrix |
|
| 58 | 58 |
|
| 59 | 59 |
deleted bool |
| 60 | 60 |
|
| ... | ... |
@@ -5,7 +5,7 @@ package libnetwork |
| 5 | 5 |
import ( |
| 6 | 6 |
"net" |
| 7 | 7 |
|
| 8 |
- "github.com/docker/libnetwork/common" |
|
| 8 |
+ "github.com/docker/libnetwork/internal/setmatrix" |
|
| 9 | 9 |
"github.com/sirupsen/logrus" |
| 10 | 10 |
) |
| 11 | 11 |
|
| ... | ... |
@@ -139,7 +139,7 @@ func newService(name string, id string, ingressPorts []*PortConfig, serviceAlias |
| 139 | 139 |
ingressPorts: ingressPorts, |
| 140 | 140 |
loadBalancers: make(map[string]*loadBalancer), |
| 141 | 141 |
aliases: serviceAliases, |
| 142 |
- ipToEndpoint: common.NewSetMatrix(), |
|
| 142 |
+ ipToEndpoint: setmatrix.NewSetMatrix(), |
|
| 143 | 143 |
} |
| 144 | 144 |
} |
| 145 | 145 |
|
| ... | ... |
@@ -27,7 +27,7 @@ import ( |
| 27 | 27 |
|
| 28 | 28 |
func init() {
|
| 29 | 29 |
reexec.Register("fwmarker", fwMarker)
|
| 30 |
- reexec.Register("redirecter", redirecter)
|
|
| 30 |
+ reexec.Register("redirector", redirector)
|
|
| 31 | 31 |
} |
| 32 | 32 |
|
| 33 | 33 |
// Populate all loadbalancers on the network that the passed endpoint |
| ... | ... |
@@ -431,7 +431,7 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 431 | 431 |
// DOCKER-USER so the user is able to filter packet first. |
| 432 | 432 |
// The second rule should be jump to INGRESS-CHAIN. |
| 433 | 433 |
// This chain has the rules to allow access to the published ports for swarm tasks |
| 434 |
-// from local bridge networks and docker_gwbridge (ie:taks on other swarm netwroks) |
|
| 434 |
+// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) |
|
| 435 | 435 |
func arrangeIngressFilterRule() {
|
| 436 | 436 |
if iptables.ExistChain(ingressChain, iptables.Filter) {
|
| 437 | 437 |
if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
| ... | ... |
@@ -668,7 +668,7 @@ func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) e |
| 668 | 668 |
|
| 669 | 669 |
cmd := &exec.Cmd{
|
| 670 | 670 |
Path: reexec.Self(), |
| 671 |
- Args: append([]string{"redirecter"}, path, eIP.String(), ingressPortsFile),
|
|
| 671 |
+ Args: append([]string{"redirector"}, path, eIP.String(), ingressPortsFile),
|
|
| 672 | 672 |
Stdout: os.Stdout, |
| 673 | 673 |
Stderr: os.Stderr, |
| 674 | 674 |
} |
| ... | ... |
@@ -680,8 +680,8 @@ func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) e |
| 680 | 680 |
return nil |
| 681 | 681 |
} |
| 682 | 682 |
|
| 683 |
-// Redirecter reexec function. |
|
| 684 |
-func redirecter() {
|
|
| 683 |
+// Redirector reexec function. |
|
| 684 |
+func redirector() {
|
|
| 685 | 685 |
runtime.LockOSThread() |
| 686 | 686 |
defer runtime.UnlockOSThread() |
| 687 | 687 |
|