зеркало из https://github.com/microsoft/docker.git
Vendor libnetwork to f4338b6f1085ccfe5972e655cca8a1d15d73439d
This fix updates libnetwork to f4338b6f1085ccfe5972e655cca8a1d15d73439d. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Родитель
e9c4c513d1
Коммит
fc62ad6b95
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче