diff --git a/components/engine/vendor.conf b/components/engine/vendor.conf index f0cedfc22b1..d896c86e843 100644 --- a/components/engine/vendor.conf +++ b/components/engine/vendor.conf @@ -26,7 +26,7 @@ github.com/imdario/mergo 0.2.1 golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 #get libnetwork packages -github.com/docker/libnetwork 83e1e49475b88a9f1f8ba89a690a7d5de42e24b9 +github.com/docker/libnetwork 869489614e849bffe28297c619a68fb8e26ddbf1 github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec diff --git a/components/engine/vendor/github.com/docker/libnetwork/controller.go b/components/engine/vendor/github.com/docker/libnetwork/controller.go index df75be707fd..ae7dac0b828 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/controller.go +++ b/components/engine/vendor/github.com/docker/libnetwork/controller.go @@ -738,7 +738,6 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... if network.configOnly { network.scope = datastore.LocalScope network.networkType = "null" - network.ipamType = "" goto addToStore } diff --git a/components/engine/vendor/github.com/docker/libnetwork/network.go b/components/engine/vendor/github.com/docker/libnetwork/network.go index 2b6c705a7ba..fa2ab800ae3 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/network.go +++ b/components/engine/vendor/github.com/docker/libnetwork/network.go @@ -412,6 +412,9 @@ func (n *network) applyConfigurationTo(to *network) error { } } } + if len(n.ipamType) != 0 { + to.ipamType = n.ipamType + } if len(n.ipamOptions) > 0 { to.ipamOptions = make(map[string]string, len(n.ipamOptions)) for k, v := range n.ipamOptions { diff --git a/components/engine/vendor/github.com/docker/libnetwork/networkdb/cluster.go b/components/engine/vendor/github.com/docker/libnetwork/networkdb/cluster.go index d448c8caef9..9156d0da68b 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/networkdb/cluster.go +++ b/components/engine/vendor/github.com/docker/libnetwork/networkdb/cluster.go @@ -284,7 +284,6 @@ func (nDB *NetworkDB) reconnectNode() { } if err := nDB.sendNodeEvent(NodeEventTypeJoin); err != nil { - logrus.Errorf("failed to send node join during reconnect: %v", err) return } diff --git a/components/engine/vendor/github.com/docker/libnetwork/networkdb/delegate.go b/components/engine/vendor/github.com/docker/libnetwork/networkdb/delegate.go index 2096ea622ee..6df358382ff 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/networkdb/delegate.go +++ b/components/engine/vendor/github.com/docker/libnetwork/networkdb/delegate.go @@ -17,6 +17,25 @@ func (d *delegate) NodeMeta(limit int) []byte { return []byte{} } +func (nDB *NetworkDB) getNode(nEvent *NodeEvent) *node { + nDB.Lock() + defer nDB.Unlock() + + for _, nodes := range []map[string]*node{ + nDB.failedNodes, + nDB.leftNodes, + nDB.nodes, + } { + if n, ok := nodes[nEvent.NodeName]; ok { + if n.ltime >= nEvent.LTime { + return nil + } + return n + } + } + return nil +} + func (nDB *NetworkDB) checkAndGetNode(nEvent *NodeEvent) *node { nDB.Lock() defer nDB.Unlock() @@ -63,10 +82,28 @@ func (nDB *NetworkDB) purgeSameNode(n *node) { } func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool { - n := nDB.checkAndGetNode(nEvent) + // Update our local clock if the received messages has newer + // time. + nDB.networkClock.Witness(nEvent.LTime) + + n := nDB.getNode(nEvent) if n == nil { return false } + // If its 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 + // cluster manager's gossip can't be bootstrapped unless some other node + // connects to it. + if len(nDB.bootStrapIP) == 1 && nEvent.Type == NodeEventTypeLeave { + for _, ip := range nDB.bootStrapIP { + if ip.Equal(n.Addr) { + n.ltime = nEvent.LTime + return true + } + } + } + + n = nDB.checkAndGetNode(nEvent) nDB.purgeSameNode(n) n.ltime = nEvent.LTime @@ -76,11 +113,13 @@ func (nDB *NetworkDB) handleNodeEvent(nEvent *NodeEvent) bool { nDB.Lock() nDB.nodes[n.Name] = n nDB.Unlock() + logrus.Infof("Node join event for %s/%s", n.Name, n.Addr) return true case NodeEventTypeLeave: nDB.Lock() nDB.leftNodes[n.Name] = n nDB.Unlock() + logrus.Infof("Node leave event for %s/%s", n.Name, n.Addr) return true } diff --git a/components/engine/vendor/github.com/docker/libnetwork/networkdb/event_delegate.go b/components/engine/vendor/github.com/docker/libnetwork/networkdb/event_delegate.go index 6ae0a32ad11..23e16832e70 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/networkdb/event_delegate.go +++ b/components/engine/vendor/github.com/docker/libnetwork/networkdb/event_delegate.go @@ -22,6 +22,7 @@ func (e *eventDelegate) broadcastNodeEvent(addr net.IP, op opType) { } func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) { + logrus.Infof("Node %s/%s, joined gossip cluster", mn.Name, mn.Addr) e.broadcastNodeEvent(mn.Addr, opCreate) e.nDB.Lock() // In case the node is rejoining after a failure or leave, @@ -37,9 +38,12 @@ func (e *eventDelegate) NotifyJoin(mn *memberlist.Node) { e.nDB.nodes[mn.Name] = &node{Node: *mn} e.nDB.Unlock() + logrus.Infof("Node %s/%s, added to nodes list", mn.Name, mn.Addr) } func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) { + var failed bool + logrus.Infof("Node %s/%s, left gossip cluster", mn.Name, mn.Addr) e.broadcastNodeEvent(mn.Addr, opDelete) e.nDB.deleteNodeTableEntries(mn.Name) e.nDB.deleteNetworkEntriesForNode(mn.Name) @@ -47,10 +51,17 @@ func (e *eventDelegate) NotifyLeave(mn *memberlist.Node) { if n, ok := e.nDB.nodes[mn.Name]; ok { delete(e.nDB.nodes, mn.Name) - n.reapTime = reapInterval + // 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 } e.nDB.Unlock() + if failed { + logrus.Infof("Node %s/%s, added to failed nodes list", mn.Name, mn.Addr) + } + } func (e *eventDelegate) NotifyUpdate(n *memberlist.Node) { diff --git a/components/engine/vendor/github.com/docker/libnetwork/networkdb/networkdb.go b/components/engine/vendor/github.com/docker/libnetwork/networkdb/networkdb.go index 86b0128b600..ecb2d714a40 100644 --- a/components/engine/vendor/github.com/docker/libnetwork/networkdb/networkdb.go +++ b/components/engine/vendor/github.com/docker/libnetwork/networkdb/networkdb.go @@ -4,6 +4,7 @@ package networkdb import ( "fmt" + "net" "strings" "sync" "time" @@ -88,6 +89,10 @@ type NetworkDB struct { // Reference to the memberlist's keyring to add & remove keys keyring *memberlist.Keyring + + // bootStrapIP is the list of IPs that can be used to bootstrap + // the gossip. + bootStrapIP []net.IP } // PeerInfo represents the peer (gossip cluster) nodes of a network @@ -194,6 +199,11 @@ func New(c *Config) (*NetworkDB, error) { // Join joins this NetworkDB instance with a list of peer NetworkDB // instances passed by the caller in the form of addr:port func (nDB *NetworkDB) Join(members []string) error { + nDB.Lock() + for _, m := range members { + nDB.bootStrapIP = append(nDB.bootStrapIP, net.ParseIP(m)) + } + nDB.Unlock() return nDB.clusterJoin(members) }