Merge pull request #35791 from corbin-coleman/libnetwork_vendoring

[AUTOMATED] libnetwork Vendoring
This commit is contained in:
Yong Tang 2017-12-26 00:17:26 -06:00 committed by GitHub
commit 4a804016ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 198 additions and 120 deletions

View file

@ -30,7 +30,7 @@ github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8
github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2
#get libnetwork packages #get libnetwork packages
github.com/docker/libnetwork 9bca9a4a220b158cc94402e0f8c2c7714eb6f503 github.com/docker/libnetwork 26531e56a76d7334e594098d7cfab88285d9065c
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec

View file

@ -91,7 +91,7 @@ func (s *Server) EnableDebug(ip string, port int) {
} }
logrus.Infof("Starting the diagnose server listening on %d for commands", port) logrus.Infof("Starting the diagnose server listening on %d for commands", port)
srv := &http.Server{Addr: fmt.Sprintf("127.0.0.1:%d", port), Handler: s} srv := &http.Server{Addr: fmt.Sprintf("%s:%d", ip, port), Handler: s}
s.srv = srv s.srv = srv
s.enable = 1 s.enable = 1
go func(n *Server) { go func(n *Server) {
@ -101,7 +101,6 @@ func (s *Server) EnableDebug(ip string, port int) {
atomic.SwapInt32(&n.enable, 0) atomic.SwapInt32(&n.enable, 0)
} }
}(s) }(s)
} }
// DisableDebug stop the dubug and closes the tcp socket // DisableDebug stop the dubug and closes the tcp socket

View file

@ -39,4 +39,7 @@ const (
// DisableDNS label // DisableDNS label
DisableDNS = "com.docker.network.windowsshim.disable_dns" DisableDNS = "com.docker.network.windowsshim.disable_dns"
// DisableGatewayDNS label
DisableGatewayDNS = "com.docker.network.windowsshim.disable_gatewaydns"
) )

View file

@ -44,6 +44,7 @@ type networkConfiguration struct {
NetworkAdapterName string NetworkAdapterName string
dbIndex uint64 dbIndex uint64
dbExists bool dbExists bool
DisableGatewayDNS bool
} }
// endpointConfiguration represents the user specified configuration for the sandbox endpoint // endpointConfiguration represents the user specified configuration for the sandbox endpoint
@ -177,6 +178,12 @@ func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string
config.DNSSuffix = value config.DNSSuffix = value
case DNSServers: case DNSServers:
config.DNSServers = value config.DNSServers = value
case DisableGatewayDNS:
b, err := strconv.ParseBool(value)
if err != nil {
return nil, err
}
config.DisableGatewayDNS = b
case MacPool: case MacPool:
config.MacPools = make([]hcsshim.MacPool, 0) config.MacPools = make([]hcsshim.MacPool, 0)
s := strings.Split(value, ",") s := strings.Split(value, ",")
@ -589,7 +596,14 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",") endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
// overwrite the ep DisableDNS option if DisableGatewayDNS was set to true during the network creation option
if n.config.DisableGatewayDNS {
logrus.Debugf("n.config.DisableGatewayDNS[%v] overwrites epOption.DisableDNS[%v]", n.config.DisableGatewayDNS, epOption.DisableDNS)
epOption.DisableDNS = n.config.DisableGatewayDNS
}
if n.driver.name == "nat" && !epOption.DisableDNS { if n.driver.name == "nat" && !epOption.DisableDNS {
logrus.Debugf("endpointStruct.EnableInternalDNS =[%v]", endpointStruct.EnableInternalDNS)
endpointStruct.EnableInternalDNS = true endpointStruct.EnableInternalDNS = true
} }

View file

