From 196b27211b77562cd6d5d620d4dd5bfe473383ed Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Wed, 17 Feb 2016 17:07:33 -0800 Subject: [PATCH] Vendoring libnetwork v0.7.0-dev.3 Signed-off-by: Alessandro Boch --- hack/vendor.sh | 2 +- .../github.com/docker/libnetwork/CHANGELOG.md | 8 + .../docker/libnetwork/Dockerfile.build | 1 - .../src/github.com/docker/libnetwork/Makefile | 2 +- .../docker/libnetwork/config/config.go | 16 + .../docker/libnetwork/controller.go | 120 +++++- .../docker/libnetwork/datastore/datastore.go | 29 ++ .../libnetwork/discoverapi/discoverapi.go | 9 +- .../github.com/docker/libnetwork/drivers.go | 14 +- .../libnetwork/drivers/bridge/bridge.go | 5 + .../libnetwork/drivers/bridge/bridge_store.go | 28 +- .../libnetwork/drivers/overlay/overlay.go | 84 ++-- .../libnetwork/drivers/windows/labels.go | 12 + .../libnetwork/drivers/windows/windows.go | 390 +++++++++++++++++- .../docker/libnetwork/drivers_windows.go | 11 +- .../docker/libnetwork/ipam/allocator.go | 75 +++- .../docker/libnetwork/ipamapi/contract.go | 3 + .../builtin/{builtin.go => builtin_unix.go} | 2 + .../ipams/builtin/builtin_windows.go | 16 + .../docker/libnetwork/ipams/remote/remote.go | 11 + .../ipams/windowsipam/windowsipam.go | 93 +++++ .../docker/libnetwork/netlabel/labels.go | 11 + .../github.com/docker/libnetwork/network.go | 2 +- .../docker/libnetwork/portmapper/proxy.go | 2 +- .../github.com/docker/libnetwork/resolver.go | 11 +- .../github.com/docker/libnetwork/sandbox.go | 312 -------------- .../docker/libnetwork/sandbox_dns_unix.go | 323 +++++++++++++++ .../docker/libnetwork/sandbox_dns_windows.go | 32 ++ .../libnetwork/sandbox_externalkey_unix.go | 2 +- .../src/github.com/docker/libnetwork/store.go | 4 + 30 files changed, 1204 insertions(+), 426 deletions(-) create mode 100644 vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go rename vendor/src/github.com/docker/libnetwork/ipams/builtin/{builtin.go => builtin_unix.go} (96%) create mode 100644 vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go create mode 100644 vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go create mode 100644 vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go create mode 100644 vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go diff --git a/hack/vendor.sh b/hack/vendor.sh index 2cc90db0be..19a1e2c79c 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -29,7 +29,7 @@ clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de clone git github.com/imdario/mergo 0.2.1 #get libnetwork packages -clone git github.com/docker/libnetwork v0.7.0-dev.2 +clone git github.com/docker/libnetwork v0.7.0-dev.3 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4 diff --git a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md index 177eee6c79..35fe418a43 100644 --- a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md +++ b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.7.0-dev.3 (2016-02-17) +- Fixes https://github.com/docker/docker/issues/20350 +- Fixes https://github.com/docker/docker/issues/20145 +- Initial Windows HNS integration +- Allow passing global datastore config to libnetwork after boot +- Set Recursion Available bit in DNS query responses +- Make sure iptables chains are recreated on firewalld reload + ## 0.7.0-dev.2 (2016-02-11) - Fixes https://github.com/docker/docker/issues/20140 diff --git a/vendor/src/github.com/docker/libnetwork/Dockerfile.build b/vendor/src/github.com/docker/libnetwork/Dockerfile.build index 2b767c2a57..8dcfd83255 100644 --- a/vendor/src/github.com/docker/libnetwork/Dockerfile.build +++ b/vendor/src/github.com/docker/libnetwork/Dockerfile.build @@ -8,6 +8,5 @@ RUN cd /go/src && mkdir -p golang.org/x && \ RUN go get github.com/tools/godep \ github.com/golang/lint/golint \ golang.org/x/tools/cmd/vet \ - golang.org/x/tools/cmd/goimports \ golang.org/x/tools/cmd/cover\ github.com/mattn/goveralls diff --git a/vendor/src/github.com/docker/libnetwork/Makefile b/vendor/src/github.com/docker/libnetwork/Makefile index 2031826c7d..096d7fcc21 100644 --- a/vendor/src/github.com/docker/libnetwork/Makefile +++ b/vendor/src/github.com/docker/libnetwork/Makefile @@ -53,7 +53,7 @@ check-code: check-format: @echo "Checking format... " - test -z "$$(goimports -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" + test -z "$$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" @echo "Done checking format" run-tests: diff --git a/vendor/src/github.com/docker/libnetwork/config/config.go b/vendor/src/github.com/docker/libnetwork/config/config.go index 320eb39e00..8da92f7a0e 100644 --- a/vendor/src/github.com/docker/libnetwork/config/config.go +++ b/vendor/src/github.com/docker/libnetwork/config/config.go @@ -61,6 +61,22 @@ func ParseConfig(tomlCfgFile string) (*Config, error) { return cfg, nil } +// ParseConfigOptions parses the configuration options and returns +// a reference to the corresponding Config structure +func ParseConfigOptions(cfgOptions ...Option) *Config { + cfg := &Config{ + Daemon: DaemonCfg{ + DriverCfg: make(map[string]interface{}), + }, + Scopes: make(map[string]*datastore.ScopeCfg), + } + + cfg.ProcessOptions(cfgOptions...) + cfg.LoadDefaultScopes(cfg.Daemon.DataDir) + + return cfg +} + // Option is an option setter function type used to pass various configurations // to the controller type Option func(c *Config) diff --git a/vendor/src/github.com/docker/libnetwork/controller.go b/vendor/src/github.com/docker/libnetwork/controller.go index 274eab2861..3a5e188cec 100644 --- a/vendor/src/github.com/docker/libnetwork/controller.go +++ b/vendor/src/github.com/docker/libnetwork/controller.go @@ -106,6 +106,9 @@ type NetworkController interface { // Stop network controller Stop() + + // ReloadCondfiguration updates the controller configuration + ReloadConfiguration(cfgOptions ...config.Option) error } // NetworkWalker is a client provided function which will be used to walk the Networks. @@ -129,7 +132,6 @@ type ipamData struct { } type driverTable map[string]*driverData - type ipamTable map[string]*ipamData type sandboxTable map[string]*sandbox @@ -153,22 +155,9 @@ type controller struct { // New creates a new instance of network controller. func New(cfgOptions ...config.Option) (NetworkController, error) { - var cfg *config.Config - cfg = &config.Config{ - Daemon: config.DaemonCfg{ - DriverCfg: make(map[string]interface{}), - }, - Scopes: make(map[string]*datastore.ScopeCfg), - } - - if len(cfgOptions) > 0 { - cfg.ProcessOptions(cfgOptions...) - } - cfg.LoadDefaultScopes(cfg.Daemon.DataDir) - c := &controller{ id: stringid.GenerateRandomID(), - cfg: cfg, + cfg: config.ParseConfigOptions(cfgOptions...), sandboxes: sandboxTable{}, drivers: driverTable{}, ipamDrivers: ipamTable{}, @@ -179,8 +168,8 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { return nil, err } - if cfg != nil && cfg.Cluster.Watcher != nil { - if err := c.initDiscovery(cfg.Cluster.Watcher); err != nil { + if c.cfg != nil && c.cfg.Cluster.Watcher != nil { + if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil { // Failing to initalize discovery is a bad situation to be in. // But it cannot fail creating the Controller log.Errorf("Failed to Initialize Discovery : %v", err) @@ -206,6 +195,83 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { return c, nil } +var procReloadConfig = make(chan (bool), 1) + +func (c *controller) ReloadConfiguration(cfgOptions ...config.Option) error { + procReloadConfig <- true + defer func() { <-procReloadConfig }() + + // For now we accept the configuration reload only as a mean to provide a global store config after boot. + // Refuse the configuration if it alters an existing datastore client configuration. + update := false + cfg := config.ParseConfigOptions(cfgOptions...) + for s := range c.cfg.Scopes { + if _, ok := cfg.Scopes[s]; !ok { + return types.ForbiddenErrorf("cannot accept new configuration because it removes an existing datastore client") + } + } + for s, nSCfg := range cfg.Scopes { + if eSCfg, ok := c.cfg.Scopes[s]; ok { + if eSCfg.Client.Provider != nSCfg.Client.Provider || + eSCfg.Client.Address != nSCfg.Client.Address { + return types.ForbiddenErrorf("cannot accept new configuration because it modifies an existing datastore client") + } + } else { + update = true + } + } + if !update { + return nil + } + + c.Lock() + c.cfg = cfg + c.Unlock() + + if err := c.initStores(); err != nil { + return err + } + + if c.discovery == nil && c.cfg.Cluster.Watcher != nil { + if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil { + log.Errorf("Failed to Initialize Discovery after configuration update: %v", err) + } + } + + var dsConfig *discoverapi.DatastoreConfigData + for scope, sCfg := range cfg.Scopes { + if scope == datastore.LocalScope || !sCfg.IsValid() { + continue + } + dsConfig = &discoverapi.DatastoreConfigData{ + Scope: scope, + Provider: sCfg.Client.Provider, + Address: sCfg.Client.Address, + Config: sCfg.Client.Config, + } + break + } + if dsConfig == nil { + return nil + } + + for nm, id := range c.getIpamDrivers() { + err := id.driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig) + if err != nil { + log.Errorf("Failed to set datastore in driver %s: %v", nm, err) + } + } + + for nm, id := range c.getNetDrivers() { + err := id.driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig) + if err != nil { + log.Errorf("Failed to set datastore in driver %s: %v", nm, err) + } + } + + return nil +} + func (c *controller) ID() string { return c.id } @@ -726,6 +792,26 @@ func (c *controller) getIpamDriver(name string) (ipamapi.Ipam, error) { return id.driver, nil } +func (c *controller) getIpamDrivers() ipamTable { + c.Lock() + defer c.Unlock() + table := ipamTable{} + for i, d := range c.ipamDrivers { + table[i] = d + } + return table +} + +func (c *controller) getNetDrivers() driverTable { + c.Lock() + defer c.Unlock() + table := driverTable{} + for i, d := range c.drivers { + table[i] = d + } + return table +} + func (c *controller) Stop() { c.closeStores() c.stopExternalKeyListener() diff --git a/vendor/src/github.com/docker/libnetwork/datastore/datastore.go b/vendor/src/github.com/docker/libnetwork/datastore/datastore.go index 0ba7b6ef2c..687473d275 100644 --- a/vendor/src/github.com/docker/libnetwork/datastore/datastore.go +++ b/vendor/src/github.com/docker/libnetwork/datastore/datastore.go @@ -13,6 +13,7 @@ import ( "github.com/docker/libkv/store/consul" "github.com/docker/libkv/store/etcd" "github.com/docker/libkv/store/zookeeper" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/types" ) @@ -253,6 +254,34 @@ func NewDataStore(scope string, cfg *ScopeCfg) (DataStore, error) { return newClient(scope, cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config, cached) } +// NewDataStoreFromConfig creates a new instance of LibKV data store starting from the datastore config data +func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, error) { + var ( + ok bool + sCfgP *store.Config + ) + + sCfgP, ok = dsc.Config.(*store.Config) + if !ok && dsc.Config != nil { + return nil, fmt.Errorf("cannot parse store configuration: %v", dsc.Config) + } + + scopeCfg := &ScopeCfg{ + Client: ScopeClientCfg{ + Address: dsc.Address, + Provider: dsc.Provider, + Config: sCfgP, + }, + } + + ds, err := NewDataStore(dsc.Scope, scopeCfg) + if err != nil { + return nil, fmt.Errorf("failed to construct datastore client from datastore configuration %v: %v", dsc, err) + } + + return ds, err +} + func (ds *datastore) Close() { ds.store.Close() } diff --git a/vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go b/vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go index 27993ec1bc..03e9e909cf 100644 --- a/vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go +++ b/vendor/src/github.com/docker/libnetwork/discoverapi/discoverapi.go @@ -16,8 +16,8 @@ type DiscoveryType int const ( // NodeDiscovery represents Node join/leave events provided by discovery NodeDiscovery = iota + 1 - // DatastoreUpdate represents a add/remove datastore event - DatastoreUpdate + // DatastoreConfig represents a add/remove datastore event + DatastoreConfig ) // NodeDiscoveryData represents the structure backing the node discovery data json string @@ -26,8 +26,9 @@ type NodeDiscoveryData struct { Self bool } -// DatastoreUpdateData is the data for the datastore update event message -type DatastoreUpdateData struct { +// DatastoreConfigData is the data for the datastore update event message +type DatastoreConfigData struct { + Scope string Provider string Address string Config interface{} diff --git a/vendor/src/github.com/docker/libnetwork/drivers.go b/vendor/src/github.com/docker/libnetwork/drivers.go index 1b11f37324..1a4b348303 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers.go +++ b/vendor/src/github.com/docker/libnetwork/drivers.go @@ -3,11 +3,13 @@ package libnetwork import ( "strings" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/ipamapi" + "github.com/docker/libnetwork/netlabel" + builtinIpam "github.com/docker/libnetwork/ipams/builtin" remoteIpam "github.com/docker/libnetwork/ipams/remote" - "github.com/docker/libnetwork/netlabel" ) type initializer struct { @@ -56,10 +58,12 @@ func makeDriverConfig(c *controller, ntype string) map[string]interface{} { if !v.IsValid() { continue } - - config[netlabel.MakeKVProvider(k)] = v.Client.Provider - config[netlabel.MakeKVProviderURL(k)] = v.Client.Address - config[netlabel.MakeKVProviderConfig(k)] = v.Client.Config + config[netlabel.MakeKVClient(k)] = discoverapi.DatastoreConfigData{ + Scope: k, + Provider: v.Client.Provider, + Address: v.Client.Address, + Config: v.Client.Config, + } } return config diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index b93d984ebd..55acf8ac7f 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -133,6 +133,9 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { if out, err := exec.Command("modprobe", "-va", "nf_nat").CombinedOutput(); err != nil { logrus.Warnf("Running modprobe nf_nat failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) } + if out, err := exec.Command("modprobe", "-va", "xt_conntrack").CombinedOutput(); err != nil { + logrus.Warnf("Running modprobe xt_conntrack failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) + } if err := iptables.FirewalldInit(); err != nil { logrus.Debugf("Fail to initialize firewalld: %v, using raw iptables instead", err) } @@ -384,6 +387,8 @@ func (d *driver) configure(option map[string]interface{}) error { if err != nil { return err } + // Make sure on firewall reload, first thing being re-played is chains creation + iptables.OnReloaded(func() { logrus.Debugf("Recreating iptables chains on firewall reload"); setupIPChains(config) }) } d.Lock() diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go index 96c31d87e8..066469adc9 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge_store.go @@ -6,9 +6,9 @@ import ( "net" "github.com/Sirupsen/logrus" - "github.com/docker/libkv/store" "github.com/docker/libkv/store/boltdb" "github.com/docker/libnetwork/datastore" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/types" ) @@ -16,27 +16,15 @@ import ( const bridgePrefix = "bridge" func (d *driver) initStore(option map[string]interface{}) error { - var err error - - provider, provOk := option[netlabel.LocalKVProvider] - provURL, urlOk := option[netlabel.LocalKVProviderURL] - - if provOk && urlOk { - cfg := &datastore.ScopeCfg{ - Client: datastore.ScopeClientCfg{ - Provider: provider.(string), - Address: provURL.(string), - }, + if data, ok := option[netlabel.LocalKVClient]; ok { + var err error + dsc, ok := data.(discoverapi.DatastoreConfigData) + if !ok { + return types.InternalErrorf("incorrect data in datastore configuration: %v", data) } - - provConfig, confOk := option[netlabel.LocalKVProviderConfig] - if confOk { - cfg.Client.Config = provConfig.(*store.Config) - } - - d.store, err = datastore.NewDataStore(datastore.LocalScope, cfg) + d.store, err = datastore.NewDataStoreFromConfig(dsc) if err != nil { - return fmt.Errorf("bridge driver failed to initialize data store: %v", err) + return types.InternalErrorf("bridge driver failed to initialize data store: %v", err) } return d.populateNetworks() diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go index f58ecd8b29..284e806030 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/overlay.go @@ -6,12 +6,12 @@ import ( "sync" "github.com/Sirupsen/logrus" - "github.com/docker/libkv/store" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/idm" "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/types" "github.com/hashicorp/serf/serf" ) @@ -25,6 +25,8 @@ const ( vxlanVethMTU = 1450 ) +var initVxlanIdm = make(chan (bool), 1) + type driver struct { eventCh chan serf.Event notifyCh chan ovNotify @@ -56,6 +58,18 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { config: config, } + if data, ok := config[netlabel.GlobalKVClient]; ok { + var err error + dsc, ok := data.(discoverapi.DatastoreConfigData) + if !ok { + return types.InternalErrorf("incorrect data in datastore configuration: %v", data) + } + d.store, err = datastore.NewDataStoreFromConfig(dsc) + if err != nil { + return types.InternalErrorf("failed to initialize data store: %v", err) + } + } + return dc.RegisterDriver(networkType, d, c) } @@ -73,42 +87,33 @@ func Fini(drv driverapi.Driver) { } func (d *driver) configure() error { + if d.store == nil { + return types.NoServiceErrorf("datastore is not available") + } + + if d.vxlanIdm == nil { + return d.initializeVxlanIdm() + } + + return nil +} + +func (d *driver) initializeVxlanIdm() error { var err error - if len(d.config) == 0 { + initVxlanIdm <- true + defer func() { <-initVxlanIdm }() + + if d.vxlanIdm != nil { return nil } - d.once.Do(func() { - provider, provOk := d.config[netlabel.GlobalKVProvider] - provURL, urlOk := d.config[netlabel.GlobalKVProviderURL] + d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) + if err != nil { + return fmt.Errorf("failed to initialize vxlan id manager: %v", err) + } - if provOk && urlOk { - cfg := &datastore.ScopeCfg{ - Client: datastore.ScopeClientCfg{ - Provider: provider.(string), - Address: provURL.(string), - }, - } - provConfig, confOk := d.config[netlabel.GlobalKVProviderConfig] - if confOk { - cfg.Client.Config = provConfig.(*store.Config) - } - d.store, err = datastore.NewDataStore(datastore.GlobalScope, cfg) - if err != nil { - err = fmt.Errorf("failed to initialize data store: %v", err) - return - } - } - - d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) - if err != nil { - err = fmt.Errorf("failed to initialize vxlan id manager: %v", err) - return - } - }) - - return err + return nil } func (d *driver) Type() string { @@ -187,12 +192,27 @@ func (d *driver) pushLocalEndpointEvent(action, nid, eid string) { // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { - if dType == discoverapi.NodeDiscovery { + switch dType { + case discoverapi.NodeDiscovery: nodeData, ok := data.(discoverapi.NodeDiscoveryData) if !ok || nodeData.Address == "" { return fmt.Errorf("invalid discovery data") } d.nodeJoin(nodeData.Address, nodeData.Self) + case discoverapi.DatastoreConfig: + var err error + if d.store != nil { + return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already") + } + dsc, ok := data.(discoverapi.DatastoreConfigData) + if !ok { + return types.InternalErrorf("incorrect data in datastore configuration: %v", data) + } + d.store, err = datastore.NewDataStoreFromConfig(dsc) + if err != nil { + return types.InternalErrorf("failed to initialize data store: %v", err) + } + default: } return nil } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go b/vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go new file mode 100644 index 0000000000..7cccf2011c --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go @@ -0,0 +1,12 @@ +package windows + +const ( + // NetworkName label for bridge driver + NetworkName = "com.docker.network.windowsshim.networkname" + + // HNSID of the discovered network + HNSID = "com.docker.network.windowsshim.hnsid" + + // RoutingDomain of the network + RoutingDomain = "com.docker.network.windowsshim.routingdomain" +) diff --git a/vendor/src/github.com/docker/libnetwork/drivers/windows/windows.go b/vendor/src/github.com/docker/libnetwork/drivers/windows/windows.go index e51da7dca2..9cb9faaeb2 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/windows/windows.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/windows/windows.go @@ -1,57 +1,419 @@ +// +build windows + +// Shim for the Host Network Service (HNS) to manage networking for +// Windows Server containers and Hyper-V containers. This module +// is a basic libnetwork driver that passes all the calls to HNS +// It implements the 4 networking modes supported by HNS L2Bridge, +// L2Tunnel, NAT and Transparent(DHCP) +// +// The network are stored in memory and docker daemon ensures discovering +// and loading these networks on startup + package windows import ( + "encoding/json" + "fmt" + "net" + "strings" + "sync" + + "github.com/Microsoft/hcsshim" + log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/types" ) -const networkType = "windows" - -// TODO Windows. This is a placeholder for now - -type driver struct{} - -// Init registers a new instance of null driver -func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { - c := driverapi.Capability{ - DataScope: datastore.LocalScope, - } - return dc.RegisterDriver(networkType, &driver{}, c) +// networkConfiguration for network specific configuration +type networkConfiguration struct { + ID string + Type string + Name string + HnsID string + RDID string } +type hnsEndpoint struct { + id string + profileID string + macAddress net.HardwareAddr + addr *net.IPNet +} + +type hnsNetwork struct { + id string + config *networkConfiguration + endpoints map[string]*hnsEndpoint // key: endpoint id + driver *driver // The network's driver + sync.Mutex +} + +type driver struct { + name string + networks map[string]*hnsNetwork + sync.Mutex +} + +func isValidNetworkType(networkType string) bool { + if "L2Bridge" == networkType || "L2Tunnel" == networkType || "NAT" == networkType || "Transparent" == networkType { + return true + } + + return false +} + +// New constructs a new bridge driver +func newDriver(networkType string) *driver { + return &driver{name: networkType, networks: map[string]*hnsNetwork{}} +} + +// GetInit returns an initializer for the given network type +func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error { + return func(dc driverapi.DriverCallback, config map[string]interface{}) error { + if !isValidNetworkType(networkType) { + return types.BadRequestErrorf("Network type not supported: %s", networkType) + } + + return dc.RegisterDriver(networkType, newDriver(networkType), driverapi.Capability{ + DataScope: datastore.LocalScope, + }) + } +} + +func (d *driver) getNetwork(id string) (*hnsNetwork, error) { + d.Lock() + defer d.Unlock() + + if nw, ok := d.networks[id]; ok { + return nw, nil + } + + return nil, types.NotFoundErrorf("network not found: %s", id) +} + +func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) { + n.Lock() + defer n.Unlock() + + if ep, ok := n.endpoints[eid]; ok { + return ep, nil + } + + return nil, types.NotFoundErrorf("Endpoint not found: %s", eid) +} + +func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) { + config := &networkConfiguration{} + + for label, value := range genericOptions { + switch label { + case NetworkName: + config.Name = value + case HNSID: + config.HnsID = value + case RoutingDomain: + config.RDID = value + } + } + + config.ID = id + config.Type = d.name + return config, nil +} + +func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error { + if len(ipamV6Data) > 0 { + return types.ForbiddenErrorf("windowsshim driver doesnt support v6 subnets") + } + + if len(ipamV4Data) == 0 { + return types.BadRequestErrorf("network %s requires ipv4 configuration", id) + } + + return nil +} + +// Create a new network func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error { + if _, err := d.getNetwork(id); err == nil { + return types.ForbiddenErrorf("network %s exists", id) + } + + genData, ok := option[netlabel.GenericData].(map[string]string) + if !ok { + return fmt.Errorf("Unknown generic data option") + } + + // Parse and validate the config. It should not conflict with existing networks' config + config, err := d.parseNetworkOptions(id, genData) + if err != nil { + return err + } + + err = config.processIPAM(id, ipV4Data, ipV6Data) + if err != nil { + return err + } + + network := &hnsNetwork{ + id: config.ID, + endpoints: make(map[string]*hnsEndpoint), + config: config, + driver: d, + } + + d.Lock() + d.networks[config.ID] = network + d.Unlock() + + // A non blank hnsid indicates that the network was discovered + // from HNS. No need to call HNS if this network was discovered + // from HNS + if config.HnsID == "" { + subnets := []hcsshim.Subnet{} + + for _, ipData := range ipV4Data { + subnet := hcsshim.Subnet{ + AddressPrefix: ipData.Pool.String(), + GatewayAddress: ipData.Gateway.IP.String(), + } + + subnets = append(subnets, subnet) + } + + network := &hcsshim.HNSNetwork{ + Name: config.Name, + Type: d.name, + Subnets: subnets, + } + + if network.Name == "" { + network.Name = id + } + + configurationb, err := json.Marshal(network) + if err != nil { + return err + } + + configuration := string(configurationb) + log.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets) + + hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration) + if err != nil { + return err + } + + config.HnsID = hnsresponse.Id + genData[HNSID] = config.HnsID + } + return nil } func (d *driver) DeleteNetwork(nid string) error { + n, err := d.getNetwork(nid) + if err != nil { + return types.InternalMaskableErrorf("%s", err) + } + + n.Lock() + config := n.config + n.Unlock() + + // Cannot remove network if endpoints are still present + if len(n.endpoints) != 0 { + return fmt.Errorf("network %s has active endpoint", n.id) + } + + _, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "") + if err != nil { + return err + } + + d.Lock() + delete(d.networks, nid) + d.Unlock() + return nil } +func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) { + var pbs []json.RawMessage + + // Enumerate through the port bindings specified by the user and convert + // them into the internal structure matching the JSON blob that can be + // understood by the HCS. + for _, elem := range portBindings { + proto := strings.ToUpper(elem.Proto.String()) + if proto != "TCP" && proto != "UDP" { + return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String()) + } + + if elem.HostPort != elem.HostPortEnd { + return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings") + } + + if len(elem.HostIP) != 0 { + return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings") + } + + encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{ + Type: "NAT", + ExternalPort: elem.HostPort, + InternalPort: elem.Port, + Protocol: elem.Proto.String(), + }) + + if err != nil { + return nil, err + } + pbs = append(pbs, encodedPolicy) + } + return pbs, nil +} + func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { + n, err := d.getNetwork(nid) + if err != nil { + return err + } + + // Check if endpoint id is good and retrieve corresponding endpoint + ep, err := n.getEndpoint(eid) + if err == nil && ep != nil { + return driverapi.ErrEndpointExists(eid) + } + + endpointStruct := &hcsshim.HNSEndpoint{ + VirtualNetwork: n.config.HnsID, + } + + // Convert the port mapping for the network + if opt, ok := epOptions[netlabel.PortMap]; ok { + if bs, ok := opt.([]types.PortBinding); ok { + endpointStruct.Policies, err = convertPortBindings(bs) + if err != nil { + return err + } + } else { + return fmt.Errorf("Invalid endpoint configuration for endpoint id%s", eid) + } + } + + configurationb, err := json.Marshal(endpointStruct) + if err != nil { + return err + } + + hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb)) + if err != nil { + return err + } + + mac, err := net.ParseMAC(hnsresponse.MacAddress) + if err != nil { + return err + } + + // TODO For now the ip mask is not in the info generated by HNS + endpoint := &hnsEndpoint{ + id: eid, + addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()}, + macAddress: mac, + } + endpoint.profileID = hnsresponse.Id + n.Lock() + n.endpoints[eid] = endpoint + n.Unlock() + + ifInfo.SetIPAddress(endpoint.addr) + ifInfo.SetMacAddress(endpoint.macAddress) + return nil } func (d *driver) DeleteEndpoint(nid, eid string) error { + n, err := d.getNetwork(nid) + if err != nil { + return types.InternalMaskableErrorf("%s", err) + } + + ep, err := n.getEndpoint(eid) + if err != nil { + return err + } + + n.Lock() + delete(n.endpoints, eid) + n.Unlock() + + _, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "") + if err != nil { + return err + } + return nil } func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { - return make(map[string]interface{}, 0), nil + network, err := d.getNetwork(nid) + if err != nil { + return nil, err + } + + endpoint, err := network.getEndpoint(eid) + if err != nil { + return nil, err + } + + data := make(map[string]interface{}, 1) + data["hnsid"] = endpoint.profileID + return data, nil } // Join method is invoked when a Sandbox is attached to an endpoint. func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { + network, err := d.getNetwork(nid) + if err != nil { + return err + } + + // Ensure that the endpoint exists + _, err = network.getEndpoint(eid) + if err != nil { + return err + } + + // This is just a stub for now + + jinfo.DisableGatewayService() return nil } // Leave method is invoked when a Sandbox detaches from an endpoint. func (d *driver) Leave(nid, eid string) error { + network, err := d.getNetwork(nid) + if err != nil { + return types.InternalMaskableErrorf("%s", err) + } + + // Ensure that the endpoint exists + _, err = network.getEndpoint(eid) + if err != nil { + return err + } + + // This is just a stub for now + return nil } func (d *driver) Type() string { - return networkType + return d.name } // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster diff --git a/vendor/src/github.com/docker/libnetwork/drivers_windows.go b/vendor/src/github.com/docker/libnetwork/drivers_windows.go index 314ff8d58d..d4769aec9b 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers_windows.go +++ b/vendor/src/github.com/docker/libnetwork/drivers_windows.go @@ -1,9 +1,16 @@ package libnetwork -import "github.com/docker/libnetwork/drivers/windows" +import ( + "github.com/docker/libnetwork/drivers/null" + "github.com/docker/libnetwork/drivers/windows" +) func getInitializers() []initializer { return []initializer{ - {windows.Init, "windows"}, + {null.Init, "null"}, + {windows.GetInit("Transparent"), "Transparent"}, + {windows.GetInit("L2Bridge"), "L2Bridge"}, + {windows.GetInit("L2Tunnel"), "L2Tunnel"}, + {windows.GetInit("NAT"), "NAT"}, } } diff --git a/vendor/src/github.com/docker/libnetwork/ipam/allocator.go b/vendor/src/github.com/docker/libnetwork/ipam/allocator.go index bbaa7d11d2..70fe06eba7 100644 --- a/vendor/src/github.com/docker/libnetwork/ipam/allocator.go +++ b/vendor/src/github.com/docker/libnetwork/ipam/allocator.go @@ -8,6 +8,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/bitseq" "github.com/docker/libnetwork/datastore" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/ipamutils" "github.com/docker/libnetwork/types" @@ -60,19 +61,9 @@ func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) { if aspc.ds == nil { continue } - - a.addrSpaces[aspc.as] = &addrSpace{ - subnets: map[SubnetKey]*PoolData{}, - id: dsConfigKey + "/" + aspc.as, - scope: aspc.ds.Scope(), - ds: aspc.ds, - alloc: a, - } + a.initializeAddressSpace(aspc.as, aspc.ds) } - a.checkConsistency(localAddressSpace) - a.checkConsistency(globalAddressSpace) - return a, nil } @@ -118,25 +109,83 @@ func (a *Allocator) updateBitMasks(aSpace *addrSpace) error { return nil } -// Checks for and fixes damaged bitmask. Meant to be called in constructor only. +// Checks for and fixes damaged bitmask. func (a *Allocator) checkConsistency(as string) { + var sKeyList []SubnetKey + // Retrieve this address space's configuration and bitmasks from the datastore a.refresh(as) + a.Lock() aSpace, ok := a.addrSpaces[as] + a.Unlock() if !ok { return } a.updateBitMasks(aSpace) + + aSpace.Lock() for sk, pd := range aSpace.subnets { if pd.Range != nil { continue } - if err := a.addresses[sk].CheckConsistency(); err != nil { + sKeyList = append(sKeyList, sk) + } + aSpace.Unlock() + + for _, sk := range sKeyList { + a.Lock() + bm := a.addresses[sk] + a.Unlock() + if err := bm.CheckConsistency(); err != nil { log.Warnf("Error while running consistency check for %s: %v", sk, err) } } } +func (a *Allocator) initializeAddressSpace(as string, ds datastore.DataStore) error { + a.Lock() + if _, ok := a.addrSpaces[as]; ok { + a.Unlock() + return types.ForbiddenErrorf("tried to add an axisting address space: %s", as) + } + a.addrSpaces[as] = &addrSpace{ + subnets: map[SubnetKey]*PoolData{}, + id: dsConfigKey + "/" + as, + scope: ds.Scope(), + ds: ds, + alloc: a, + } + a.Unlock() + + a.checkConsistency(as) + + return nil +} + +// DiscoverNew informs the allocator about a new global scope datastore +func (a *Allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { + if dType != discoverapi.DatastoreConfig { + return nil + } + + dsc, ok := data.(discoverapi.DatastoreConfigData) + if !ok { + return types.InternalErrorf("incorrect data in datastore update notification: %v", data) + } + + ds, err := datastore.NewDataStoreFromConfig(dsc) + if err != nil { + return err + } + + return a.initializeAddressSpace(globalAddressSpace, ds) +} + +// DiscoverDelete is a notification of no interest for the allocator +func (a *Allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { + return nil +} + // GetDefaultAddressSpaces returns the local and global default address spaces func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) { return localAddressSpace, globalAddressSpace, nil diff --git a/vendor/src/github.com/docker/libnetwork/ipamapi/contract.go b/vendor/src/github.com/docker/libnetwork/ipamapi/contract.go index 812bdbc068..ae6ecc8990 100644 --- a/vendor/src/github.com/docker/libnetwork/ipamapi/contract.go +++ b/vendor/src/github.com/docker/libnetwork/ipamapi/contract.go @@ -4,6 +4,7 @@ package ipamapi import ( "net" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/types" ) @@ -56,6 +57,8 @@ var ( // Ipam represents the interface the IPAM service plugins must implement // in order to allow injection/modification of IPAM database. type Ipam interface { + discoverapi.Discover + // GetDefaultAddressSpaces returns the default local and global address spaces for this ipam GetDefaultAddressSpaces() (string, string, error) // RequestPool returns an address pool along with its unique id. Address space is a mandatory field diff --git a/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin.go b/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go similarity index 96% rename from vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin.go rename to vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go index 707e001f73..311183fc87 100644 --- a/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin.go +++ b/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_unix.go @@ -1,3 +1,5 @@ +// +build linux freebsd + package builtin import ( diff --git a/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go b/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go new file mode 100644 index 0000000000..d24f5e63dc --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go @@ -0,0 +1,16 @@ +// +build windows + +package builtin + +import ( + "github.com/docker/libnetwork/ipamapi" + + windowsipam "github.com/docker/libnetwork/ipams/windowsipam" +) + +// Init registers the built-in ipam service with libnetwork +func Init(ic ipamapi.Callback, l, g interface{}) error { + initFunc := windowsipam.GetInit(ipamapi.DefaultIPAM) + + return initFunc(ic, l, g) +} diff --git a/vendor/src/github.com/docker/libnetwork/ipams/remote/remote.go b/vendor/src/github.com/docker/libnetwork/ipams/remote/remote.go index 581a9c8871..799a2e77f4 100644 --- a/vendor/src/github.com/docker/libnetwork/ipams/remote/remote.go +++ b/vendor/src/github.com/docker/libnetwork/ipams/remote/remote.go @@ -6,6 +6,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/plugins" + "github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/ipams/remote/api" "github.com/docker/libnetwork/types" @@ -124,3 +125,13 @@ func (a *allocator) ReleaseAddress(poolID string, address net.IP) error { res := &api.ReleaseAddressResponse{} return a.call("ReleaseAddress", req, res) } + +// DiscoverNew is a notification for a new discovery event, such as a new global datastore +func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { + return nil +} + +// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster +func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { + return nil +} diff --git a/vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go b/vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go new file mode 100644 index 0000000000..6c112d2536 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go @@ -0,0 +1,93 @@ +package windowsipam + +import ( + "net" + + log "github.com/Sirupsen/logrus" + "github.com/docker/libnetwork/discoverapi" + "github.com/docker/libnetwork/ipamapi" + "github.com/docker/libnetwork/types" +) + +const ( + localAddressSpace = "LocalDefault" + globalAddressSpace = "GlobalDefault" +) + +var ( + defaultPool, _ = types.ParseCIDR("0.0.0.0/0") +) + +type allocator struct { +} + +// GetInit registers the built-in ipam service with libnetwork +func GetInit(ipamName string) func(ic ipamapi.Callback, l, g interface{}) error { + return func(ic ipamapi.Callback, l, g interface{}) error { + return ic.RegisterIpamDriver(ipamName, &allocator{}) + } +} + +func (a *allocator) GetDefaultAddressSpaces() (string, string, error) { + return localAddressSpace, globalAddressSpace, nil +} + +// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the +// subnet user asked and does not validate anything. Doesnt support subpool allocation +func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) { + log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6) + if subPool != "" || v6 { + return "", nil, nil, types.InternalErrorf("This request is not supported by null ipam driver") + } + + var ipNet *net.IPNet + var err error + + if pool != "" { + _, ipNet, err = net.ParseCIDR(pool) + if err != nil { + return "", nil, nil, err + } + } else { + ipNet = defaultPool + } + + return ipNet.String(), ipNet, nil, nil +} + +// ReleasePool releases the address pool - always succeeds +func (a *allocator) ReleasePool(poolID string) error { + log.Debugf("ReleasePool(%s)", poolID) + return nil +} + +// RequestAddress returns an address from the specified pool ID. +// Always allocate the 0.0.0.0/32 ip if no preferred address was specified +func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) { + log.Debugf("RequestAddress(%s, %v, %v) %s", poolID, prefAddress, opts, opts["RequestAddressType"]) + _, ipNet, err := net.ParseCIDR(poolID) + + if err != nil { + return nil, nil, err + } + if prefAddress == nil { + return ipNet, nil, nil + } + return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil +} + +// ReleaseAddress releases the address - always succeeds +func (a *allocator) ReleaseAddress(poolID string, address net.IP) error { + log.Debugf("ReleaseAddress(%s, %v)", poolID, address) + return nil +} + +// DiscoverNew informs the allocator about a new global scope datastore +func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { + return nil +} + +// DiscoverDelete is a notification of no interest for the allocator +func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { + return nil +} diff --git a/vendor/src/github.com/docker/libnetwork/netlabel/labels.go b/vendor/src/github.com/docker/libnetwork/netlabel/labels.go index c6d7f13477..d44015f159 100644 --- a/vendor/src/github.com/docker/libnetwork/netlabel/labels.go +++ b/vendor/src/github.com/docker/libnetwork/netlabel/labels.go @@ -56,6 +56,9 @@ var ( // GlobalKVProviderConfig constant represents the KV provider Config GlobalKVProviderConfig = MakeKVProviderConfig("global") + // GlobalKVClient constants represents the global kv store client + GlobalKVClient = MakeKVClient("global") + // LocalKVProvider constant represents the KV provider backend LocalKVProvider = MakeKVProvider("local") @@ -64,6 +67,9 @@ var ( // LocalKVProviderConfig constant represents the KV provider Config LocalKVProviderConfig = MakeKVProviderConfig("local") + + // LocalKVClient constants represents the local kv store client + LocalKVClient = MakeKVClient("local") ) // MakeKVProvider returns the kvprovider label for the scope @@ -81,6 +87,11 @@ func MakeKVProviderConfig(scope string) string { return DriverPrivatePrefix + scope + "kv_provider_config" } +// MakeKVClient returns the kv client label for the scope +func MakeKVClient(scope string) string { + return DriverPrivatePrefix + scope + "kv_client" +} + // Key extracts the key portion of the label func Key(label string) (key string) { if kv := strings.SplitN(label, "=", 2); len(kv) > 0 { diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go index d995072f9c..1ef4e569a0 100644 --- a/vendor/src/github.com/docker/libnetwork/network.go +++ b/vendor/src/github.com/docker/libnetwork/network.go @@ -1004,7 +1004,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error { if ipVer == 6 { return nil } - *cfgList = []*IpamConf{&IpamConf{}} + *cfgList = []*IpamConf{{}} } *infoList = make([]*IpamInfo, len(*cfgList)) diff --git a/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go b/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go index 530703b259..ddde2744c2 100644 --- a/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go +++ b/vendor/src/github.com/docker/libnetwork/portmapper/proxy.go @@ -85,7 +85,7 @@ func handleStopSignals(p proxy.Proxy) { s := make(chan os.Signal, 10) signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP) - for _ = range s { + for range s { p.Close() os.Exit(0) diff --git a/vendor/src/github.com/docker/libnetwork/resolver.go b/vendor/src/github.com/docker/libnetwork/resolver.go index e0a5e49aad..ed17a2d9ef 100644 --- a/vendor/src/github.com/docker/libnetwork/resolver.go +++ b/vendor/src/github.com/docker/libnetwork/resolver.go @@ -35,7 +35,7 @@ const ( dnsPort = "53" ptrIPv4domain = ".in-addr.arpa." ptrIPv6domain = ".ip6.arpa." - respTTL = 1800 + respTTL = 600 maxExtDNS = 3 //max number of external servers to try ) @@ -147,6 +147,10 @@ func (r *resolver) ResolverOptions() []string { return []string{"ndots:0"} } +func setCommonFlags(msg *dns.Msg) { + msg.RecursionAvailable = true +} + func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) { addr := r.sb.ResolveName(name) if addr == nil { @@ -157,6 +161,7 @@ func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error resp := new(dns.Msg) resp.SetReply(query) + setCommonFlags(resp) rr := new(dns.A) rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL} @@ -186,6 +191,7 @@ func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error) resp := new(dns.Msg) resp.SetReply(query) + setCommonFlags(resp) rr := new(dns.PTR) rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL} @@ -200,6 +206,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) { err error ) + if query == nil || len(query.Question) == 0 { + return + } name := query.Question[0].Name if query.Question[0].Qtype == dns.TypeA { resp, err = r.handleIPv4Query(name, query) diff --git a/vendor/src/github.com/docker/libnetwork/sandbox.go b/vendor/src/github.com/docker/libnetwork/sandbox.go index ae11665773..c33f4e68da 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox.go @@ -4,19 +4,13 @@ import ( "container/heap" "encoding/json" "fmt" - "io/ioutil" "net" - "os" - "path" - "path/filepath" "strings" "sync" log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/etchosts" - "github.com/docker/libnetwork/netutils" "github.com/docker/libnetwork/osl" - "github.com/docker/libnetwork/resolvconf" "github.com/docker/libnetwork/types" ) @@ -309,46 +303,6 @@ func (sb *sandbox) UnmarshalJSON(b []byte) (err error) { return nil } -func (sb *sandbox) startResolver() { - sb.resolverOnce.Do(func() { - var err error - sb.resolver = NewResolver(sb) - defer func() { - if err != nil { - sb.resolver = nil - } - }() - - err = sb.rebuildDNS() - if err != nil { - log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err) - return - } - sb.resolver.SetExtServers(sb.extDNS) - - sb.osSbox.InvokeFunc(sb.resolver.SetupFunc()) - if err = sb.resolver.Start(); err != nil { - log.Errorf("Resolver Setup/Start failed for container %s, %q", sb.ContainerID(), err) - } - }) -} - -func (sb *sandbox) setupResolutionFiles() error { - if err := sb.buildHostsFile(); err != nil { - return err - } - - if err := sb.updateParentHosts(); err != nil { - return err - } - - if err := sb.setupDNS(); err != nil { - return err - } - - return nil -} - func (sb *sandbox) Endpoints() []Endpoint { sb.Lock() defer sb.Unlock() @@ -753,243 +707,6 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error { return nil } -const ( - defaultPrefix = "/var/lib/docker/network/files" - dirPerm = 0755 - filePerm = 0644 -) - -func (sb *sandbox) buildHostsFile() error { - if sb.config.hostsPath == "" { - sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts" - } - - dir, _ := filepath.Split(sb.config.hostsPath) - if err := createBasePath(dir); err != nil { - return err - } - - // This is for the host mode networking - if sb.config.originHostsPath != "" { - 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) - } - return nil - } - - extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts)) - for _, extraHost := range sb.config.extraHosts { - extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP}) - } - - return etchosts.Build(sb.config.hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent) -} - -func (sb *sandbox) updateHostsFile(ifaceIP string) error { - var mhost string - - if sb.config.originHostsPath != "" { - return nil - } - - if sb.config.domainName != "" { - mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName, - sb.config.hostName) - } else { - mhost = sb.config.hostName - } - - extraContent := []etchosts.Record{{Hosts: mhost, IP: ifaceIP}} - - sb.addHostsEntries(extraContent) - return nil -} - -func (sb *sandbox) addHostsEntries(recs []etchosts.Record) { - if err := etchosts.Add(sb.config.hostsPath, recs); err != nil { - log.Warnf("Failed adding service host entries to the running container: %v", err) - } -} - -func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) { - if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil { - log.Warnf("Failed deleting service host entries to the running container: %v", err) - } -} - -func (sb *sandbox) updateParentHosts() error { - var pSb Sandbox - - for _, update := range sb.config.parentUpdates { - sb.controller.WalkSandboxes(SandboxContainerWalker(&pSb, update.cid)) - if pSb == nil { - continue - } - if err := etchosts.Update(pSb.(*sandbox).config.hostsPath, update.ip, update.name); err != nil { - return err - } - } - - return nil -} - -func (sb *sandbox) setupDNS() error { - var newRC *resolvconf.File - - if sb.config.resolvConfPath == "" { - sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf" - } - - sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash" - - dir, _ := filepath.Split(sb.config.resolvConfPath) - if err := createBasePath(dir); err != nil { - return err - } - - // This is for the host mode networking - if sb.config.originResolvConfPath != "" { - if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil { - return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err) - } - return nil - } - - currRC, err := resolvconf.Get() - if err != nil { - return err - } - - if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 { - var ( - err error - dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP) - dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) - dnsOptionsList = resolvconf.GetOptions(currRC.Content) - ) - if len(sb.config.dnsList) > 0 { - dnsList = sb.config.dnsList - } - if len(sb.config.dnsSearchList) > 0 { - dnsSearchList = sb.config.dnsSearchList - } - if len(sb.config.dnsOptionsList) > 0 { - dnsOptionsList = sb.config.dnsOptionsList - } - newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList) - if err != nil { - return err - } - } else { - // Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true) - if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil { - return err - } - // No contention on container resolv.conf file at sandbox creation - if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil { - return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err) - } - } - - // Write hash - if err := ioutil.WriteFile(sb.config.resolvConfHashFile, []byte(newRC.Hash), filePerm); err != nil { - return types.InternalErrorf("failed to write resolv.conf hash file when setting up dns for sandbox %s: %v", sb.ID(), err) - } - - return nil -} - -func (sb *sandbox) updateDNS(ipv6Enabled bool) error { - var ( - currHash string - hashFile = sb.config.resolvConfHashFile - ) - - // This is for the host mode networking - if sb.config.originResolvConfPath != "" { - return nil - } - - if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 { - return nil - } - - currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) - if err != nil { - if !os.IsNotExist(err) { - return err - } - } else { - h, err := ioutil.ReadFile(hashFile) - if err != nil { - if !os.IsNotExist(err) { - return err - } - } else { - currHash = string(h) - } - } - - if currHash != "" && currHash != currRC.Hash { - // Seems the user has changed the container resolv.conf since the last time - // we checked so return without doing anything. - log.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled) - return nil - } - - // replace any localhost/127.* and remove IPv6 nameservers if IPv6 disabled. - newRC, err := resolvconf.FilterResolvDNS(currRC.Content, ipv6Enabled) - if err != nil { - return err - } - err = ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, 0644) - if err != nil { - return err - } - - // write the new hash in a temp file and rename it to make the update atomic - dir := path.Dir(sb.config.resolvConfPath) - tmpHashFile, err := ioutil.TempFile(dir, "hash") - if err != nil { - return err - } - if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil { - return err - } - return os.Rename(tmpHashFile.Name(), hashFile) -} - -// Embedded DNS server has to be enabled for this sandbox. Rebuild the container's -// resolv.conf by doing the follwing -// - Save the external name servers in resolv.conf in the sandbox -// - Add only the embedded server's IP to container's resolv.conf -// - If the embedded server needs any resolv.conf options add it to the current list -func (sb *sandbox) rebuildDNS() error { - currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) - if err != nil { - return err - } - - // localhost entries have already been filtered out from the list - // retain only the v4 servers in sb for forwarding the DNS queries - sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4) - - var ( - dnsList = []string{sb.resolver.NameServer()} - dnsOptionsList = resolvconf.GetOptions(currRC.Content) - dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) - ) - - // external v6 DNS servers has to be listed in resolv.conf - dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...) - - // Resolver returns the options in the format resolv.conf expects - dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...) - - _, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList) - return err -} - // joinLeaveStart waits to ensure there are no joins or leaves in progress and // marks this join/leave in progress without race func (sb *sandbox) joinLeaveStart() { @@ -1191,32 +908,3 @@ func (eh *epHeap) Pop() interface{} { *eh = old[0 : n-1] return x } - -func createBasePath(dir string) error { - return os.MkdirAll(dir, dirPerm) -} - -func createFile(path string) error { - var f *os.File - - dir, _ := filepath.Split(path) - err := createBasePath(dir) - if err != nil { - return err - } - - f, err = os.Create(path) - if err == nil { - f.Close() - } - - return err -} - -func copyFile(src, dst string) error { - sBytes, err := ioutil.ReadFile(src) - if err != nil { - return err - } - return ioutil.WriteFile(dst, sBytes, filePerm) -} diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go b/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go new file mode 100644 index 0000000000..c8b595eb24 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go @@ -0,0 +1,323 @@ +// +build !windows + +package libnetwork + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + + log "github.com/Sirupsen/logrus" + "github.com/docker/libnetwork/etchosts" + "github.com/docker/libnetwork/netutils" + "github.com/docker/libnetwork/resolvconf" + "github.com/docker/libnetwork/types" +) + +const ( + defaultPrefix = "/var/lib/docker/network/files" + dirPerm = 0755 + filePerm = 0644 +) + +func (sb *sandbox) startResolver() { + sb.resolverOnce.Do(func() { + var err error + sb.resolver = NewResolver(sb) + defer func() { + if err != nil { + sb.resolver = nil + } + }() + + err = sb.rebuildDNS() + if err != nil { + log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err) + return + } + sb.resolver.SetExtServers(sb.extDNS) + + sb.osSbox.InvokeFunc(sb.resolver.SetupFunc()) + if err = sb.resolver.Start(); err != nil { + log.Errorf("Resolver Setup/Start failed for container %s, %q", sb.ContainerID(), err) + } + }) +} + +func (sb *sandbox) setupResolutionFiles() error { + if err := sb.buildHostsFile(); err != nil { + return err + } + + if err := sb.updateParentHosts(); err != nil { + return err + } + + if err := sb.setupDNS(); err != nil { + return err + } + + return nil +} + +func (sb *sandbox) buildHostsFile() error { + if sb.config.hostsPath == "" { + sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts" + } + + dir, _ := filepath.Split(sb.config.hostsPath) + if err := createBasePath(dir); err != nil { + return err + } + + // This is for the host mode networking + if sb.config.originHostsPath != "" { + 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) + } + return nil + } + + extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts)) + for _, extraHost := range sb.config.extraHosts { + extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP}) + } + + return etchosts.Build(sb.config.hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent) +} + +func (sb *sandbox) updateHostsFile(ifaceIP string) error { + var mhost string + + if sb.config.originHostsPath != "" { + return nil + } + + if sb.config.domainName != "" { + mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName, + sb.config.hostName) + } else { + mhost = sb.config.hostName + } + + extraContent := []etchosts.Record{{Hosts: mhost, IP: ifaceIP}} + + sb.addHostsEntries(extraContent) + return nil +} + +func (sb *sandbox) addHostsEntries(recs []etchosts.Record) { + if err := etchosts.Add(sb.config.hostsPath, recs); err != nil { + log.Warnf("Failed adding service host entries to the running container: %v", err) + } +} + +func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) { + if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil { + log.Warnf("Failed deleting service host entries to the running container: %v", err) + } +} + +func (sb *sandbox) updateParentHosts() error { + var pSb Sandbox + + for _, update := range sb.config.parentUpdates { + sb.controller.WalkSandboxes(SandboxContainerWalker(&pSb, update.cid)) + if pSb == nil { + continue + } + if err := etchosts.Update(pSb.(*sandbox).config.hostsPath, update.ip, update.name); err != nil { + return err + } + } + + return nil +} + +func (sb *sandbox) setupDNS() error { + var newRC *resolvconf.File + + if sb.config.resolvConfPath == "" { + sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf" + } + + sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash" + + dir, _ := filepath.Split(sb.config.resolvConfPath) + if err := createBasePath(dir); err != nil { + return err + } + + // This is for the host mode networking + if sb.config.originResolvConfPath != "" { + if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil { + return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err) + } + return nil + } + + currRC, err := resolvconf.Get() + if err != nil { + return err + } + + if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 { + var ( + err error + dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP) + dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) + dnsOptionsList = resolvconf.GetOptions(currRC.Content) + ) + if len(sb.config.dnsList) > 0 { + dnsList = sb.config.dnsList + } + if len(sb.config.dnsSearchList) > 0 { + dnsSearchList = sb.config.dnsSearchList + } + if len(sb.config.dnsOptionsList) > 0 { + dnsOptionsList = sb.config.dnsOptionsList + } + newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList) + if err != nil { + return err + } + } else { + // Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true) + if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil { + return err + } + // No contention on container resolv.conf file at sandbox creation + if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil { + return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err) + } + } + + // Write hash + if err := ioutil.WriteFile(sb.config.resolvConfHashFile, []byte(newRC.Hash), filePerm); err != nil { + return types.InternalErrorf("failed to write resolv.conf hash file when setting up dns for sandbox %s: %v", sb.ID(), err) + } + + return nil +} + +func (sb *sandbox) updateDNS(ipv6Enabled bool) error { + var ( + currHash string + hashFile = sb.config.resolvConfHashFile + ) + + // This is for the host mode networking + if sb.config.originResolvConfPath != "" { + return nil + } + + if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 { + return nil + } + + currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) + if err != nil { + if !os.IsNotExist(err) { + return err + } + } else { + h, err := ioutil.ReadFile(hashFile) + if err != nil { + if !os.IsNotExist(err) { + return err + } + } else { + currHash = string(h) + } + } + + if currHash != "" && currHash != currRC.Hash { + // Seems the user has changed the container resolv.conf since the last time + // we checked so return without doing anything. + log.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled) + return nil + } + + // replace any localhost/127.* and remove IPv6 nameservers if IPv6 disabled. + newRC, err := resolvconf.FilterResolvDNS(currRC.Content, ipv6Enabled) + if err != nil { + return err + } + err = ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, 0644) + if err != nil { + return err + } + + // write the new hash in a temp file and rename it to make the update atomic + dir := path.Dir(sb.config.resolvConfPath) + tmpHashFile, err := ioutil.TempFile(dir, "hash") + if err != nil { + return err + } + if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil { + return err + } + return os.Rename(tmpHashFile.Name(), hashFile) +} + +// Embedded DNS server has to be enabled for this sandbox. Rebuild the container's +// resolv.conf by doing the follwing +// - Save the external name servers in resolv.conf in the sandbox +// - Add only the embedded server's IP to container's resolv.conf +// - If the embedded server needs any resolv.conf options add it to the current list +func (sb *sandbox) rebuildDNS() error { + currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath) + if err != nil { + return err + } + + // localhost entries have already been filtered out from the list + // retain only the v4 servers in sb for forwarding the DNS queries + sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4) + + var ( + dnsList = []string{sb.resolver.NameServer()} + dnsOptionsList = resolvconf.GetOptions(currRC.Content) + dnsSearchList = resolvconf.GetSearchDomains(currRC.Content) + ) + + // external v6 DNS servers has to be listed in resolv.conf + dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...) + + // Resolver returns the options in the format resolv.conf expects + dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...) + + _, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList) + return err +} + +func createBasePath(dir string) error { + return os.MkdirAll(dir, dirPerm) +} + +func createFile(path string) error { + var f *os.File + + dir, _ := filepath.Split(path) + err := createBasePath(dir) + if err != nil { + return err + } + + f, err = os.Create(path) + if err == nil { + f.Close() + } + + return err +} + +func copyFile(src, dst string) error { + sBytes, err := ioutil.ReadFile(src) + if err != nil { + return err + } + return ioutil.WriteFile(dst, sBytes, filePerm) +} diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go b/vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go new file mode 100644 index 0000000000..ef90ddaeef --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go @@ -0,0 +1,32 @@ +// +build windows + +package libnetwork + +import ( + "github.com/docker/libnetwork/etchosts" +) + +// Stub implementations for DNS related functions + +func (sb *sandbox) startResolver() { +} + +func (sb *sandbox) setupResolutionFiles() error { + return nil +} + +func (sb *sandbox) updateHostsFile(ifaceIP string) error { + return nil +} + +func (sb *sandbox) addHostsEntries(recs []etchosts.Record) { + +} + +func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) { + +} + +func (sb *sandbox) updateDNS(ipv6Enabled bool) error { + return nil +} diff --git a/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go index 74ae2af78e..d0682c2f17 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox_externalkey_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build linux freebsd package libnetwork diff --git a/vendor/src/github.com/docker/libnetwork/store.go b/vendor/src/github.com/docker/libnetwork/store.go index c7c6928dbf..182923ef6c 100644 --- a/vendor/src/github.com/docker/libnetwork/store.go +++ b/vendor/src/github.com/docker/libnetwork/store.go @@ -14,6 +14,7 @@ func (c *controller) initStores() error { return nil } scopeConfigs := c.cfg.Scopes + c.stores = nil c.Unlock() for scope, scfg := range scopeConfigs { @@ -418,6 +419,9 @@ func (c *controller) watchLoop() { } func (c *controller) startWatch() { + if c.watchCh != nil { + return + } c.watchCh = make(chan *endpoint) c.unWatchCh = make(chan *endpoint) c.nmap = make(map[string]*netWatch)