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:
Yong Tang 2016-10-26 13:37:46 -07:00
parent e9c4c513d1
commit fc62ad6b95
18 changed files with 193 additions and 66 deletions

View File

@ -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

View File

@ -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())
}

View File

@ -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()

View File

@ -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 {

View File

@ -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 {

View File

@ -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{}

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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)
}

View File

@ -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

View File

@ -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")
}

View File

@ -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

View File

@ -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

View File

@ -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")
}

View File

@ -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 {

View File

@ -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()

View File

@ -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.