From 0fc52ca6dd628f2b9163f5d328d1d749c6708de4 Mon Sep 17 00:00:00 2001 From: Flavio Crisciani Date: Mon, 16 Jul 2018 17:46:47 -0700 Subject: [PATCH 1/3] Add a way to get a pid of a process Signed-off-by: Flavio Crisciani --- internal/procfs/procfs_linux.go | 105 ++++++++++++++++++ internal/procfs/procfs_linux_test.go | 36 ++++++ .../docker/libnetwork/osl/namespace_linux.go | 16 ++- 3 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 internal/procfs/procfs_linux.go create mode 100644 internal/procfs/procfs_linux_test.go diff --git a/internal/procfs/procfs_linux.go b/internal/procfs/procfs_linux.go new file mode 100644 index 0000000000000..8a681108789ff --- /dev/null +++ b/internal/procfs/procfs_linux.go @@ -0,0 +1,105 @@ +package procfs + +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "unicode" + + "github.com/sirupsen/logrus" +) + +// PidOf finds process(es) with a specified name (regexp match) +// and return their pid(s) +func PidOf(name string) ([]int, error) { + if len(name) == 0 { + return []int{}, fmt.Errorf("name should not be empty") + } + re, err := regexp.Compile("(^|/)" + name + "$") + if err != nil { + return []int{}, err + } + return getPids(re), nil +} + +func getPids(re *regexp.Regexp) []int { + pids := []int{} + + dirFD, err := os.Open("/proc") + if err != nil { + return nil + } + defer dirFD.Close() + + for { + // Read a small number at a time in case there are many entries, we don't want to + // allocate a lot here. + ls, err := dirFD.Readdir(10) + if err == io.EOF { + break + } + if err != nil { + return nil + } + + for _, entry := range ls { + if !entry.IsDir() { + continue + } + + // If the directory is not a number (i.e. not a PID), skip it + pid, err := strconv.Atoi(entry.Name()) + if err != nil { + continue + } + + cmdline, err := ioutil.ReadFile(filepath.Join("/proc", entry.Name(), "cmdline")) + if err != nil { + logrus.Infof("Error reading file %s: %+v", filepath.Join("/proc", entry.Name(), "cmdline"), err) + continue + } + + // The bytes we read have '\0' as a separator for the command line + parts := bytes.SplitN(cmdline, []byte{0}, 2) + if len(parts) == 0 { + continue + } + // Split the command line itself we are interested in just the first part + exe := strings.FieldsFunc(string(parts[0]), func(c rune) bool { + return unicode.IsSpace(c) || c == ':' + }) + if len(exe) == 0 { + continue + } + // Check if the name of the executable is what we are looking for + if re.MatchString(exe[0]) { + // Grab the PID from the directory path + pids = append(pids, pid) + } + } + } + + return pids +} diff --git a/internal/procfs/procfs_linux_test.go b/internal/procfs/procfs_linux_test.go new file mode 100644 index 0000000000000..4c5d822f76e03 --- /dev/null +++ b/internal/procfs/procfs_linux_test.go @@ -0,0 +1,36 @@ +package procfs + +import ( + "os" + "path/filepath" + "regexp" + "runtime" + "testing" + + "gotest.tools/assert" +) + +func TestPidOf(t *testing.T) { + pids, err := PidOf(filepath.Base(os.Args[0])) + assert.NilError(t, err) + assert.Check(t, len(pids) == 1) + assert.DeepEqual(t, pids[0], os.Getpid()) +} + +func BenchmarkGetPids(b *testing.B) { + if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { + b.Skipf("not supported on GOOS=%s", runtime.GOOS) + } + + re, err := regexp.Compile("(^|/)" + filepath.Base(os.Args[0]) + "$") + assert.Check(b, err == nil) + + for i := 0; i < b.N; i++ { + pids := getPids(re) + + b.StopTimer() + assert.Check(b, len(pids) > 0) + assert.Check(b, pids[0] == os.Getpid()) + b.StartTimer() + } +} diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go index 45c46852fc57d..4ae11b8e7b870 100644 --- a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go @@ -394,13 +394,10 @@ func (n *networkNamespace) InvokeFunc(f func()) error { // InitOSContext initializes OS context while configuring network resources func InitOSContext() func() { runtime.LockOSThread() - if err := ns.SetNamespace(); err != nil { - logrus.Error(err) - } return runtime.UnlockOSThread } -func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error { +func nsInvoke(path string, prefunc, postfunc func(int) error) error { defer InitOSContext()() newNs, err := netns.GetFromPath(path) @@ -415,10 +412,14 @@ func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD return fmt.Errorf("failed in prefunc: %v", err) } + // save the current namespace (host namespace) + curNs, _ := netns.Get() if err = netns.Set(newNs); err != nil { return err } - defer ns.SetNamespace() + defer curNs.Close() + // will restore the previous namespace before unlocking the thread + defer netns.Set(curNs) // Invoked after the namespace switch. return postfunc(ns.ParseHandlerInt()) @@ -651,7 +652,10 @@ func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) { for _, t := range types { switch t { case SandboxTypeLoadBalancer: - kernel.ApplyOSTweaks(loadBalancerConfig) + nsInvoke(n.nsPath(), + func(nsFD int) error { return nil }, + func(callerFD int) error { kernel.ApplyOSTweaks(loadBalancerConfig); return nil }, + ) } } } From e353e7e3f0ce8eceeff657393cba2876375403fa Mon Sep 17 00:00:00 2001 From: Flavio Crisciani Date: Tue, 17 Jul 2018 12:11:38 -0700 Subject: [PATCH 2/3] Fixes for resolv.conf Handle the case of systemd-resolved, and if in place use a different resolv.conf source. Set appropriately the option on libnetwork. Move unix specific code to container_operation_unix Signed-off-by: Flavio Crisciani --- daemon/config/config.go | 4 +-- daemon/config/config_common_unix.go | 6 +++++ daemon/config/config_unix.go | 2 ++ daemon/container_operations.go | 10 +------- daemon/container_operations_unix.go | 10 +++++++- daemon/container_operations_windows.go | 2 +- daemon/daemon.go | 3 +++ daemon/daemon_linux.go | 34 ++++++++++++++++++++++++++ daemon/daemon_unsupported.go | 4 +++ daemon/daemon_windows.go | 3 +++ 10 files changed, 65 insertions(+), 13 deletions(-) diff --git a/daemon/config/config.go b/daemon/config/config.go index 6cda223a11811..3aa87038808d2 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -75,6 +75,8 @@ type commonBridgeConfig struct { type NetworkConfig struct { // Default address pools for docker networks DefaultAddressPools opts.PoolsOpt `json:"default-address-pools,omitempty"` + // NetworkControlPlaneMTU allows to specify the control plane MTU, this will allow to optimize the network use in some components + NetworkControlPlaneMTU int `json:"network-control-plane-mtu,omitempty"` } // CommonTLSOptions defines TLS configuration for the daemon server. @@ -192,8 +194,6 @@ type CommonConfig struct { // Exposed node Generic Resources // e.g: ["orange=red", "orange=green", "orange=blue", "apple=3"] NodeGenericResources []string `json:"node-generic-resources,omitempty"` - // NetworkControlPlaneMTU allows to specify the control plane MTU, this will allow to optimize the network use in some components - NetworkControlPlaneMTU int `json:"network-control-plane-mtu,omitempty"` // ContainerAddr is the address used to connect to containerd if we're // not starting it ourselves diff --git a/daemon/config/config_common_unix.go b/daemon/config/config_common_unix.go index 4bdf7588692dc..0a862d3b50a9b 100644 --- a/daemon/config/config_common_unix.go +++ b/daemon/config/config_common_unix.go @@ -69,3 +69,9 @@ func (conf *Config) GetInitPath() string { } return DefaultInitBinary } + +// GetResolvConf returns the appropriate resolv.conf +// Check setupResolvConf on how this is selected +func (conf *Config) GetResolvConf() string { + return conf.ResolvConf +} diff --git a/daemon/config/config_unix.go b/daemon/config/config_unix.go index 1970928f9b146..5ed6abd89e8fd 100644 --- a/daemon/config/config_unix.go +++ b/daemon/config/config_unix.go @@ -37,6 +37,8 @@ type Config struct { ShmSize opts.MemBytes `json:"default-shm-size,omitempty"` NoNewPrivileges bool `json:"no-new-privileges,omitempty"` IpcMode string `json:"default-ipc-mode,omitempty"` + // ResolvConf is the path to the configuration of the host resolver + ResolvConf string `json:"resolv-conf,omitempty"` } // BridgeConfig stores all the bridge driver specific diff --git a/daemon/container_operations.go b/daemon/container_operations.go index df84f88f3f6e4..909c7ccb275c6 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -63,21 +63,13 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]lib if container.HostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) - if len(container.HostConfig.ExtraHosts) == 0 { - sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) - } - if len(container.HostConfig.DNS) == 0 && len(daemon.configStore.DNS) == 0 && - len(container.HostConfig.DNSSearch) == 0 && len(daemon.configStore.DNSSearch) == 0 && - len(container.HostConfig.DNSOptions) == 0 && len(daemon.configStore.DNSOptions) == 0 { - sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) - } } else { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } - if err = setupPathsAndSandboxOptions(container, &sboxOptions); err != nil { + if err = daemon.setupPathsAndSandboxOptions(container, &sboxOptions); err != nil { return nil, err } diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index bc7ee452332b6..e66030d9c5d39 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -369,9 +369,17 @@ func (daemon *Daemon) isNetworkHotPluggable() bool { return true } -func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { +func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { var err error + if container.HostConfig.NetworkMode.IsHost() { + // Point to the host files, so that will be copied into the container running in host mode + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) + } else { + *sboxOptions = append(*sboxOptions, libnetwork.OptionOriginResolvConfPath(daemon.configStore.GetResolvConf())) + } + container.HostsPath, err = container.GetRootResourcePath("hosts") if err != nil { return err diff --git a/daemon/container_operations_windows.go b/daemon/container_operations_windows.go index 562528a8ef20b..349d3a1566fad 100644 --- a/daemon/container_operations_windows.go +++ b/daemon/container_operations_windows.go @@ -155,7 +155,7 @@ func (daemon *Daemon) isNetworkHotPluggable() bool { return true } -func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { +func (daemon *Daemon) setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error { return nil } diff --git a/daemon/daemon.go b/daemon/daemon.go index 119fac2a0a4fd..c579766e95e7b 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -581,6 +581,9 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe // Do we have a disabled network? config.DisableBridge = isBridgeNetworkDisabled(config) + // Setup the resolv.conf + setupResolvConf(config) + // Verify the platform is supported as a daemon if !platformSupported { return nil, errSystemNotSupported diff --git a/daemon/daemon_linux.go b/daemon/daemon_linux.go index 7cb6727534676..6a5790b4fc94e 100644 --- a/daemon/daemon_linux.go +++ b/daemon/daemon_linux.go @@ -8,12 +8,19 @@ import ( "regexp" "strings" + "github.com/docker/docker/daemon/config" + "github.com/docker/docker/internal/procfs" "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/mount" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) +const ( + defaultResolvConf = "/etc/resolv.conf" + alternateResolvConf = "/run/systemd/resolve/resolv.conf" +) + // On Linux, plugins use a static path for storing execution state, // instead of deriving path from daemon's exec-root. This is because // plugin socket files are created here and they cannot exceed max @@ -131,3 +138,30 @@ func shouldUnmountRoot(root string, info *mount.Info) bool { } return hasMountinfoOption(info.Optional, sharedPropagationOption) } + +// setupResolvConf sets the appropriate resolv.conf file if not specified +// When systemd-resolved is running the default /etc/resolv.conf points to +// localhost. In this case fetch the alternative config file that is in a +// different path so that containers can use it +// In all the other cases fallback to the default one +func setupResolvConf(config *config.Config) { + if config.ResolvConf != "" { + return + } + + config.ResolvConf = defaultResolvConf + pids, err := procfs.PidOf("systemd-resolved") + if err != nil { + logrus.Errorf("unable to check systemd-resolved status: %s", err) + return + } + if len(pids) > 0 && pids[0] > 0 { + _, err := os.Stat(alternateResolvConf) + if err == nil { + logrus.Infof("systemd-resolved is running, so using resolvconf: %s", alternateResolvConf) + config.ResolvConf = alternateResolvConf + return + } + logrus.Infof("systemd-resolved is running, but %s is not present, fallback to %s", alternateResolvConf, defaultResolvConf) + } +} diff --git a/daemon/daemon_unsupported.go b/daemon/daemon_unsupported.go index ee680b641136e..6d8ac6224bd05 100644 --- a/daemon/daemon_unsupported.go +++ b/daemon/daemon_unsupported.go @@ -1,5 +1,9 @@ // +build !linux,!freebsd,!windows package daemon // import "github.com/docker/docker/daemon" +import "github.com/docker/docker/daemon/config" const platformSupported = false + +func setupResolvConf(config *config.Config) { +} diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 1f801032df3b7..98f89f39d3639 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -653,3 +653,6 @@ func (daemon *Daemon) loadRuntimes() error { func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error { return nil } + +func setupResolvConf(config *config.Config) { +} From fc4ebe0b8bc5e41b3b2d108c21dc19ea08a9fcb7 Mon Sep 17 00:00:00 2001 From: Flavio Crisciani Date: Tue, 17 Jul 2018 12:12:18 -0700 Subject: [PATCH 3/3] Vendor libnetwork Signed-off-by: Flavio Crisciani --- hack/dockerfile/install/proxy.installer | 2 +- vendor.conf | 2 +- vendor/github.com/docker/libnetwork/README.md | 11 ++ vendor/github.com/docker/libnetwork/agent.go | 2 +- .../docker/libnetwork/bitseq/sequence.go | 2 +- .../docker/libnetwork/controller.go | 4 +- .../docker/libnetwork/datastore/datastore.go | 6 +- .../docker/libnetwork/datastore/mock_store.go | 12 +- .../docker/libnetwork/diagnostic/server.go | 10 +- .../docker/libnetwork/driverapi/driverapi.go | 6 +- .../libnetwork/drivers/bridge/bridge.go | 2 +- .../drivers/ipvlan/ipvlan_joinleave.go | 4 +- .../drivers/ipvlan/ipvlan_network.go | 4 +- .../libnetwork/drivers/ipvlan/ipvlan_setup.go | 4 +- .../libnetwork/drivers/ipvlan/ipvlan_state.go | 2 +- .../drivers/macvlan/macvlan_joinleave.go | 4 +- .../drivers/macvlan/macvlan_network.go | 4 +- .../drivers/macvlan/macvlan_setup.go | 4 +- .../libnetwork/drivers/overlay/encryption.go | 2 +- .../libnetwork/drivers/overlay/joinleave.go | 10 +- .../libnetwork/drivers/overlay/ov_network.go | 171 ++++++++++-------- .../libnetwork/drivers/overlay/overlay.go | 19 +- .../libnetwork/drivers/overlay/peerdb.go | 17 +- .../libnetwork/drivers/remote/api/api.go | 2 +- .../libnetwork/drvregistry/drvregistry.go | 2 +- .../{common => internal/caller}/caller.go | 8 +- .../setmatrix}/setmatrix.go | 2 +- .../docker/libnetwork/iptables/firewalld.go | 2 +- .../docker/libnetwork/iptables/iptables.go | 2 +- .../docker/libnetwork/ipvs/netlink.go | 4 +- .../github.com/docker/libnetwork/network.go | 30 +-- .../docker/libnetwork/networkdb/cluster.go | 2 +- .../docker/libnetwork/networkdb/networkdb.go | 4 +- .../libnetwork/networkdb/networkdb.pb.go | 4 +- .../libnetwork/networkdb/networkdb.proto | 4 +- .../networkdb/networkdbdiagnostic.go | 24 +-- .../docker/libnetwork/osl/interface_linux.go | 10 + .../docker/libnetwork/osl/kernel/knobs.go | 2 +- .../docker/libnetwork/osl/namespace_linux.go | 16 +- .../libnetwork/resolvconf/resolvconf.go | 15 +- .../github.com/docker/libnetwork/resolver.go | 2 +- .../github.com/docker/libnetwork/sandbox.go | 10 +- .../docker/libnetwork/sandbox_dns_unix.go | 24 ++- .../github.com/docker/libnetwork/service.go | 4 +- .../docker/libnetwork/service_common.go | 4 +- .../docker/libnetwork/service_linux.go | 10 +- 46 files changed, 259 insertions(+), 232 deletions(-) rename vendor/github.com/docker/libnetwork/{common => internal/caller}/caller.go (66%) rename vendor/github.com/docker/libnetwork/{common => internal/setmatrix}/setmatrix.go (99%) diff --git a/hack/dockerfile/install/proxy.installer b/hack/dockerfile/install/proxy.installer index 4983d909b363a..ed9ab5363270e 100755 --- a/hack/dockerfile/install/proxy.installer +++ b/hack/dockerfile/install/proxy.installer @@ -3,7 +3,7 @@ # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When # updating the binary version, consider updating github.com/docker/libnetwork # in vendor.conf accordingly -LIBNETWORK_COMMIT=3ac297bc7fd0afec9051bbb47024c9bc1d75bf5b +LIBNETWORK_COMMIT=f30a35b091cc2a431ef9856c75c343f75bb5f2e2 install_proxy() { case "$1" in diff --git a/vendor.conf b/vendor.conf index 0a015862bddca..c5916c0a27d43 100644 --- a/vendor.conf +++ b/vendor.conf @@ -37,7 +37,7 @@ github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b #get libnetwork packages # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly -github.com/docker/libnetwork d00ceed44cc447c77f25cdf5d59e83163bdcb4c9 +github.com/docker/libnetwork f30a35b091cc2a431ef9856c75c343f75bb5f2e2 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec diff --git a/vendor/github.com/docker/libnetwork/README.md b/vendor/github.com/docker/libnetwork/README.md index 981b62bb1cb5e..a9020381abe8f 100644 --- a/vendor/github.com/docker/libnetwork/README.md +++ b/vendor/github.com/docker/libnetwork/README.md @@ -15,6 +15,17 @@ There are many networking solutions available to suit a broad range of use-cases ```go +import ( + "fmt" + "log" + + "github.com/docker/docker/pkg/reexec" + "github.com/docker/libnetwork" + "github.com/docker/libnetwork/config" + "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/options" +) + func main() { if reexec.Init() { return diff --git a/vendor/github.com/docker/libnetwork/agent.go b/vendor/github.com/docker/libnetwork/agent.go index c90fa81ff86f2..a9d77e26701d4 100644 --- a/vendor/github.com/docker/libnetwork/agent.go +++ b/vendor/github.com/docker/libnetwork/agent.go @@ -194,7 +194,7 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error { func (c *controller) agentSetup(clusterProvider cluster.Provider) error { agent := c.getAgent() - // If the agent is already present there is no need to try to initilize it again + // If the agent is already present there is no need to try to initialize it again if agent != nil { return nil } diff --git a/vendor/github.com/docker/libnetwork/bitseq/sequence.go b/vendor/github.com/docker/libnetwork/bitseq/sequence.go index 4bd0f3ca5dd7f..2235601ac373d 100644 --- a/vendor/github.com/docker/libnetwork/bitseq/sequence.go +++ b/vendor/github.com/docker/libnetwork/bitseq/sequence.go @@ -372,7 +372,7 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial h.Lock() } - // Previous atomic push was succesfull. Save private copy to local copy + // Previous atomic push was successful. Save private copy to local copy h.unselected = nh.unselected h.head = nh.head h.dbExists = nh.dbExists diff --git a/vendor/github.com/docker/libnetwork/controller.go b/vendor/github.com/docker/libnetwork/controller.go index f3b6b02aba5e2..f956ddb2800b4 100644 --- a/vendor/github.com/docker/libnetwork/controller.go +++ b/vendor/github.com/docker/libnetwork/controller.go @@ -121,7 +121,7 @@ type NetworkController interface { // Stop network controller Stop() - // ReloadCondfiguration updates the controller configuration + // ReloadConfiguration updates the controller configuration ReloadConfiguration(cfgOptions ...config.Option) error // SetClusterProvider sets cluster provider @@ -1107,6 +1107,8 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S sb.config.hostsPath = filepath.Join(c.cfg.Daemon.DataDir, "/network/files/hosts") sb.config.resolvConfPath = filepath.Join(c.cfg.Daemon.DataDir, "/network/files/resolv.conf") sb.id = "ingress_sbox" + } else if sb.loadBalancerNID != "" { + sb.id = "lb_" + sb.loadBalancerNID } c.Unlock() diff --git a/vendor/github.com/docker/libnetwork/datastore/datastore.go b/vendor/github.com/docker/libnetwork/datastore/datastore.go index 82feef1c84eba..e35dc43b2e59c 100644 --- a/vendor/github.com/docker/libnetwork/datastore/datastore.go +++ b/vendor/github.com/docker/libnetwork/datastore/datastore.go @@ -185,7 +185,7 @@ func Key(key ...string) string { func ParseKey(key string) ([]string, error) { chain := strings.Split(strings.Trim(key, "/"), "/") - // The key must atleast be equal to the rootChain in order to be considered as valid + // The key must at least be equal to the rootChain in order to be considered as valid if len(chain) <= len(rootChain) || !reflect.DeepEqual(chain[0:len(rootChain)], rootChain) { return nil, types.BadRequestErrorf("invalid Key : %s", key) } @@ -589,7 +589,7 @@ func (ds *datastore) DeleteObject(kvObject KVObject) error { defer ds.Unlock() } - // cleaup the cache first + // cleanup the cache first if ds.cache != nil { // If persistent store is skipped, sequencing needs to // happen in cache. @@ -645,7 +645,7 @@ func (ds *datastore) DeleteTree(kvObject KVObject) error { defer ds.Unlock() } - // cleaup the cache first + // cleanup the cache first if ds.cache != nil { // If persistent store is skipped, sequencing needs to // happen in cache. diff --git a/vendor/github.com/docker/libnetwork/datastore/mock_store.go b/vendor/github.com/docker/libnetwork/datastore/mock_store.go index 0817339b6a487..215cc4fd01ea2 100644 --- a/vendor/github.com/docker/libnetwork/datastore/mock_store.go +++ b/vendor/github.com/docker/libnetwork/datastore/mock_store.go @@ -8,8 +8,8 @@ import ( ) var ( - // ErrNotImplmented exported - ErrNotImplmented = errors.New("Functionality not implemented") + // ErrNotImplemented exported + ErrNotImplemented = errors.New("Functionality not implemented") ) // MockData exported @@ -65,7 +65,7 @@ func (s *MockStore) Exists(key string) (bool, error) { // List gets a range of values at "directory" func (s *MockStore) List(prefix string) ([]*store.KVPair, error) { - return nil, ErrNotImplmented + return nil, ErrNotImplemented } // DeleteTree deletes a range of values at "directory" @@ -76,17 +76,17 @@ func (s *MockStore) DeleteTree(prefix string) error { // Watch a single key for modifications func (s *MockStore) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) { - return nil, ErrNotImplmented + return nil, ErrNotImplemented } // WatchTree triggers a watch on a range of values at "directory" func (s *MockStore) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) { - return nil, ErrNotImplmented + return nil, ErrNotImplemented } // NewLock exposed func (s *MockStore) NewLock(key string, options *store.LockOptions) (store.Locker, error) { - return nil, ErrNotImplmented + return nil, ErrNotImplemented } // AtomicPut put a value at "key" if the key has not been diff --git a/vendor/github.com/docker/libnetwork/diagnostic/server.go b/vendor/github.com/docker/libnetwork/diagnostic/server.go index f351762bd1cb3..cca30cd32ea49 100644 --- a/vendor/github.com/docker/libnetwork/diagnostic/server.go +++ b/vendor/github.com/docker/libnetwork/diagnostic/server.go @@ -9,7 +9,7 @@ import ( "sync/atomic" stackdump "github.com/docker/docker/pkg/signal" - "github.com/docker/libnetwork/common" + "github.com/docker/libnetwork/internal/caller" "github.com/sirupsen/logrus" ) @@ -127,7 +127,7 @@ func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) { rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path)) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("command not implemented done") HTTPReply(w, rsp, json) @@ -138,7 +138,7 @@ func help(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("help done") n, ok := ctx.(*Server) @@ -156,7 +156,7 @@ func ready(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("ready done") HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), json) } @@ -166,7 +166,7 @@ func stackTrace(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("stack trace") path, err := stackdump.DumpStacks("/tmp/") diff --git a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go index 48a14ae57a8ba..3d667ceb7e792 100644 --- a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go +++ b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go @@ -75,10 +75,10 @@ type Driver interface { // DecodeTableEntry passes the driver a key, value pair from table it registered // with libnetwork. Driver should return {object ID, map[string]string} tuple. // If DecodeTableEntry is called for a table associated with NetworkObject or - // EndpointObject the return object ID should be the network id or endppoint id + // EndpointObject the return object ID should be the network id or endpoint id // associated with that entry. map should have information about the object that // can be presented to the user. - // For exampe: overlay driver returns the VTEP IP of the host that has the endpoint + // For example: overlay driver returns the VTEP IP of the host that has the endpoint // which is shown in 'network inspect --verbose' DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) @@ -97,7 +97,7 @@ type NetworkInfo interface { TableEventRegister(tableName string, objType ObjectType) error } -// InterfaceInfo provides a go interface for drivers to retrive +// InterfaceInfo provides a go interface for drivers to retrieve // network information to interface resources. type InterfaceInfo interface { // SetMacAddress allows the driver to set the mac address to the endpoint interface diff --git a/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go index 0383ce35a8076..535da3c1ad712 100644 --- a/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -104,7 +104,7 @@ type containerConfiguration struct { ChildEndpoints []string } -// cnnectivityConfiguration represents the user specified configuration regarding the external connectivity +// connectivityConfiguration represents the user specified configuration regarding the external connectivity type connectivityConfiguration struct { PortBindings []types.PortBinding ExposedPorts []types.TransportPort diff --git a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go index bcbbbfdfd2b04..fc56bce5a6681 100644 --- a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go +++ b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go @@ -84,7 +84,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } v4gw, _, err := net.ParseCIDR(s.GwIP) if err != nil { - return fmt.Errorf("gatway %s is not a valid ipv4 address: %v", s.GwIP, err) + return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err) } err = jinfo.SetGateway(v4gw) if err != nil { @@ -101,7 +101,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } v6gw, _, err := net.ParseCIDR(s.GwIP) if err != nil { - return fmt.Errorf("gatway %s is not a valid ipv6 address: %v", s.GwIP, err) + return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err) } err = jinfo.SetGatewayIPv6(v6gw) if err != nil { diff --git a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go index 5451cced91c1c..8825e1e117248 100644 --- a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go +++ b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go @@ -68,7 +68,7 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo err = d.storeUpdate(config) if err != nil { d.deleteNetwork(config.ID) - logrus.Debugf("encoutered an error rolling back a network create for %s : %v", config.ID, err) + logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err) return err } @@ -92,7 +92,7 @@ func (d *driver) createNetwork(config *configuration) error { return err } config.CreatedSlaveLink = true - // notify the user in logs they have limited comunicatins + // notify the user in logs they have limited communications if config.Parent == getDummyName(stringid.TruncateID(config.ID)) { logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s", config.Parent) diff --git a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go index d4639eb7ad38e..da8d8faeb8534 100644 --- a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go +++ b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go @@ -30,7 +30,7 @@ func createIPVlan(containerIfName, parent, ipvlanMode string) (string, error) { // Get the link for the master index (Example: the docker host eth iface) parentLink, err := ns.NlHandle().LinkByName(parent) if err != nil { - return "", fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", ipvlanType, parent, err) + return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, parent, err) } // Create an ipvlan link ipvlan := &netlink.IPVlan{ @@ -169,7 +169,7 @@ func createDummyLink(dummyName, truncNetID string) error { } parentDummyLink, err := ns.NlHandle().LinkByName(dummyName) if err != nil { - return fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", ipvlanType, dummyName, err) + return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, dummyName, err) } // bring the new netlink iface up if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil { diff --git a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go index 2a4ad25b4073f..dc73b6893d36b 100644 --- a/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go +++ b/vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go @@ -31,7 +31,7 @@ func (d *driver) deleteNetwork(nid string) { d.Unlock() } -// getNetworks Safely returns a slice of existng networks +// getNetworks Safely returns a slice of existing networks func (d *driver) getNetworks() []*network { d.Lock() defer d.Unlock() diff --git a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go index 6716d58de6a7a..72d5c24ddc4e5 100644 --- a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go +++ b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go @@ -46,7 +46,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } v4gw, _, err := net.ParseCIDR(s.GwIP) if err != nil { - return fmt.Errorf("gatway %s is not a valid ipv4 address: %v", s.GwIP, err) + return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err) } err = jinfo.SetGateway(v4gw) if err != nil { @@ -63,7 +63,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, } v6gw, _, err := net.ParseCIDR(s.GwIP) if err != nil { - return fmt.Errorf("gatway %s is not a valid ipv6 address: %v", s.GwIP, err) + return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err) } err = jinfo.SetGatewayIPv6(v6gw) if err != nil { diff --git a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go index abeb0e6ecb3b7..beeed41638dac 100644 --- a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go +++ b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go @@ -72,7 +72,7 @@ func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo err = d.storeUpdate(config) if err != nil { d.deleteNetwork(config.ID) - logrus.Debugf("encoutered an error rolling back a network create for %s : %v", config.ID, err) + logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err) return err } @@ -96,7 +96,7 @@ func (d *driver) createNetwork(config *configuration) error { return err } config.CreatedSlaveLink = true - // notify the user in logs they have limited comunicatins + // notify the user in logs they have limited communications if config.Parent == getDummyName(stringid.TruncateID(config.ID)) { logrus.Debugf("Empty -o parent= and --internal flags limit communications to other containers inside of network: %s", config.Parent) diff --git a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go index 98d4bd3832a57..fc33ebd707e48 100644 --- a/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go +++ b/vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go @@ -30,7 +30,7 @@ func createMacVlan(containerIfName, parent, macvlanMode string) (string, error) // Get the link for the master index (Example: the docker host eth iface) parentLink, err := ns.NlHandle().LinkByName(parent) if err != nil { - return "", fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", macvlanType, parent, err) + return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, parent, err) } // Create a macvlan link macvlan := &netlink.Macvlan{ @@ -173,7 +173,7 @@ func createDummyLink(dummyName, truncNetID string) error { } parentDummyLink, err := ns.NlHandle().LinkByName(dummyName) if err != nil { - return fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", macvlanType, dummyName, err) + return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, dummyName, err) } // bring the new netlink iface up if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil { diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go b/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go index 8e10906dc1bee..a97e73df82bc9 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go @@ -601,7 +601,7 @@ func (n *network) maxMTU() int { mtu -= vxlanEncap if n.secure { // In case of encryption account for the - // esp packet espansion and padding + // esp packet expansion and padding mtu -= pktExpansion mtu -= (mtu % 4) } diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go b/vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go index 985d9977844ec..a51bcd8985f95 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go @@ -47,18 +47,10 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err) } - if err := n.joinSandbox(false); err != nil { + if err := n.joinSandbox(s, false, true); err != nil { return fmt.Errorf("network sandbox join failed: %v", err) } - if err := n.joinSubnetSandbox(s, false); err != nil { - return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err) - } - - // joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the - // overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox - n.incEndpointCount() - sbox := n.sandbox() overlayIfName, containerIfName, err := createVethPair() diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go index 4dda2801fb8a9..cf32e45951fc5 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go @@ -39,7 +39,7 @@ var ( type networkTable map[string]*network type subnet struct { - once *sync.Once + sboxInit bool vxlanName string brName string vni uint32 @@ -63,7 +63,7 @@ type network struct { endpoints endpointTable driver *driver joinCnt int - once *sync.Once + sboxInit bool initEpoch int initErr error subnets []*subnet @@ -150,7 +150,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d id: id, driver: d, endpoints: endpointTable{}, - once: &sync.Once{}, subnets: []*subnet{}, } @@ -193,7 +192,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d s := &subnet{ subnetIP: ipd.Pool, gwIP: ipd.Gateway, - once: &sync.Once{}, } if len(vnis) != 0 { @@ -277,7 +275,7 @@ func (d *driver) DeleteNetwork(nid string) error { logrus.Warnf("Failed to delete overlay endpoint %.7s from local store: %v", ep.id, err) } } - // flush the peerDB entries + doPeerFlush = true delete(d.networks, nid) @@ -304,29 +302,54 @@ func (d *driver) RevokeExternalConnectivity(nid, eid string) error { return nil } -func (n *network) incEndpointCount() { - n.Lock() - defer n.Unlock() - n.joinCnt++ -} - -func (n *network) joinSandbox(restore bool) error { +func (n *network) joinSandbox(s *subnet, restore bool, incJoinCount bool) error { // If there is a race between two go routines here only one will win // the other will wait. - n.once.Do(func() { - // save the error status of initSandbox in n.initErr so that - // all the racing go routines are able to know the status. + networkOnce.Do(networkOnceInit) + + n.Lock() + // If non-restore initialization occurred and was successful then + // tell the peerDB to initialize the sandbox with all the peers + // previously received from networkdb. But only do this after + // unlocking the network. Otherwise we could deadlock with + // on the peerDB channel while peerDB is waiting for the network lock. + var doInitPeerDB bool + defer func() { + n.Unlock() + if doInitPeerDB { + n.driver.initSandboxPeerDB(n.id) + } + }() + + if !n.sboxInit { n.initErr = n.initSandbox(restore) - }) + doInitPeerDB = n.initErr == nil && !restore + // If there was an error, we cannot recover it + n.sboxInit = true + } - return n.initErr -} + if n.initErr != nil { + return fmt.Errorf("network sandbox join failed: %v", n.initErr) + } -func (n *network) joinSubnetSandbox(s *subnet, restore bool) error { - s.once.Do(func() { - s.initErr = n.initSubnetSandbox(s, restore) - }) - return s.initErr + subnetErr := s.initErr + if !s.sboxInit { + subnetErr = n.initSubnetSandbox(s, restore) + // We can recover from these errors, but not on restore + if restore || subnetErr == nil { + s.initErr = subnetErr + s.sboxInit = true + } + } + if subnetErr != nil { + return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), subnetErr) + } + + if incJoinCount { + n.joinCnt++ + } + + return nil } func (n *network) leaveSandbox() { @@ -337,15 +360,14 @@ func (n *network) leaveSandbox() { return } - // We are about to destroy sandbox since the container is leaving the network - // Reinitialize the once variable so that we will be able to trigger one time - // sandbox initialization(again) when another container joins subsequently. - n.once = &sync.Once{} + n.destroySandbox() + + n.sboxInit = false + n.initErr = nil for _, s := range n.subnets { - s.once = &sync.Once{} + s.sboxInit = false + s.initErr = nil } - - n.destroySandbox() } // to be called while holding network lock @@ -478,7 +500,7 @@ func (n *network) generateVxlanName(s *subnet) string { id = n.id[:5] } - return "vx-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + id + return fmt.Sprintf("vx-%06x-%v", s.vni, id) } func (n *network) generateBridgeName(s *subnet) string { @@ -491,7 +513,7 @@ func (n *network) generateBridgeName(s *subnet) string { } func (n *network) getBridgeNamePrefix(s *subnet) string { - return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s)) + return fmt.Sprintf("ov-%06x", s.vni) } func checkOverlap(nw *net.IPNet) error { @@ -513,7 +535,7 @@ func checkOverlap(nw *net.IPNet) error { } func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error { - sbox := n.sandbox() + sbox := n.sbox // restore overlay osl sandbox Ifaces := make(map[string][]osl.IfaceOption) @@ -542,7 +564,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error deleteInterfaceBySubnet(n.getBridgeNamePrefix(s), s) } // Try to delete the vxlan interface by vni if already present - deleteVxlanByVNI("", n.vxlanID(s)) + deleteVxlanByVNI("", s.vni) if err := checkOverlap(s.subnetIP); err != nil { return err @@ -556,24 +578,24 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error // it must a stale namespace from previous // life. Destroy it completely and reclaim resourced. networkMu.Lock() - path, ok := vniTbl[n.vxlanID(s)] + path, ok := vniTbl[s.vni] networkMu.Unlock() if ok { - deleteVxlanByVNI(path, n.vxlanID(s)) + deleteVxlanByVNI(path, s.vni) if err := syscall.Unmount(path, syscall.MNT_FORCE); err != nil { logrus.Errorf("unmount of %s failed: %v", path, err) } os.Remove(path) networkMu.Lock() - delete(vniTbl, n.vxlanID(s)) + delete(vniTbl, s.vni) networkMu.Unlock() } } // create a bridge and vxlan device for this subnet and move it to the sandbox - sbox := n.sandbox() + sbox := n.sbox if err := sbox.AddInterface(brName, "br", sbox.InterfaceOptions().Address(s.gwIP), @@ -581,13 +603,30 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err) } - err := createVxlan(vxlanName, n.vxlanID(s), n.maxMTU()) + err := createVxlan(vxlanName, s.vni, n.maxMTU()) if err != nil { return err } if err := sbox.AddInterface(vxlanName, "vxlan", sbox.InterfaceOptions().Master(brName)); err != nil { + // If adding vxlan device to the overlay namespace fails, remove the bridge interface we + // already added to the namespace. This allows the caller to try the setup again. + for _, iface := range sbox.Info().Interfaces() { + if iface.SrcName() == brName { + if ierr := iface.Remove(); ierr != nil { + logrus.Errorf("removing bridge failed from ov ns %v failed, %v", n.sbox.Key(), ierr) + } + } + } + + // Also, delete the vxlan interface. Since a global vni id is associated + // with the vxlan interface, an orphaned vxlan interface will result in + // failure of vxlan device creation if the vni is assigned to some other + // network. + if deleteErr := deleteInterface(vxlanName); deleteErr != nil { + logrus.Warnf("could not delete vxlan interface, %s, error %v, after config error, %v", vxlanName, deleteErr, err) + } return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.String(), err) } @@ -619,6 +658,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error return nil } +// Must be called with the network lock func (n *network) initSubnetSandbox(s *subnet, restore bool) error { brName := n.generateBridgeName(s) vxlanName := n.generateVxlanName(s) @@ -633,10 +673,8 @@ func (n *network) initSubnetSandbox(s *subnet, restore bool) error { } } - n.Lock() s.vxlanName = vxlanName s.brName = brName - n.Unlock() return nil } @@ -677,11 +715,7 @@ func (n *network) cleanupStaleSandboxes() { } func (n *network) initSandbox(restore bool) error { - n.Lock() n.initEpoch++ - n.Unlock() - - networkOnce.Do(networkOnceInit) if !restore { if hostMode { @@ -711,12 +745,7 @@ func (n *network) initSandbox(restore bool) error { } // this is needed to let the peerAdd configure the sandbox - n.setSandbox(sbox) - - if !restore { - // Initialize the sandbox with all the peers previously received from networkdb - n.driver.initSandboxPeerDB(n.id) - } + n.sbox = sbox // If we are in swarm mode, we don't need anymore the watchMiss routine. // This will save 1 thread and 1 netlink socket per network @@ -734,7 +763,7 @@ func (n *network) initSandbox(restore bool) error { tv := syscall.NsecToTimeval(soTimeout.Nanoseconds()) err = nlSock.SetReceiveTimeout(&tv) }) - n.setNetlinkSocket(nlSock) + n.nlSocket = nlSock if err == nil { go n.watchMiss(nlSock, key) @@ -836,7 +865,6 @@ func (d *driver) restoreNetworkFromStore(nid string) *network { if n != nil { n.driver = d n.endpoints = endpointTable{} - n.once = &sync.Once{} d.networks[nid] = n } return n @@ -844,11 +872,11 @@ func (d *driver) restoreNetworkFromStore(nid string) *network { func (d *driver) network(nid string) *network { d.Lock() - defer d.Unlock() n, ok := d.networks[nid] if !ok { n = d.restoreNetworkFromStore(nid) } + d.Unlock() return n } @@ -869,26 +897,12 @@ func (d *driver) getNetworkFromStore(nid string) *network { func (n *network) sandbox() osl.Sandbox { n.Lock() defer n.Unlock() - return n.sbox } -func (n *network) setSandbox(sbox osl.Sandbox) { - n.Lock() - n.sbox = sbox - n.Unlock() -} - -func (n *network) setNetlinkSocket(nlSk *nl.NetlinkSocket) { - n.Lock() - n.nlSocket = nlSk - n.Unlock() -} - func (n *network) vxlanID(s *subnet) uint32 { n.Lock() defer n.Unlock() - return s.vni } @@ -997,7 +1011,6 @@ func (n *network) SetValue(value []byte) error { subnetIP: subnetIP, gwIP: gwIP, vni: vni, - once: &sync.Once{}, } n.subnets = append(n.subnets, s) } else { @@ -1023,7 +1036,10 @@ func (n *network) writeToStore() error { } func (n *network) releaseVxlanID() ([]uint32, error) { - if len(n.subnets) == 0 { + n.Lock() + nSubnets := len(n.subnets) + n.Unlock() + if nSubnets == 0 { return nil, nil } @@ -1039,14 +1055,17 @@ func (n *network) releaseVxlanID() ([]uint32, error) { } } var vnis []uint32 + n.Lock() for _, s := range n.subnets { if n.driver.vxlanIdm != nil { - vni := n.vxlanID(s) - vnis = append(vnis, vni) - n.driver.vxlanIdm.Release(uint64(vni)) + vnis = append(vnis, s.vni) } + s.vni = 0 + } + n.Unlock() - n.setVxlanID(s, 0) + for _, vni := range vnis { + n.driver.vxlanIdm.Release(uint64(vni)) } return vnis, nil @@ -1054,7 +1073,7 @@ func (n *network) releaseVxlanID() ([]uint32, error) { func (n *network) obtainVxlanID(s *subnet) error { //return if the subnet already has a vxlan id assigned - if s.vni != 0 { + if n.vxlanID(s) != 0 { return nil } @@ -1067,7 +1086,7 @@ func (n *network) obtainVxlanID(s *subnet) error { return fmt.Errorf("getting network %q from datastore failed %v", n.id, err) } - if s.vni == 0 { + if n.vxlanID(s) == 0 { vxlanID, err := n.driver.vxlanIdm.GetID(true) if err != nil { return fmt.Errorf("failed to allocate vxlan id: %v", err) diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go b/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go index f31a8ca597b66..1bbd761c2f996 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go @@ -105,17 +105,6 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { logrus.Warnf("Failure during overlay endpoints restore: %v", err) } - // If an error happened when the network join the sandbox during the endpoints restore - // we should reset it now along with the once variable, so that subsequent endpoint joins - // outside of the restore path can potentially fix the network join and succeed. - for nid, n := range d.networks { - if n.initErr != nil { - logrus.Infof("resetting init error and once variable for network %s after unsuccessful endpoint restore: %v", nid, n.initErr) - n.initErr = nil - n.once = &sync.Once{} - } - } - return dc.RegisterDriver(networkType, d, c) } @@ -151,14 +140,10 @@ func (d *driver) restoreEndpoints() error { return fmt.Errorf("could not find subnet for endpoint %s", ep.id) } - if err := n.joinSandbox(true); err != nil { + if err := n.joinSandbox(s, true, true); err != nil { return fmt.Errorf("restore network sandbox failed: %v", err) } - if err := n.joinSubnetSandbox(s, true); err != nil { - return fmt.Errorf("restore subnet sandbox failed for %q: %v", s.subnetIP.String(), err) - } - Ifaces := make(map[string][]osl.IfaceOption) vethIfaceOption := make([]osl.IfaceOption, 1) vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName)) @@ -166,10 +151,10 @@ func (d *driver) restoreEndpoints() error { err := n.sbox.Restore(Ifaces, nil, nil, nil) if err != nil { + n.leaveSandbox() return fmt.Errorf("failed to restore overlay sandbox: %v", err) } - n.incEndpointCount() d.peerAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true) } return nil diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go b/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go index bdd3cb12af9f0..58d70d04d8dd3 100644 --- a/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go +++ b/vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go @@ -7,7 +7,8 @@ import ( "sync" "syscall" - "github.com/docker/libnetwork/common" + "github.com/docker/libnetwork/internal/caller" + "github.com/docker/libnetwork/internal/setmatrix" "github.com/docker/libnetwork/osl" "github.com/sirupsen/logrus" ) @@ -59,7 +60,7 @@ func (p *peerEntryDB) UnMarshalDB() peerEntry { type peerMap struct { // set of peerEntry, note they have to be objects and not pointers to maintain the proper equality checks - mp common.SetMatrix + mp setmatrix.SetMatrix sync.Mutex } @@ -170,7 +171,7 @@ func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask pMap, ok := d.peerDb.mp[nid] if !ok { d.peerDb.mp[nid] = &peerMap{ - mp: common.NewSetMatrix(), + mp: setmatrix.NewSetMatrix(), } pMap = d.peerDb.mp[nid] @@ -297,7 +298,7 @@ func (d *driver) peerOpRoutine(ctx context.Context, ch chan *peerOperation) { } func (d *driver) peerInit(nid string) { - callerName := common.CallerName(1) + callerName := caller.Name(1) d.peerOpCh <- &peerOperation{ opType: peerOperationINIT, networkID: nid, @@ -331,7 +332,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, l2Miss: l2Miss, l3Miss: l3Miss, localPeer: localPeer, - callerName: common.CallerName(1), + callerName: caller.Name(1), } } @@ -384,7 +385,7 @@ func (d *driver) peerAddOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err) } - if err := n.joinSubnetSandbox(s, false); err != nil { + if err := n.joinSandbox(s, false, false); err != nil { return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err) } @@ -422,7 +423,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas peerIPMask: peerIPMask, peerMac: peerMac, vtepIP: vtep, - callerName: common.CallerName(1), + callerName: caller.Name(1), localPeer: localPeer, } } @@ -491,7 +492,7 @@ func (d *driver) peerFlush(nid string) { d.peerOpCh <- &peerOperation{ opType: peerOperationFLUSH, networkID: nid, - callerName: common.CallerName(1), + callerName: caller.Name(1), } } diff --git a/vendor/github.com/docker/libnetwork/drivers/remote/api/api.go b/vendor/github.com/docker/libnetwork/drivers/remote/api/api.go index d24f19016226f..fb35da59288bc 100644 --- a/vendor/github.com/docker/libnetwork/drivers/remote/api/api.go +++ b/vendor/github.com/docker/libnetwork/drivers/remote/api/api.go @@ -150,7 +150,7 @@ type JoinRequest struct { Options map[string]interface{} } -// InterfaceName is the struct represetation of a pair of devices with source +// InterfaceName is the struct representation of a pair of devices with source // and destination, for the purposes of putting an endpoint into a container. type InterfaceName struct { SrcName string diff --git a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go index b3fe9bafcfa46..cc336fa5a82be 100644 --- a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go +++ b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go @@ -54,7 +54,7 @@ type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capabili // DriverNotifyFunc defines the notify function signature when a new network driver gets registered. type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error -// New retruns a new driver registry handle. +// New returns a new driver registry handle. func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg plugingetter.PluginGetter) (*DrvRegistry, error) { r := &DrvRegistry{ drivers: make(driverTable), diff --git a/vendor/github.com/docker/libnetwork/common/caller.go b/vendor/github.com/docker/libnetwork/internal/caller/caller.go similarity index 66% rename from vendor/github.com/docker/libnetwork/common/caller.go rename to vendor/github.com/docker/libnetwork/internal/caller/caller.go index 0dec3bc0bc977..1634ffc6b3fb5 100644 --- a/vendor/github.com/docker/libnetwork/common/caller.go +++ b/vendor/github.com/docker/libnetwork/internal/caller/caller.go @@ -1,4 +1,4 @@ -package common +package caller import ( "runtime" @@ -11,7 +11,7 @@ func callerInfo(i int) string { if ok { f := runtime.FuncForPC(ptr) if f != nil { - // f.Name() is like: github.com/docker/libnetwork/common.MethodName + // f.Name() is like: github.com/docker/libnetwork/caller.MethodName tmp := strings.Split(f.Name(), ".") if len(tmp) > 0 { fName = tmp[len(tmp)-1] @@ -22,8 +22,8 @@ func callerInfo(i int) string { return fName } -// CallerName returns the name of the function at the specified level +// Name returns the name of the function at the specified level // level == 0 means current method name -func CallerName(level int) string { +func Name(level int) string { return callerInfo(2 + level) } diff --git a/vendor/github.com/docker/libnetwork/common/setmatrix.go b/vendor/github.com/docker/libnetwork/internal/setmatrix/setmatrix.go similarity index 99% rename from vendor/github.com/docker/libnetwork/common/setmatrix.go rename to vendor/github.com/docker/libnetwork/internal/setmatrix/setmatrix.go index 72be5bbbfc83c..4a57d841cf73e 100644 --- a/vendor/github.com/docker/libnetwork/common/setmatrix.go +++ b/vendor/github.com/docker/libnetwork/internal/setmatrix/setmatrix.go @@ -1,4 +1,4 @@ -package common +package setmatrix import ( "sync" diff --git a/vendor/github.com/docker/libnetwork/iptables/firewalld.go b/vendor/github.com/docker/libnetwork/iptables/firewalld.go index c9838d5b65eb7..8f13c8644852b 100644 --- a/vendor/github.com/docker/libnetwork/iptables/firewalld.go +++ b/vendor/github.com/docker/libnetwork/iptables/firewalld.go @@ -66,7 +66,7 @@ func newConnection() (*Conn, error) { return c, nil } -// Innitialize D-Bus connection. +// Initialize D-Bus connection. func (c *Conn) initConnection() error { var err error diff --git a/vendor/github.com/docker/libnetwork/iptables/iptables.go b/vendor/github.com/docker/libnetwork/iptables/iptables.go index 50896d935a44e..4b8d8832e9035 100644 --- a/vendor/github.com/docker/libnetwork/iptables/iptables.go +++ b/vendor/github.com/docker/libnetwork/iptables/iptables.go @@ -477,7 +477,7 @@ func raw(args ...string) ([]byte, error) { return filterOutput(startTime, output, args...), err } -// RawCombinedOutput inernally calls the Raw function and returns a non nil +// RawCombinedOutput internally calls the Raw function and returns a non nil // error if Raw returned a non nil error or a non empty output func RawCombinedOutput(args ...string) error { if output, err := Raw(args...); err != nil || len(output) != 0 { diff --git a/vendor/github.com/docker/libnetwork/ipvs/netlink.go b/vendor/github.com/docker/libnetwork/ipvs/netlink.go index c062a1789d1fe..f88057f7b7471 100644 --- a/vendor/github.com/docker/libnetwork/ipvs/netlink.go +++ b/vendor/github.com/docker/libnetwork/ipvs/netlink.go @@ -100,7 +100,7 @@ func fillService(s *Service) nl.NetlinkRequestData { return cmdAttr } -func fillDestinaton(d *Destination) nl.NetlinkRequestData { +func fillDestination(d *Destination) nl.NetlinkRequestData { cmdAttr := nl.NewRtAttr(ipvsCmdAttrDest, nil) nl.NewRtAttrChild(cmdAttr, ipvsDestAttrAddress, rawIPData(d.Address)) @@ -134,7 +134,7 @@ func (i *Handle) doCmdwithResponse(s *Service, d *Destination, cmd uint8) ([][]b } } else { - req.AddData(fillDestinaton(d)) + req.AddData(fillDestination(d)) } res, err := execute(i.sock, req, 0) diff --git a/vendor/github.com/docker/libnetwork/network.go b/vendor/github.com/docker/libnetwork/network.go index 5ca660c3b55cb..052aa8febe8f7 100644 --- a/vendor/github.com/docker/libnetwork/network.go +++ b/vendor/github.com/docker/libnetwork/network.go @@ -9,11 +9,11 @@ import ( "time" "github.com/docker/docker/pkg/stringid" - "github.com/docker/libnetwork/common" "github.com/docker/libnetwork/config" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/etchosts" + "github.com/docker/libnetwork/internal/setmatrix" "github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/netutils" @@ -88,7 +88,7 @@ type NetworkInfo interface { type EndpointWalker func(ep Endpoint) bool // ipInfo is the reverse mapping from IP to service name to serve the PTR query. -// extResolver is set if an externl server resolves a service name to this IP. +// extResolver is set if an external server resolves a service name to this IP. // Its an indication to defer PTR queries also to that external server. type ipInfo struct { name string @@ -104,9 +104,9 @@ type svcMapEntry struct { } type svcInfo struct { - svcMap common.SetMatrix - svcIPv6Map common.SetMatrix - ipMap common.SetMatrix + svcMap setmatrix.SetMatrix + svcIPv6Map setmatrix.SetMatrix + ipMap setmatrix.SetMatrix service map[string][]servicePorts } @@ -1353,7 +1353,7 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool } } -func addIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) { +func addIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) { reverseIP := netutils.ReverseIP(ip.String()) ipMap.Insert(reverseIP, ipInfo{ name: name, @@ -1361,7 +1361,7 @@ func addIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) { }) } -func delIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) { +func delIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) { reverseIP := netutils.ReverseIP(ip.String()) ipMap.Remove(reverseIP, ipInfo{ name: name, @@ -1369,14 +1369,14 @@ func delIPToName(ipMap common.SetMatrix, name, serviceID string, ip net.IP) { }) } -func addNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) { +func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) { svcMap.Insert(name, svcMapEntry{ ip: epIP.String(), serviceID: serviceID, }) } -func delNameToIP(svcMap common.SetMatrix, name, serviceID string, epIP net.IP) { +func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) { svcMap.Remove(name, svcMapEntry{ ip: epIP.String(), serviceID: serviceID, @@ -1399,9 +1399,9 @@ func (n *network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP sr, ok := c.svcRecords[n.ID()] if !ok { sr = svcInfo{ - svcMap: common.NewSetMatrix(), - svcIPv6Map: common.NewSetMatrix(), - ipMap: common.NewSetMatrix(), + svcMap: setmatrix.NewSetMatrix(), + svcIPv6Map: setmatrix.NewSetMatrix(), + ipMap: setmatrix.NewSetMatrix(), } c.svcRecords[n.ID()] = sr } @@ -1654,7 +1654,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error { return types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name()) } if !d.Pool.Contains(ip) { - return types.ForbiddenErrorf("auxilairy address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool) + return types.ForbiddenErrorf("auxiliary address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool) } // Attempt reservation in the container addressable pool, silent the error if address does not belong to that pool 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) { logrus.Debugf("Service name To resolve: %v", name) - // There are DNS implementaions that allow SRV queries for names not in + // There are DNS implementations that allow SRV queries for names not in // the format defined by RFC 2782. Hence specific validations checks are // not done parts := strings.Split(name, ".") @@ -2126,7 +2126,7 @@ func (n *network) lbEndpointName() string { func (n *network) createLoadBalancerSandbox() (retErr error) { sandboxName := n.lbSandboxName() // Mark the sandbox to be a load balancer - sbOptions := []SandboxOption{OptionLoadBalancer()} + sbOptions := []SandboxOption{OptionLoadBalancer(n.id)} if n.ingress { sbOptions = append(sbOptions, OptionIngress()) } diff --git a/vendor/github.com/docker/libnetwork/networkdb/cluster.go b/vendor/github.com/docker/libnetwork/networkdb/cluster.go index 0a64787df9d0f..c9895708483b3 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/cluster.go +++ b/vendor/github.com/docker/libnetwork/networkdb/cluster.go @@ -243,7 +243,7 @@ func (nDB *NetworkDB) clusterLeave() error { } func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, f func()) { - // Use a random stagger to avoid syncronizing + // Use a random stagger to avoid synchronizing randStagger := time.Duration(uint64(rnd.Int63()) % uint64(stagger)) select { case <-time.After(randStagger): diff --git a/vendor/github.com/docker/libnetwork/networkdb/networkdb.go b/vendor/github.com/docker/libnetwork/networkdb/networkdb.go index b79f346eeacb7..d8c3107baacb4 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/networkdb.go +++ b/vendor/github.com/docker/libnetwork/networkdb/networkdb.go @@ -58,7 +58,7 @@ type NetworkDB struct { // List of all peer nodes which have left leftNodes map[string]*node - // A multi-dimensional map of network/node attachmemts. The + // A multi-dimensional map of network/node attachments. The // first key is a node name and the second key is a network ID // for the network that node is participating in. networks map[string]map[string]*network @@ -153,7 +153,7 @@ type network struct { entriesNumber int } -// Config represents the configuration of the networdb instance and +// Config represents the configuration of the networkdb instance and // can be passed by the caller. type Config struct { // NodeID is the node unique identifier of the node when is part of the cluster diff --git a/vendor/github.com/docker/libnetwork/networkdb/networkdb.pb.go b/vendor/github.com/docker/libnetwork/networkdb/networkdb.pb.go index 043c23b605a9c..971e868aa4a47 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/networkdb.pb.go +++ b/vendor/github.com/docker/libnetwork/networkdb/networkdb.pb.go @@ -48,7 +48,7 @@ type MessageType int32 const ( MessageTypeInvalid MessageType = 0 - // NetworEvent message type is used to communicate network + // NetworkEvent message type is used to communicate network // attachments on the node. MessageTypeNetworkEvent MessageType = 1 // TableEvent message type is used to communicate any table @@ -66,7 +66,7 @@ const ( // which is a pack of many message of above types, packed into // a single compound message. MessageTypeCompound MessageType = 5 - // NodeEvent message type is used to communicare node + // NodeEvent message type is used to communicate node // join/leave events in the cluster MessageTypeNodeEvent MessageType = 6 ) diff --git a/vendor/github.com/docker/libnetwork/networkdb/networkdb.proto b/vendor/github.com/docker/libnetwork/networkdb/networkdb.proto index 0b8490be7a629..4e1272eb89d8d 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/networkdb.proto +++ b/vendor/github.com/docker/libnetwork/networkdb/networkdb.proto @@ -19,7 +19,7 @@ enum MessageType { INVALID = 0 [(gogoproto.enumvalue_customname) = "MessageTypeInvalid"]; - // NetworEvent message type is used to communicate network + // NetworkEvent message type is used to communicate network // attachments on the node. NETWORK_EVENT = 1 [(gogoproto.enumvalue_customname) = "MessageTypeNetworkEvent"]; @@ -42,7 +42,7 @@ enum MessageType { // a single compound message. COMPOUND = 5 [(gogoproto.enumvalue_customname) = "MessageTypeCompound"]; - // NodeEvent message type is used to communicare node + // NodeEvent message type is used to communicate node // join/leave events in the cluster NODE_EVENT = 6 [(gogoproto.enumvalue_customname) = "MessageTypeNodeEvent"]; } diff --git a/vendor/github.com/docker/libnetwork/networkdb/networkdbdiagnostic.go b/vendor/github.com/docker/libnetwork/networkdb/networkdbdiagnostic.go index a0e95987992e5..ea90c5a0e8df9 100644 --- a/vendor/github.com/docker/libnetwork/networkdb/networkdbdiagnostic.go +++ b/vendor/github.com/docker/libnetwork/networkdb/networkdbdiagnostic.go @@ -6,8 +6,8 @@ import ( "net/http" "strings" - "github.com/docker/libnetwork/common" "github.com/docker/libnetwork/diagnostic" + "github.com/docker/libnetwork/internal/caller" "github.com/sirupsen/logrus" ) @@ -37,7 +37,7 @@ func dbJoin(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("join cluster") if len(r.Form["members"]) < 1 { @@ -70,7 +70,7 @@ func dbPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("network peers") if len(r.Form["nid"]) < 1 { @@ -104,7 +104,7 @@ func dbClusterPeers(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("cluster peers") nDB, ok := ctx.(*NetworkDB) @@ -127,7 +127,7 @@ func dbCreateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { unsafe, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("create entry") if len(r.Form["tname"]) < 1 || @@ -176,7 +176,7 @@ func dbUpdateEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { unsafe, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("update entry") if len(r.Form["tname"]) < 1 || @@ -224,7 +224,7 @@ func dbDeleteEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("delete entry") if len(r.Form["tname"]) < 1 || @@ -261,7 +261,7 @@ func dbGetEntry(ctx interface{}, w http.ResponseWriter, r *http.Request) { unsafe, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("get entry") if len(r.Form["tname"]) < 1 || @@ -307,7 +307,7 @@ func dbJoinNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("join network") if len(r.Form["nid"]) < 1 { @@ -339,7 +339,7 @@ func dbLeaveNetwork(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("leave network") if len(r.Form["nid"]) < 1 { @@ -371,7 +371,7 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) { unsafe, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("get table") if len(r.Form["tname"]) < 1 || @@ -419,7 +419,7 @@ func dbNetworkStats(ctx interface{}, w http.ResponseWriter, r *http.Request) { _, json := diagnostic.ParseHTTPFormOptions(r) // audit logs - log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": common.CallerName(0), "url": r.URL.String()}) + log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()}) log.Info("network stats") if len(r.Form["nid"]) < 1 { diff --git a/vendor/github.com/docker/libnetwork/osl/interface_linux.go b/vendor/github.com/docker/libnetwork/osl/interface_linux.go index 0ecda09f6e622..a924af4bdf19b 100644 --- a/vendor/github.com/docker/libnetwork/osl/interface_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/interface_linux.go @@ -289,6 +289,16 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If // Configure the interface now this is moved in the proper namespace. if err := configureInterface(nlh, iface, i); err != nil { + // If configuring the device fails move it back to the host namespace + // and change the name back to the source name. This allows the caller + // to properly cleanup the interface. Its important especially for + // interfaces with global attributes, ex: vni id for vxlan interfaces. + if nerr := nlh.LinkSetName(iface, i.SrcName()); nerr != nil { + logrus.Errorf("renaming interface (%s->%s) failed, %v after config error %v", i.DstName(), i.SrcName(), nerr, err) + } + if nerr := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); nerr != nil { + logrus.Errorf("moving inteface %s to host ns failed, %v, after config error %v", i.SrcName(), nerr, err) + } return err } diff --git a/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go b/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go index 5088f0e7f950a..a7cd7dbb7261c 100644 --- a/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go +++ b/vendor/github.com/docker/libnetwork/osl/kernel/knobs.go @@ -2,7 +2,7 @@ package kernel type conditionalCheck func(val1, val2 string) bool -// OSValue represents a tuple, value defired, check function when to apply the value +// OSValue represents a tuple, value defined, check function when to apply the value type OSValue struct { Value string CheckFn conditionalCheck diff --git a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go index 4ae11b8e7b870..45c46852fc57d 100644 --- a/vendor/github.com/docker/libnetwork/osl/namespace_linux.go +++ b/vendor/github.com/docker/libnetwork/osl/namespace_linux.go @@ -394,10 +394,13 @@ func (n *networkNamespace) InvokeFunc(f func()) error { // InitOSContext initializes OS context while configuring network resources func InitOSContext() func() { runtime.LockOSThread() + if err := ns.SetNamespace(); err != nil { + logrus.Error(err) + } return runtime.UnlockOSThread } -func nsInvoke(path string, prefunc, postfunc func(int) error) error { +func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error { defer InitOSContext()() newNs, err := netns.GetFromPath(path) @@ -412,14 +415,10 @@ func nsInvoke(path string, prefunc, postfunc func(int) error) error { return fmt.Errorf("failed in prefunc: %v", err) } - // save the current namespace (host namespace) - curNs, _ := netns.Get() if err = netns.Set(newNs); err != nil { return err } - defer curNs.Close() - // will restore the previous namespace before unlocking the thread - defer netns.Set(curNs) + defer ns.SetNamespace() // Invoked after the namespace switch. return postfunc(ns.ParseHandlerInt()) @@ -652,10 +651,7 @@ func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) { for _, t := range types { switch t { case SandboxTypeLoadBalancer: - nsInvoke(n.nsPath(), - func(nsFD int) error { return nil }, - func(callerFD int) error { kernel.ApplyOSTweaks(loadBalancerConfig); return nil }, - ) + kernel.ApplyOSTweaks(loadBalancerConfig) } } } diff --git a/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go b/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go index 5cb251b131035..23caf7f120832 100644 --- a/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go +++ b/vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go @@ -14,6 +14,11 @@ import ( "github.com/sirupsen/logrus" ) +const ( + // DefaultResolvConf points to the default file used for dns configuration on a linux machine + DefaultResolvConf = "/etc/resolv.conf" +) + var ( // Note: the default IPv4 & IPv6 resolvers are set to Google's Public DNS defaultIPv4Dns = []string{"nameserver 8.8.8.8", "nameserver 8.8.4.4"} @@ -50,15 +55,7 @@ type File struct { // Get returns the contents of /etc/resolv.conf and its hash func Get() (*File, error) { - resolv, err := ioutil.ReadFile("/etc/resolv.conf") - if err != nil { - return nil, err - } - hash, err := ioutils.HashData(bytes.NewReader(resolv)) - if err != nil { - return nil, err - } - return &File{Content: resolv, Hash: hash}, nil + return GetSpecific(DefaultResolvConf) } // GetSpecific returns the contents of the user specified resolv.conf file and its hash diff --git a/vendor/github.com/docker/libnetwork/resolver.go b/vendor/github.com/docker/libnetwork/resolver.go index 2efd026d00ca0..04afe7a1d73d5 100644 --- a/vendor/github.com/docker/libnetwork/resolver.go +++ b/vendor/github.com/docker/libnetwork/resolver.go @@ -35,7 +35,7 @@ type Resolver interface { } // DNSBackend represents a backend DNS resolver used for DNS name -// resolution. All the queries to the resolver are forwared to the +// resolution. All the queries to the resolver are forwarded to the // backend resolver. type DNSBackend interface { // ResolveName resolves a service name to an IPv4 or IPv6 address by searching diff --git a/vendor/github.com/docker/libnetwork/sandbox.go b/vendor/github.com/docker/libnetwork/sandbox.go index 0f9a53a36715e..d98f359a7d718 100644 --- a/vendor/github.com/docker/libnetwork/sandbox.go +++ b/vendor/github.com/docker/libnetwork/sandbox.go @@ -84,6 +84,7 @@ type sandbox struct { ingress bool ndotsSet bool oslTypes []osl.SandboxType // slice of properties of this sandbox + loadBalancerNID string // NID that this SB is a load balancer for sync.Mutex // This mutex is used to serialize service related operation for an endpoint // 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) { logrus.Debugf("Service name To resolve: %v", name) - // There are DNS implementaions that allow SRV queries for names not in + // There are DNS implementations that allow SRV queries for names not in // the format defined by RFC 2782. Hence specific validations checks are // not done parts := strings.Split(name, ".") @@ -1098,8 +1099,8 @@ func OptionDNSOptions(options string) SandboxOption { } } -// OptionUseDefaultSandbox function returns an option setter for using default sandbox to -// be passed to container Create method. +// OptionUseDefaultSandbox function returns an option setter for using default sandbox +// (host namespace) to be passed to container Create method. func OptionUseDefaultSandbox() SandboxOption { return func(sb *sandbox) { sb.config.useDefaultSandBox = true @@ -1169,8 +1170,9 @@ func OptionIngress() SandboxOption { // OptionLoadBalancer function returns an option setter for marking a // sandbox as a load balancer sandbox. -func OptionLoadBalancer() SandboxOption { +func OptionLoadBalancer(nid string) SandboxOption { return func(sb *sandbox) { + sb.loadBalancerNID = nid sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeLoadBalancer) } } diff --git a/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go b/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go index 3641f60f7c092..db1b66b190dc8 100644 --- a/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go +++ b/vendor/github.com/docker/libnetwork/sandbox_dns_unix.go @@ -81,7 +81,9 @@ func (sb *sandbox) buildHostsFile() error { } // This is for the host mode networking - if sb.config.originHostsPath != "" { + if sb.config.useDefaultSandBox && len(sb.config.extraHosts) == 0 { + // We are working under the assumption that the origin file option had been properly expressed by the upper layer + // if not here we are going to error out if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) { return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err) } @@ -190,8 +192,13 @@ func (sb *sandbox) setupDNS() error { return err } - // This is for the host mode networking - if sb.config.originResolvConfPath != "" { + // When the user specify a conainter in the host namespace and do no have any dns option specified + // we just copy the host resolv.conf from the host itself + if sb.config.useDefaultSandBox && + len(sb.config.dnsList) == 0 && len(sb.config.dnsSearchList) == 0 && len(sb.config.dnsOptionsList) == 0 { + + // We are working under the assumption that the origin file option had been properly expressed by the upper layer + // if not here we are going to error out if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil { if !os.IsNotExist(err) { 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 { return nil } - currRC, err := resolvconf.Get() + originResolvConfPath := sb.config.originResolvConfPath + if originResolvConfPath == "" { + // if not specified fallback to default /etc/resolv.conf + originResolvConfPath = resolvconf.DefaultResolvConf + } + currRC, err := resolvconf.GetSpecific(originResolvConfPath) if err != nil { if !os.IsNotExist(err) { return err @@ -241,7 +253,7 @@ func (sb *sandbox) setupDNS() error { sb.setExternalResolvers(newRC.Content, types.IPv4, false) } else { // If the host resolv.conf file has 127.0.0.x container should - // use the host restolver for queries. This is supported by the + // use the host resolver for queries. This is supported by the // docker embedded DNS server. Hence save the external resolvers // before filtering it out. sb.setExternalResolvers(currRC.Content, types.IPv4, true) @@ -271,7 +283,7 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error { ) // This is for the host mode networking - if sb.config.originResolvConfPath != "" { + if sb.config.useDefaultSandBox { return nil } diff --git a/vendor/github.com/docker/libnetwork/service.go b/vendor/github.com/docker/libnetwork/service.go index 02bcdb1884eeb..5ed11959a10f9 100644 --- a/vendor/github.com/docker/libnetwork/service.go +++ b/vendor/github.com/docker/libnetwork/service.go @@ -5,7 +5,7 @@ import ( "net" "sync" - "github.com/docker/libnetwork/common" + "github.com/docker/libnetwork/internal/setmatrix" ) var ( @@ -54,7 +54,7 @@ type service struct { // associated with it. At stable state the endpoint ID expected is 1 // but during transition and service change it is possible to have // temporary more than 1 - ipToEndpoint common.SetMatrix + ipToEndpoint setmatrix.SetMatrix deleted bool diff --git a/vendor/github.com/docker/libnetwork/service_common.go b/vendor/github.com/docker/libnetwork/service_common.go index 4c30e465e2baf..78986c5424f4f 100644 --- a/vendor/github.com/docker/libnetwork/service_common.go +++ b/vendor/github.com/docker/libnetwork/service_common.go @@ -5,7 +5,7 @@ package libnetwork import ( "net" - "github.com/docker/libnetwork/common" + "github.com/docker/libnetwork/internal/setmatrix" "github.com/sirupsen/logrus" ) @@ -139,7 +139,7 @@ func newService(name string, id string, ingressPorts []*PortConfig, serviceAlias ingressPorts: ingressPorts, loadBalancers: make(map[string]*loadBalancer), aliases: serviceAliases, - ipToEndpoint: common.NewSetMatrix(), + ipToEndpoint: setmatrix.NewSetMatrix(), } } diff --git a/vendor/github.com/docker/libnetwork/service_linux.go b/vendor/github.com/docker/libnetwork/service_linux.go index 3ffa60719cafd..a97d24b59ed2a 100644 --- a/vendor/github.com/docker/libnetwork/service_linux.go +++ b/vendor/github.com/docker/libnetwork/service_linux.go @@ -27,7 +27,7 @@ import ( func init() { reexec.Register("fwmarker", fwMarker) - reexec.Register("redirecter", redirecter) + reexec.Register("redirector", redirector) } // Populate all loadbalancers on the network that the passed endpoint @@ -431,7 +431,7 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro // DOCKER-USER so the user is able to filter packet first. // The second rule should be jump to INGRESS-CHAIN. // This chain has the rules to allow access to the published ports for swarm tasks -// from local bridge networks and docker_gwbridge (ie:taks on other swarm netwroks) +// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) func arrangeIngressFilterRule() { if iptables.ExistChain(ingressChain, iptables.Filter) { if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) { @@ -668,7 +668,7 @@ func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) e cmd := &exec.Cmd{ Path: reexec.Self(), - Args: append([]string{"redirecter"}, path, eIP.String(), ingressPortsFile), + Args: append([]string{"redirector"}, path, eIP.String(), ingressPortsFile), Stdout: os.Stdout, Stderr: os.Stderr, } @@ -680,8 +680,8 @@ func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) e return nil } -// Redirecter reexec function. -func redirecter() { +// Redirector reexec function. +func redirector() { runtime.LockOSThread() defer runtime.UnlockOSThread()