diff --git a/hack/vendor.sh b/hack/vendor.sh index 8dc659b6bb..31d8378679 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -70,7 +70,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e clone git github.com/imdario/mergo 0.2.1 #get libnetwork packages -clone git github.com/docker/libnetwork 9fbb4ecbb45af655c4ac3c2f3a849b2294cb447a +clone git github.com/docker/libnetwork f4338b6f1085ccfe5972e655cca8a1d15d73439d clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec diff --git a/vendor/src/github.com/docker/libnetwork/controller.go b/vendor/src/github.com/docker/libnetwork/controller.go index 914287a5be..a8c30adc95 100644 --- a/vendor/src/github.com/docker/libnetwork/controller.go +++ b/vendor/src/github.com/docker/libnetwork/controller.go @@ -1062,9 +1062,14 @@ func SandboxKeyWalker(out *Sandbox, key string) SandboxWalker { } func (c *controller) loadDriver(networkType string) error { - // Plugins pkg performs lazy loading of plugins that acts as remote drivers. - // As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available. - _, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType) + var err error + + if pg := c.GetPluginGetter(); pg != nil { + _, err = pg.Get(networkType, driverapi.NetworkPluginEndpointType, plugingetter.LOOKUP) + } else { + _, err = plugins.Get(networkType, driverapi.NetworkPluginEndpointType) + } + if err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) @@ -1076,7 +1081,15 @@ func (c *controller) loadDriver(networkType string) error { } func (c *controller) loadIPAMDriver(name string) error { - if _, err := c.GetPluginGetter().Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP); err != nil { + var err error + + if pg := c.GetPluginGetter(); pg != nil { + _, err = pg.Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP) + } else { + _, err = plugins.Get(name, ipamapi.PluginEndpointType) + } + + if err != nil { if err == plugins.ErrNotFound { return types.NotFoundErrorf(err.Error()) } 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 64492eddc2..a30140feae 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -779,6 +779,20 @@ func (d *driver) DeleteNetwork(nid string) error { config := n.config n.Unlock() + // delele endpoints belong to this network + for _, ep := range n.endpoints { + if err := n.releasePorts(ep); err != nil { + logrus.Warn(err) + } + if link, err := d.nlh.LinkByName(ep.srcName); err == nil { + d.nlh.LinkDel(link) + } + + if err := d.storeDelete(ep); err != nil { + logrus.Warnf("Failed to remove bridge endpoint %s from store: %v", ep.id[0:7], err) + } + } + d.Lock() delete(d.networks, nid) d.Unlock() diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/interface.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/interface.go index 16a8c7722d..9b20900416 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/interface.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/interface.go @@ -52,23 +52,22 @@ func (i *bridgeInterface) exists() bool { return i.Link != nil } -// addresses returns a single IPv4 address and all IPv6 addresses for the -// bridge interface. -func (i *bridgeInterface) addresses() (netlink.Addr, []netlink.Addr, error) { +// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface. +func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) { v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4) if err != nil { - return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err) + return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err) } v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6) if err != nil { - return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err) + return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err) } if len(v4addr) == 0 { - return netlink.Addr{}, v6addr, nil + return nil, v6addr, nil } - return v4addr[0], v6addr, nil + return v4addr, v6addr, nil } func (i *bridgeInterface) programIPv6Address() error { diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go index f11adc2cb1..3af5836d52 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go @@ -3,6 +3,7 @@ package bridge import ( "fmt" "io/ioutil" + "net" "path/filepath" log "github.com/Sirupsen/logrus" @@ -10,12 +11,28 @@ import ( "github.com/vishvananda/netlink" ) +func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) { + if len(addresses) == 0 { + return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty") + } + if selector != nil { + for _, addr := range addresses { + if selector.Contains(addr.IP) { + return addr, nil + } + } + } + return addresses[0], nil +} + func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error { - addrv4, _, err := i.addresses() + addrv4List, _, err := i.addresses() if err != nil { return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err) } + addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4) + if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) { if addrv4.IPNet != nil { if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil { diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_verify.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_verify.go index 0bafed6011..ec37d16d06 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_verify.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_verify.go @@ -11,12 +11,14 @@ import ( ) func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error { - // Fetch a single IPv4 and a slice of IPv6 addresses from the bridge. - addrv4, addrsv6, err := i.addresses() + // Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge. + addrsv4, addrsv6, err := i.addresses() if err != nil { return fmt.Errorf("Failed to verify ip addresses: %v", err) } + addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4) + // Verify that the bridge does have an IPv4 address. if addrv4.IPNet == nil { return &ErrNoIPAddr{} diff --git a/vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go b/vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go index 7a58a382d0..801fc20a7e 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/pkg/stringid" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/ns" "github.com/docker/libnetwork/options" "github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/types" @@ -147,6 +148,15 @@ func (d *driver) DeleteNetwork(nid string) error { } } } + for _, ep := range n.endpoints { + if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil { + ns.NlHandle().LinkDel(link) + } + + if err := d.storeDelete(ep); err != nil { + logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err) + } + } // delete the *network d.deleteNetwork(nid) // delete the network record from persistent cache diff --git a/vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go b/vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go index 2975596593..fcc6ccc9e1 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/pkg/stringid" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/ns" "github.com/docker/libnetwork/options" "github.com/docker/libnetwork/osl" "github.com/docker/libnetwork/types" @@ -151,6 +152,15 @@ func (d *driver) DeleteNetwork(nid string) error { } } } + for _, ep := range n.endpoints { + if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil { + ns.NlHandle().LinkDel(link) + } + + if err := d.storeDelete(ep); err != nil { + logrus.Warnf("Failed to remove macvlan endpoint %s from store: %v", ep.id[0:7], err) + } + } // delete the *network d.deleteNetwork(nid) // delete the network record from persistent cache diff --git a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go index b5af0f4b04..c6bc67cab5 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/overlay/ov_network.go @@ -182,6 +182,18 @@ func (d *driver) DeleteNetwork(nid string) error { return fmt.Errorf("could not find network with id %s", nid) } + for _, ep := range n.endpoints { + if ep.ifName != "" { + if link, err := ns.NlHandle().LinkByName(ep.ifName); err != nil { + ns.NlHandle().LinkDel(link) + } + } + + if err := d.deleteEndpointFromStore(ep); err != nil { + logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err) + } + + } d.deleteNetwork(nid) vnis, err := n.releaseVxlanID() diff --git a/vendor/src/github.com/docker/libnetwork/endpoint.go b/vendor/src/github.com/docker/libnetwork/endpoint.go index 1c75b6fea5..65a7295424 100644 --- a/vendor/src/github.com/docker/libnetwork/endpoint.go +++ b/vendor/src/github.com/docker/libnetwork/endpoint.go @@ -513,14 +513,22 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error { if moveExtConn { if extEp != nil { log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID()) - if err = d.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil { + extN, err := extEp.getNetworkFromStore() + if err != nil { + return fmt.Errorf("failed to get network from store during join: %v", err) + } + extD, err := extN.driver(true) + if err != nil { + return fmt.Errorf("failed to join endpoint: %v", err) + } + if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil { return types.InternalErrorf( "driver failed revoking external connectivity on endpoint %s (%s): %v", extEp.Name(), extEp.ID(), err) } defer func() { if err != nil { - if e := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil { + if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil { log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v", extEp.Name(), extEp.ID(), e) } @@ -699,7 +707,15 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) extEp = sb.getGatewayEndpoint() if moveExtConn && extEp != nil { log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID()) - if err := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil { + extN, err := extEp.getNetworkFromStore() + if err != nil { + return fmt.Errorf("failed to get network from store during leave: %v", err) + } + extD, err := extN.driver(true) + if err != nil { + return fmt.Errorf("failed to leave endpoint: %v", err) + } + if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil { log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v", extEp.Name(), extEp.ID(), err) } diff --git a/vendor/src/github.com/docker/libnetwork/ipam/allocator.go b/vendor/src/github.com/docker/libnetwork/ipam/allocator.go index c059d447d7..c259a05283 100644 --- a/vendor/src/github.com/docker/libnetwork/ipam/allocator.go +++ b/vendor/src/github.com/docker/libnetwork/ipam/allocator.go @@ -199,12 +199,22 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) { // RequestPool returns an address pool along with its unique id. 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) -retry: - k, nw, ipr, pdf, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) + + k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) if err != nil { return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err) } + pdf := k == nil + +retry: + if pdf { + if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil { + return "", nil, nil, err + } + k = &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String()} + } + if err := a.refresh(addressSpace); err != nil { return "", nil, nil, err } @@ -279,39 +289,36 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) { return aSpace, nil } -func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, bool, error) { +func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) { var ( nw *net.IPNet ipr *AddressRange err error - pdf = false ) if addressSpace == "" { - return nil, nil, nil, false, ipamapi.ErrInvalidAddressSpace + return nil, nil, nil, ipamapi.ErrInvalidAddressSpace } if pool == "" && subPool != "" { - return nil, nil, nil, false, ipamapi.ErrInvalidSubPool + return nil, nil, nil, ipamapi.ErrInvalidSubPool } - if pool != "" { - if _, nw, err = net.ParseCIDR(pool); err != nil { - return nil, nil, nil, false, ipamapi.ErrInvalidPool - } - if subPool != "" { - if ipr, err = getAddressRange(subPool, nw); err != nil { - return nil, nil, nil, false, err - } - } - } else { - if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil { - return nil, nil, nil, false, err - } - pdf = true + if pool == "" { + return nil, nil, nil, nil } - return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, pdf, nil + if _, nw, err = net.ParseCIDR(pool); err != nil { + return nil, nil, nil, ipamapi.ErrInvalidPool + } + + if subPool != "" { + if ipr, err = getAddressRange(subPool, nw); err != nil { + return nil, nil, nil, err + } + } + + return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil } func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { @@ -406,7 +413,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) } } - return nil, types.NotFoundErrorf("could not find an available predefined network") + return nil, types.NotFoundErrorf("could not find an available non-overlapping address pool among the defaults to auto assign to the network") } // RequestAddress returns an address from the specified pool ID diff --git a/vendor/src/github.com/docker/libnetwork/netutils/utils_freebsd.go b/vendor/src/github.com/docker/libnetwork/netutils/utils_freebsd.go index f7a7ac75f5..02bcd32aa8 100644 --- a/vendor/src/github.com/docker/libnetwork/netutils/utils_freebsd.go +++ b/vendor/src/github.com/docker/libnetwork/netutils/utils_freebsd.go @@ -7,10 +7,12 @@ import ( ) // ElectInterfaceAddresses looks for an interface on the OS with the specified name -// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, -// it chooses from a predifined list the first IPv4 address which does not conflict -// with other interfaces on the system. -func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { +// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. +// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. +// If the interface does not exist, it chooses from a predefined +// list the first IPv4 address which does not conflict with other +// interfaces on the system. +func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) { return nil, nil, types.NotImplementedErrorf("not supported on freebsd") } diff --git a/vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go b/vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go index 4a03a3a15a..870cc12855 100644 --- a/vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go +++ b/vendor/src/github.com/docker/libnetwork/netutils/utils_linux.go @@ -62,15 +62,15 @@ func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, err } // ElectInterfaceAddresses looks for an interface on the OS with the -// specified name and returns its IPv4 and IPv6 addresses in CIDR -// form. If the interface does not exist, it chooses from a predefined +// specified name and returns returns all its IPv4 and IPv6 addresses in CIDR notation. +// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. +// If the interface does not exist, it chooses from a predefined // list the first IPv4 address which does not conflict with other // interfaces on the system. -func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { +func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) { var ( - v4Net *net.IPNet + v4Nets []*net.IPNet v6Nets []*net.IPNet - err error ) defer osl.InitOSContext()() @@ -85,23 +85,24 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { if err != nil { return nil, nil, err } - if len(v4addr) > 0 { - v4Net = v4addr[0].IPNet + for _, nlAddr := range v4addr { + v4Nets = append(v4Nets, nlAddr.IPNet) } for _, nlAddr := range v6addr { v6Nets = append(v6Nets, nlAddr.IPNet) } } - if link == nil || v4Net == nil { + if link == nil || len(v4Nets) == 0 { // Choose from predefined broad networks - v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) + v4Net, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) if err != nil { return nil, nil, err } + v4Nets = append(v4Nets, v4Net) } - return v4Net, v6Nets, nil + return v4Nets, v6Nets, nil } // FindAvailableNetwork returns a network from the passed list which does not diff --git a/vendor/src/github.com/docker/libnetwork/netutils/utils_solaris.go b/vendor/src/github.com/docker/libnetwork/netutils/utils_solaris.go index 12d453f7ce..dc67101f4b 100644 --- a/vendor/src/github.com/docker/libnetwork/netutils/utils_solaris.go +++ b/vendor/src/github.com/docker/libnetwork/netutils/utils_solaris.go @@ -22,10 +22,12 @@ func CheckRouteOverlaps(toCheck *net.IPNet) error { } // ElectInterfaceAddresses looks for an interface on the OS with the specified name -// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, -// it chooses from a predifined list the first IPv4 address which does not conflict -// with other interfaces on the system. -func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { +// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. +// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. +// If the interface does not exist, it chooses from a predefined +// list the first IPv4 address which does not conflict with other +// interfaces on the system. +func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) { var ( v4Net *net.IPNet ) @@ -63,7 +65,7 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { return nil, nil, err } } - return v4Net, nil, nil + return []*net.IPNet{v4Net}, nil, nil } // FindAvailableNetwork returns a network from the passed list which does not diff --git a/vendor/src/github.com/docker/libnetwork/netutils/utils_windows.go b/vendor/src/github.com/docker/libnetwork/netutils/utils_windows.go index 3b4bb9d909..b6e79c7538 100644 --- a/vendor/src/github.com/docker/libnetwork/netutils/utils_windows.go +++ b/vendor/src/github.com/docker/libnetwork/netutils/utils_windows.go @@ -7,10 +7,12 @@ import ( ) // ElectInterfaceAddresses looks for an interface on the OS with the specified name -// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, -// it chooses from a predifined list the first IPv4 address which does not conflict -// with other interfaces on the system. -func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) { +// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. +// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. +// If the interface does not exist, it chooses from a predefined +// list the first IPv4 address which does not conflict with other +// interfaces on the system. +func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) { return nil, nil, types.NotImplementedErrorf("not supported on windows") } diff --git a/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go b/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go index 562f971af3..1ba1b14b0d 100644 --- a/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go +++ b/vendor/src/github.com/docker/libnetwork/networkdb/cluster.go @@ -16,9 +16,11 @@ import ( ) const ( - reapInterval = 60 * time.Second - reapPeriod = 5 * time.Second - retryInterval = 1 * time.Second + reapInterval = 60 * time.Second + reapPeriod = 5 * time.Second + retryInterval = 1 * time.Second + nodeReapInterval = 24 * time.Hour + nodeReapPeriod = 2 * time.Hour ) type logWriter struct{} @@ -147,6 +149,7 @@ func (nDB *NetworkDB) clusterInit() error { {config.GossipInterval, nDB.gossip}, {config.PushPullInterval, nDB.bulkSyncTables}, {retryInterval, nDB.reconnectNode}, + {nodeReapPeriod, nDB.reapDeadNode}, } { t := time.NewTicker(trigger.interval) go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) @@ -234,6 +237,19 @@ func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, sto } } +func (nDB *NetworkDB) reapDeadNode() { + nDB.Lock() + defer nDB.Unlock() + for id, n := range nDB.failedNodes { + if n.reapTime > 0 { + n.reapTime -= reapPeriod + continue + } + logrus.Debugf("Removing failed node %v from gossip cluster", n.Name) + delete(nDB.failedNodes, id) + } +} + func (nDB *NetworkDB) reconnectNode() { nDB.RLock() if len(nDB.failedNodes) == 0 { diff --git a/vendor/src/github.com/docker/libnetwork/networkdb/event_delegate.go b/vendor/src/github.com/docker/libnetwork/networkdb/event_delegate.go index 019cafbd06..c22d09eba3 100644 --- a/vendor/src/github.com/docker/libnetwork/networkdb/event_delegate.go +++ b/vendor/src/github.com/docker/libnetwork/networkdb/event_delegate.go @@ -29,6 +29,8 @@ func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) { e.nDB.Lock() if n, ok := e.nDB.nodes[mn.Name]; ok { delete(e.nDB.nodes, mn.Name) + + n.reapTime = reapInterval e.nDB.failedNodes[mn.Name] = n } e.nDB.Unlock() diff --git a/vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go b/vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go index 69fc4fe249..a79b4231d2 100644 --- a/vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go +++ b/vendor/src/github.com/docker/libnetwork/networkdb/networkdb.go @@ -94,6 +94,8 @@ type NetworkDB struct { type node struct { memberlist.Node ltime serf.LamportTime + // Number of hours left before the reaper removes the node + reapTime time.Duration } // network describes the node/network attachment.