@ -64,7 +64,7 @@ func (d *driver) populateNetworks() error {
if err = d.createNetwork(ncfg); err != nil { if err = d.createNetwork(ncfg); err != nil {
logrus.Warnf("could not create windows network for id %s hnsid %s while booting up from persistent state: %v", ncfg.ID, ncfg.HnsID, err) logrus.Warnf("could not create windows network for id %s hnsid %s while booting up from persistent state: %v", ncfg.ID, ncfg.HnsID, err)
} }
logrus.Debugf("Network (%s) restored", ncfg.ID[0:7]) logrus.Debugf("Network %v (%s) restored", d.name, ncfg.ID[0:7])
} }
return nil return nil

View file

@ -5,7 +5,6 @@ import (
"github.com/docker/libnetwork/discoverapi" "github.com/docker/libnetwork/discoverapi"
"github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/ipamapi"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/types" "github.com/docker/libnetwork/types"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -75,15 +74,11 @@ func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s
return nil, nil, err return nil, nil, err
} }
// TODO Windows: Remove this once the bug in docker daemon is fixed
// that causes it to throw an exception on nil gateway
if prefAddress != nil { if prefAddress != nil {
return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil
} else if opts[ipamapi.RequestAddressType] == netlabel.Gateway {
return ipNet, nil, nil
} else {
return nil, nil, nil
} }
return nil, nil, nil
} }
// ReleaseAddress releases the address - always succeeds // ReleaseAddress releases the address - always succeeds

View file

@ -1156,6 +1156,18 @@ func (n *network) createEndpoint(name string, options ...EndpointOption) (Endpoi
ep.releaseAddress() ep.releaseAddress()
} }
}() }()
// Moving updateToSTore before calling addEndpoint so that we shall clean up VETH interfaces in case
// DockerD get killed between addEndpoint and updateSTore call
if err = n.getController().updateToStore(ep); err != nil {
return nil, err
}
defer func() {
if err != nil {
if e := n.getController().deleteFromStore(ep); e != nil {
logrus.Warnf("error rolling back endpoint %s from store: %v", name, e)
}
}
}()
if err = n.addEndpoint(ep); err != nil { if err = n.addEndpoint(ep); err != nil {
return nil, err return nil, err
@ -1172,17 +1184,6 @@ func (n *network) createEndpoint(name string, options ...EndpointOption) (Endpoi
return nil, err return nil, err
} }
if err = n.getController().updateToStore(ep); err != nil {
return nil, err
}
defer func() {
if err != nil {
if e := n.getController().deleteFromStore(ep); e != nil {
logrus.Warnf("error rolling back endpoint %s from store: %v", name, e)
}
}
}()
// Watch for service records // Watch for service records
n.getController().watchSvcRecord(ep) n.getController().watchSvcRecord(ep)
defer func() { defer func() {

View file

@ -28,6 +28,9 @@ func executeInCompartment(compartmentID uint32, x func()) {
} }
func (n *network) startResolver() { func (n *network) startResolver() {
if n.networkType == "ics" {
return
}
n.resolverOnce.Do(func() { n.resolverOnce.Do(func() {
logrus.Debugf("Launching DNS server for network %q", n.Name()) logrus.Debugf("Launching DNS server for network %q", n.Name())
options := n.Info().DriverOptions() options := n.Info().DriverOptions()

View file

@ -16,46 +16,28 @@ func (d *delegate) NodeMeta(limit int) []byte {
return []byte{} return []byte{}
} }
// getNode searches the node inside the tables
// returns true if the node was respectively in the active list, explicit node leave list or failed list
func (nDB *NetworkDB) getNode(nEvent *NodeEvent, extract bool) (bool, bool, bool, *node) {
var active bool
var left bool
var failed bool
for _, nodes := range []map[string]*node{
nDB.failedNodes,
nDB.leftNodes,
nDB.nodes,
} {
if n, ok := nodes[nEvent.NodeName]; ok {
active = &nodes == &nDB.nodes
left = &nodes == &nDB.leftNodes
failed = &nodes == &nDB.failedNodes
if n.ltime >= nEvent.LTime {
return active, left, failed, nil
}
if extract {
delete(nodes, n.Name)
}
return active, left, failed, n
}
}
return active, left, failed, nil
}
func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool { func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool {
// Update our local clock if the received messages has newer // Update our local clock if the received messages has newer
// time. // time.
nDB.networkClock.Witness(nEvent.LTime) nDB.networkClock.Witness(nEvent.LTime)
nDB.RLock() nDB.RLock()
active, left, _, n := nDB.getNode(nEvent, false) defer nDB.RUnlock()
// check if the node exists
n, _, _ := nDB.findNode(nEvent.NodeName)
if n == nil { if n == nil {
nDB.RUnlock()
return false return false
} }
nDB.RUnlock()
// check if the event is fresh
if n.ltime >= nEvent.LTime {
return false
}
// If we are here means that the event is fresher and the node is known. Update the laport time
n.ltime = nEvent.LTime
// If it is a node leave event for a manager and this is the only manager we // If it is a node leave event for a manager and this is the only manager we
// know of we want the reconnect logic to kick in. In a single manager // know of we want the reconnect logic to kick in. In a single manager
// cluster manager's gossip can't be bootstrapped unless some other node // cluster manager's gossip can't be bootstrapped unless some other node
@ -63,45 +45,32 @@ func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool {
if len(nDB.bootStrapIP) == 1 && nEvent.Type == NodeEventTypeLeave { if len(nDB.bootStrapIP) == 1 && nEvent.Type == NodeEventTypeLeave {
for _, ip := range nDB.bootStrapIP { for _, ip := range nDB.bootStrapIP {
if ip.Equal(n.Addr) { if ip.Equal(n.Addr) {
n.ltime = nEvent.LTime
return true return true
} }
} }
} }
n.ltime = nEvent.LTime
switch nEvent.Type { switch nEvent.Type {
case NodeEventTypeJoin: case NodeEventTypeJoin:
if active { moved, err := nDB.changeNodeState(n.Name, nodeActiveState)
// the node is already marked as active nothing to do if err != nil {
logrus.WithError(err).Error("unable to find the node to move")
return false return false
} }
nDB.Lock() if moved {
// Because the lock got released on the previous check we have to do it again and re verify the status of the node
// All of this is to avoid a big lock on the function
if active, _, _, n = nDB.getNode(nEvent, true); !active && n != nil {
n.reapTime = 0
nDB.nodes[n.Name] = n
logrus.Infof("%v(%v): Node join event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr) logrus.Infof("%v(%v): Node join event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr)
} }
nDB.Unlock() return moved
return true
case NodeEventTypeLeave: case NodeEventTypeLeave:
if left { moved, err := nDB.changeNodeState(n.Name, nodeLeftState)
// the node is already marked as left nothing to do. if err != nil {
logrus.WithError(err).Error("unable to find the node to move")
return false return false
} }
nDB.Lock() if moved {
// Because the lock got released on the previous check we have to do it again and re verify the status of the node
// All of this is to avoid a big lock on the function
if _, left, _, n = nDB.getNode(nEvent, true); !left && n != nil {
n.reapTime = nodeReapInterval
nDB.leftNodes[n.Name] = n
logrus.Infof("%v(%v): Node leave event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr) logrus.Infof("%v(%v): Node leave event for %s/%s", nDB.config.Hostname, nDB.config.NodeID, n.Name, n.Addr)
} }
nDB.Unlock() return moved
return true
} }
return false return false

View file

@ -21,24 +21,6 @@ func (e *eventDelegate) broadcastNodeEvent(addr net.IP, op opType) {
} }
} }
func (e *eventDelegate) purgeReincarnation(mn *memberlist.Node) {
for name, node := range e.nDB.failedNodes {
if node.Addr.Equal(mn.Addr) {
logrus.Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", mn.Name, mn.Addr, name, node.Addr)
delete(e.nDB.failedNodes, name)
return
}
}
for name, node := range e.nDB.leftNodes {
if node.Addr.Equal(mn.Addr) {
logrus.Infof("Node %s/%s, is the new incarnation of the shutdown node %s/%s", mn.Name, mn.Addr, name, node.Addr)
delete(e.nDB.leftNodes, name)
return
}
}
}
func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) { func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) {
logrus.Infof("Node %s/%s, joined gossip cluster", mn.Name, mn.Addr) logrus.Infof("Node %s/%s, joined gossip cluster", mn.Name, mn.Addr)
e.broadcastNodeEvent(mn.Addr, opCreate) e.broadcastNodeEvent(mn.Addr, opCreate)
@ -57,44 +39,35 @@ func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) {
// Every node has a unique ID // Every node has a unique ID
// Check on the base of the IP address if the new node that joined is actually a new incarnation of a previous // Check on the base of the IP address if the new node that joined is actually a new incarnation of a previous
// failed or shutdown one // failed or shutdown one
e.purgeReincarnation(mn) e.nDB.purgeReincarnation(mn)
e.nDB.nodes[mn.Name] = &node{Node: *mn} e.nDB.nodes[mn.Name] = &node{Node: *mn}
logrus.Infof("Node %s/%s, added to nodes list", mn.Name, mn.Addr) logrus.Infof("Node %s/%s, added to nodes list", mn.Name, mn.Addr)
} }
func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) { func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) {
var failed bool
logrus.Infof("Node %s/%s, left gossip cluster", mn.Name, mn.Addr) logrus.Infof("Node %s/%s, left gossip cluster", mn.Name, mn.Addr)
e.broadcastNodeEvent(mn.Addr, opDelete) e.broadcastNodeEvent(mn.Addr, opDelete)
// The node left or failed, delete all the entries created by it.
// If the node was temporary down, deleting the entries will guarantee that the CREATE events will be accepted
// If the node instead left because was going down, then it makes sense to just delete all its state
e.nDB.Lock() e.nDB.Lock()
defer e.nDB.Unlock() defer e.nDB.Unlock()
e.nDB.deleteNodeFromNetworks(mn.Name)
e.nDB.deleteNodeTableEntries(mn.Name)
if n, ok := e.nDB.nodes[mn.Name]; ok {
delete(e.nDB.nodes, mn.Name)
// Check if a new incarnation of the same node already joined n, currState, _ := e.nDB.findNode(mn.Name)
// In that case this node can simply be removed and no further action are needed if n == nil {
for name, node := range e.nDB.nodes { logrus.Errorf("Node %s/%s not found in the node lists", mn.Name, mn.Addr)
if node.Addr.Equal(mn.Addr) { return
logrus.Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", name, node.Addr, mn.Name, mn.Addr)
return
}
}
// In case of node failure, keep retrying to reconnect every retryInterval (1sec) for nodeReapInterval (24h)
// Explicit leave will have already removed the node from the list of nodes (nDB.nodes) and put it into the leftNodes map
n.reapTime = nodeReapInterval
e.nDB.failedNodes[mn.Name] = n
failed = true
} }
// if the node was active means that did not send the leave cluster message, so it's probable that
if failed { // failed. Else would be already in the left list so nothing else has to be done
logrus.Infof("Node %s/%s, added to failed nodes list", mn.Name, mn.Addr) if currState == nodeActiveState {
moved, err := e.nDB.changeNodeState(mn.Name, nodeFailedState)
if err != nil {
logrus.WithError(err).Errorf("impossible condition, node %s/%s not present in the list", mn.Name, mn.Addr)
return
}
if moved {
logrus.Infof("Node %s/%s, added to failed nodes list", mn.Name, mn.Addr)
}
} }
} }

View file

@ -399,6 +399,7 @@ func dbGetTable(ctx interface{}, w http.ResponseWriter, r *http.Request) {
Value: encodedValue, Value: encodedValue,
Owner: v.owner, Owner: v.owner,
}) })
i++
} }
log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done") log.WithField("response", fmt.Sprintf("%+v", rsp)).Info("get table done")
diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json) diagnose.HTTPReply(w, diagnose.CommandSucceed(rsp), json)

View file

@ -0,0 +1,120 @@
package networkdb
import (
"fmt"
"github.com/hashicorp/memberlist"
"github.com/sirupsen/logrus"
)
type nodeState int
const (
nodeNotFound nodeState = -1
nodeActiveState nodeState = 0
nodeLeftState nodeState = 1
nodeFailedState nodeState = 2
)
var nodeStateName = map[nodeState]string{
-1: "NodeNotFound",
0: "NodeActive",
1: "NodeLeft",
2: "NodeFailed",
}
// findNode search the node into the 3 node lists and returns the node pointer and the list
// where it got found
func (nDB *NetworkDB) findNode(nodeName string) (*node, nodeState, map[string]*node) {
for i, nodes := range []map[string]*node{
nDB.nodes,
nDB.leftNodes,
nDB.failedNodes,
} {
if n, ok := nodes[nodeName]; ok {
return n, nodeState(i), nodes
}
}
return nil, nodeNotFound, nil
}
// changeNodeState changes the state of the node specified, returns true if the node was moved,
// false if there was no need to change the node state. Error will be returned if the node does not
// exists
func (nDB *NetworkDB) changeNodeState(nodeName string, newState nodeState) (bool, error) {
n, currState, m := nDB.findNode(nodeName)
if n == nil {
return false, fmt.Errorf("node %s not found", nodeName)
}
switch newState {
case nodeActiveState:
if currState == nodeActiveState {
return false, nil
}
delete(m, nodeName)
// reset the node reap time
n.reapTime = 0
nDB.nodes[nodeName] = n
case nodeLeftState:
if currState == nodeLeftState {
return false, nil
}
delete(m, nodeName)
nDB.leftNodes[nodeName] = n
case nodeFailedState:
if currState == nodeFailedState {
return false, nil
}
delete(m, nodeName)
nDB.failedNodes[nodeName] = n
}
logrus.Infof("Node %s change state %s --> %s", nodeName, nodeStateName[currState], nodeStateName[newState])
if newState == nodeLeftState || newState == nodeFailedState {
// set the node reap time, if not already set
// It is possible that a node passes from failed to left and the reaptime was already set so keep that value
if n.reapTime == 0 {
n.reapTime = nodeReapInterval
}
// The node leave or fails, delete all the entries created by it.
// If the node was temporary down, deleting the entries will guarantee that the CREATE events will be accepted
// If the node instead left because was going down, then it makes sense to just delete all its state
nDB.deleteNodeFromNetworks(n.Name)
nDB.deleteNodeTableEntries(n.Name)
}
return true, nil
}
func (nDB *NetworkDB) purgeReincarnation(mn *memberlist.Node) bool {
for name, node := range nDB.nodes {
if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
logrus.Infof("Node %s/%s, is the new incarnation of the active node %s/%s", mn.Name, mn.Addr, name, node.Addr)
nDB.changeNodeState(name, nodeLeftState)
return true
}
}
for name, node := range nDB.failedNodes {
if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
logrus.Infof("Node %s/%s, is the new incarnation of the failed node %s/%s", mn.Name, mn.Addr, name, node.Addr)
nDB.changeNodeState(name, nodeLeftState)
return true
}
}
for name, node := range nDB.leftNodes {
if node.Addr.Equal(mn.Addr) && node.Port == mn.Port && mn.Name != name {
logrus.Infof("Node %s/%s, is the new incarnation of the shutdown node %s/%s", mn.Name, mn.Addr, name, node.Addr)
nDB.changeNodeState(name, nodeLeftState)
return true
}
}
return false
}