2015-05-31 18:49:11 +00:00
|
|
|
package libnetwork
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-02-02 22:45:38 +00:00
|
|
|
"strings"
|
2015-05-31 18:49:11 +00:00
|
|
|
|
2016-02-26 18:05:47 +00:00
|
|
|
"github.com/docker/libkv/store/boltdb"
|
|
|
|
"github.com/docker/libkv/store/consul"
|
|
|
|
"github.com/docker/libkv/store/etcd"
|
|
|
|
"github.com/docker/libkv/store/zookeeper"
|
2015-05-31 18:49:11 +00:00
|
|
|
"github.com/docker/libnetwork/datastore"
|
2017-07-26 21:18:31 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2015-05-31 18:49:11 +00:00
|
|
|
)
|
|
|
|
|
2016-02-26 18:05:47 +00:00
|
|
|
func registerKVStores() {
|
|
|
|
consul.Register()
|
|
|
|
zookeeper.Register()
|
|
|
|
etcd.Register()
|
|
|
|
boltdb.Register()
|
|
|
|
}
|
|
|
|
|
2016-03-25 08:10:03 +00:00
|
|
|
func (c *controller) initScopedStore(scope string, scfg *datastore.ScopeCfg) error {
|
|
|
|
store, err := datastore.NewDataStore(scope, scfg)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.Lock()
|
|
|
|
c.stores = append(c.stores, store)
|
|
|
|
c.Unlock()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) initStores() error {
|
2016-02-26 18:05:47 +00:00
|
|
|
registerKVStores()
|
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
if c.cfg == nil {
|
|
|
|
c.Unlock()
|
|
|
|
return nil
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
scopeConfigs := c.cfg.Scopes
|
2016-02-16 23:19:18 +00:00
|
|
|
c.stores = nil
|
2015-10-05 11:21:15 +00:00
|
|
|
c.Unlock()
|
2015-05-31 18:49:11 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
for scope, scfg := range scopeConfigs {
|
2016-03-25 08:10:03 +00:00
|
|
|
if err := c.initScopedStore(scope, scfg); err != nil {
|
2015-10-05 11:21:15 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
c.startWatch()
|
2015-09-22 20:20:55 +00:00
|
|
|
return nil
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) closeStores() {
|
|
|
|
for _, store := range c.getStores() {
|
|
|
|
store.Close()
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
2015-09-22 20:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) getStore(scope string) datastore.DataStore {
|
2015-09-22 20:20:55 +00:00
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
defer c.Unlock()
|
|
|
|
|
|
|
|
for _, store := range c.stores {
|
|
|
|
if store.Scope() == scope {
|
|
|
|
return store
|
|
|
|
}
|
2015-09-22 20:20:55 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
return nil
|
2015-09-22 20:20:55 +00:00
|
|
|
}
|
2015-09-16 11:39:46 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) getStores() []datastore.DataStore {
|
2015-09-22 20:20:55 +00:00
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
defer c.Unlock()
|
|
|
|
|
|
|
|
return c.stores
|
2015-09-22 20:20:55 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) getNetworkFromStore(nid string) (*network, error) {
|
|
|
|
for _, store := range c.getStores() {
|
|
|
|
n := &network{id: nid, ctrlr: c}
|
|
|
|
err := store.GetObject(datastore.Key(n.Key()...), n)
|
|
|
|
// Continue searching in the next store if the key is not found in this store
|
2015-10-20 22:37:22 +00:00
|
|
|
if err != nil {
|
|
|
|
if err != datastore.ErrKeyNotFound {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Debugf("could not find network %s: %v", nid, err)
|
2015-10-20 22:37:22 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-10-12 05:28:26 +00:00
|
|
|
ec := &endpointCnt{n: n}
|
|
|
|
err = store.GetObject(datastore.Key(ec.Key()...), ec)
|
2016-03-05 10:00:31 +00:00
|
|
|
if err != nil && !n.inDelete {
|
2015-10-12 05:28:26 +00:00
|
|
|
return nil, fmt.Errorf("could not find endpoint count for network %s: %v", n.Name(), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
n.epCnt = ec
|
2017-05-15 18:48:05 +00:00
|
|
|
if n.scope == "" {
|
|
|
|
n.scope = store.Scope()
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
return n, nil
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
return nil, fmt.Errorf("network %s not found", nid)
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
|
|
|
|
2015-10-19 20:20:23 +00:00
|
|
|
func (c *controller) getNetworksForScope(scope string) ([]*network, error) {
|
|
|
|
var nl []*network
|
|
|
|
|
|
|
|
store := c.getStore(scope)
|
|
|
|
if store == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix),
|
|
|
|
&network{ctrlr: c})
|
|
|
|
if err != nil && err != datastore.ErrKeyNotFound {
|
|
|
|
return nil, fmt.Errorf("failed to get networks for scope %s: %v",
|
|
|
|
scope, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, kvo := range kvol {
|
|
|
|
n := kvo.(*network)
|
|
|
|
n.ctrlr = c
|
|
|
|
|
|
|
|
ec := &endpointCnt{n: n}
|
|
|
|
err = store.GetObject(datastore.Key(ec.Key()...), ec)
|
2016-03-05 10:00:31 +00:00
|
|
|
if err != nil && !n.inDelete {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Warnf("Could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
2016-02-10 01:00:31 +00:00
|
|
|
continue
|
2015-10-19 20:20:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
n.epCnt = ec
|
2017-05-15 18:48:05 +00:00
|
|
|
if n.scope == "" {
|
|
|
|
n.scope = scope
|
|
|
|
}
|
2015-10-19 20:20:23 +00:00
|
|
|
nl = append(nl, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nl, nil
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) getNetworksFromStore() ([]*network, error) {
|
|
|
|
var nl []*network
|
|
|
|
|
|
|
|
for _, store := range c.getStores() {
|
|
|
|
kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix),
|
|
|
|
&network{ctrlr: c})
|
|
|
|
// Continue searching in the next store if no keys found in this store
|
2015-10-20 22:37:22 +00:00
|
|
|
if err != nil {
|
|
|
|
if err != datastore.ErrKeyNotFound {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Debugf("failed to get networks for scope %s: %v", store.Scope(), err)
|
2015-10-20 22:37:22 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-02-02 22:45:38 +00:00
|
|
|
kvep, err := store.Map(datastore.Key(epCntKeyPrefix), &endpointCnt{})
|
|
|
|
if err != nil {
|
|
|
|
if err != datastore.ErrKeyNotFound {
|
|
|
|
logrus.Warnf("failed to get endpoint_count map for scope %s: %v", store.Scope(), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
for _, kvo := range kvol {
|
|
|
|
n := kvo.(*network)
|
2016-01-08 21:31:17 +00:00
|
|
|
n.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
n.ctrlr = c
|
2015-10-12 05:28:26 +00:00
|
|
|
ec := &endpointCnt{n: n}
|
2017-02-02 22:45:38 +00:00
|
|
|
// Trim the leading & trailing "/" to make it consistent across all stores
|
|
|
|
if val, ok := kvep[strings.Trim(datastore.Key(ec.Key()...), "/")]; ok {
|
|
|
|
ec = val.(*endpointCnt)
|
|
|
|
ec.n = n
|
|
|
|
n.epCnt = ec
|
2015-10-12 05:28:26 +00:00
|
|
|
}
|
2017-05-15 18:48:05 +00:00
|
|
|
if n.scope == "" {
|
|
|
|
n.scope = store.Scope()
|
|
|
|
}
|
2016-01-29 18:29:18 +00:00
|
|
|
n.Unlock()
|
2015-10-05 11:21:15 +00:00
|
|
|
nl = append(nl, n)
|
|
|
|
}
|
2015-09-16 11:42:35 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
return nl, nil
|
2015-06-18 15:18:17 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (n *network) getEndpointFromStore(eid string) (*endpoint, error) {
|
2016-01-17 20:43:41 +00:00
|
|
|
var errors []string
|
|
|
|
for _, store := range n.ctrlr.getStores() {
|
|
|
|
ep := &endpoint{id: eid, network: n}
|
|
|
|
err := store.GetObject(datastore.Key(ep.Key()...), ep)
|
|
|
|
// Continue searching in the next store if the key is not found in this store
|
|
|
|
if err != nil {
|
|
|
|
if err != datastore.ErrKeyNotFound {
|
|
|
|
errors = append(errors, fmt.Sprintf("{%s:%v}, ", store.Scope(), err))
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Debugf("could not find endpoint %s in %s: %v", eid, store.Scope(), err)
|
2016-01-17 20:43:41 +00:00
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return ep, nil
|
2015-10-20 22:37:22 +00:00
|
|
|
}
|
2016-01-17 20:43:41 +00:00
|
|
|
return nil, fmt.Errorf("could not find endpoint %s: %v", eid, errors)
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (n *network) getEndpointsFromStore() ([]*endpoint, error) {
|
|
|
|
var epl []*endpoint
|
2015-06-01 04:19:10 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
tmp := endpoint{network: n}
|
|
|
|
for _, store := range n.getController().getStores() {
|
|
|
|
kvol, err := store.List(datastore.Key(tmp.KeyPrefix()...), &endpoint{network: n})
|
|
|
|
// Continue searching in the next store if no keys found in this store
|
2015-10-20 22:37:22 +00:00
|
|
|
if err != nil {
|
|
|
|
if err != datastore.ErrKeyNotFound {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Debugf("failed to get endpoints for network %s scope %s: %v",
|
2015-10-20 22:37:22 +00:00
|
|
|
n.Name(), store.Scope(), err)
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, kvo := range kvol {
|
|
|
|
ep := kvo.(*endpoint)
|
|
|
|
epl = append(epl, ep)
|
2015-06-05 20:31:12 +00:00
|
|
|
}
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
return epl, nil
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) updateToStore(kvObject datastore.KVObject) error {
|
|
|
|
cs := c.getStore(kvObject.DataScope())
|
2015-05-31 18:49:11 +00:00
|
|
|
if cs == nil {
|
2017-04-05 05:37:58 +00:00
|
|
|
return ErrDataStoreNotInitialized(kvObject.DataScope())
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
if err := cs.PutObjectAtomic(kvObject); err != nil {
|
2015-10-10 02:31:44 +00:00
|
|
|
if err == datastore.ErrKeyModified {
|
|
|
|
return err
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) deleteFromStore(kvObject datastore.KVObject) error {
|
|
|
|
cs := c.getStore(kvObject.DataScope())
|
2015-06-01 16:43:24 +00:00
|
|
|
if cs == nil {
|
2017-04-05 05:37:58 +00:00
|
|
|
return ErrDataStoreNotInitialized(kvObject.DataScope())
|
2015-06-01 16:43:24 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
retry:
|
2015-09-16 11:42:35 +00:00
|
|
|
if err := cs.DeleteObjectAtomic(kvObject); err != nil {
|
2015-10-05 11:21:15 +00:00
|
|
|
if err == datastore.ErrKeyModified {
|
|
|
|
if err := cs.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
|
|
|
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
|
|
|
}
|
2017-11-30 08:22:30 +00:00
|
|
|
logrus.Warnf("Error (%v) deleting object %v, retrying....", err, kvObject.Key())
|
2015-10-05 11:21:15 +00:00
|
|
|
goto retry
|
|
|
|
}
|
2015-06-01 16:43:24 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
type netWatch struct {
|
|
|
|
localEps map[string]*endpoint
|
|
|
|
remoteEps map[string]*endpoint
|
|
|
|
stopCh chan struct{}
|
|
|
|
}
|
2015-06-17 16:13:31 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) getLocalEps(nw *netWatch) []*endpoint {
|
2015-05-31 18:49:11 +00:00
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
defer c.Unlock()
|
2015-05-31 18:49:11 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
var epl []*endpoint
|
|
|
|
for _, ep := range nw.localEps {
|
|
|
|
epl = append(epl, ep)
|
2015-08-17 08:07:43 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
return epl
|
2015-06-17 16:13:31 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) watchSvcRecord(ep *endpoint) {
|
|
|
|
c.watchCh <- ep
|
|
|
|
}
|
2015-06-17 16:13:31 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) unWatchSvcRecord(ep *endpoint) {
|
|
|
|
c.unWatchCh <- ep
|
|
|
|
}
|
2015-06-17 16:13:31 +00:00
|
|
|
|
2015-10-12 05:28:26 +00:00
|
|
|
func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan datastore.KVObject) {
|
2015-10-05 11:21:15 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-nw.stopCh:
|
|
|
|
return
|
2015-10-12 05:28:26 +00:00
|
|
|
case o := <-ecCh:
|
|
|
|
ec := o.(*endpointCnt)
|
2015-10-05 11:21:15 +00:00
|
|
|
|
2015-10-12 05:28:26 +00:00
|
|
|
epl, err := ec.n.getEndpointsFromStore()
|
2015-10-05 11:21:15 +00:00
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Lock()
|
|
|
|
var addEp []*endpoint
|
|
|
|
|
|
|
|
delEpMap := make(map[string]*endpoint)
|
2015-10-24 14:10:03 +00:00
|
|
|
renameEpMap := make(map[string]bool)
|
2015-10-05 11:21:15 +00:00
|
|
|
for k, v := range nw.remoteEps {
|
|
|
|
delEpMap[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, lEp := range epl {
|
|
|
|
if _, ok := nw.localEps[lEp.ID()]; ok {
|
|
|
|
continue
|
2015-06-17 16:13:31 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
2015-10-23 03:18:25 +00:00
|
|
|
if ep, ok := nw.remoteEps[lEp.ID()]; ok {
|
|
|
|
// On a container rename EP ID will remain
|
|
|
|
// the same but the name will change. service
|
|
|
|
// records should reflect the change.
|
|
|
|
// Keep old EP entry in the delEpMap and add
|
|
|
|
// EP from the store (which has the new name)
|
|
|
|
// into the new list
|
|
|
|
if lEp.name == ep.name {
|
|
|
|
delete(delEpMap, lEp.ID())
|
|
|
|
continue
|
|
|
|
}
|
2015-10-24 14:10:03 +00:00
|
|
|
renameEpMap[lEp.ID()] = true
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
nw.remoteEps[lEp.ID()] = lEp
|
|
|
|
addEp = append(addEp, lEp)
|
|
|
|
}
|
2015-10-24 14:10:03 +00:00
|
|
|
|
|
|
|
// EPs whose name are to be deleted from the svc records
|
|
|
|
// should also be removed from nw's remote EP list, except
|
|
|
|
// the ones that are getting renamed.
|
|
|
|
for _, lEp := range delEpMap {
|
|
|
|
if !renameEpMap[lEp.ID()] {
|
|
|
|
delete(nw.remoteEps, lEp.ID())
|
|
|
|
}
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
c.Unlock()
|
|
|
|
|
|
|
|
for _, lEp := range delEpMap {
|
|
|
|
ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), false)
|
|
|
|
|
|
|
|
}
|
2015-10-23 03:18:25 +00:00
|
|
|
for _, lEp := range addEp {
|
|
|
|
ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), true)
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
}
|
2015-06-05 20:31:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) processEndpointCreate(nmap map[string]*netWatch, ep *endpoint) {
|
2017-04-07 20:31:44 +00:00
|
|
|
n := ep.getNetwork()
|
|
|
|
if !c.isDistributedControl() && n.Scope() == datastore.SwarmScope && n.driverIsMultihost() {
|
2016-08-23 21:03:52 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
c.Lock()
|
2017-04-07 20:31:44 +00:00
|
|
|
nw, ok := nmap[n.ID()]
|
2015-10-05 11:21:15 +00:00
|
|
|
c.Unlock()
|
|
|
|
|
|
|
|
if ok {
|
|
|
|
// Update the svc db for the local endpoint join right away
|
2017-04-07 20:31:44 +00:00
|
|
|
n.updateSvcRecord(ep, c.getLocalEps(nw), true)
|
2015-10-05 11:21:15 +00:00
|
|
|
|
2015-06-18 15:18:17 +00:00
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
nw.localEps[ep.ID()] = ep
|
2015-10-22 04:20:12 +00:00
|
|
|
|
|
|
|
// If we had learned that from the kv store remove it
|
|
|
|
// from remote ep list now that we know that this is
|
|
|
|
// indeed a local endpoint
|
|
|
|
delete(nw.remoteEps, ep.ID())
|
2015-06-18 15:18:17 +00:00
|
|
|
c.Unlock()
|
2015-10-05 11:21:15 +00:00
|
|
|
return
|
2015-06-18 15:18:17 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
nw = &netWatch{
|
|
|
|
localEps: make(map[string]*endpoint),
|
|
|
|
remoteEps: make(map[string]*endpoint),
|
2015-06-05 20:31:12 +00:00
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
// Update the svc db for the local endpoint join right away
|
|
|
|
// Do this before adding this ep to localEps so that we don't
|
|
|
|
// try to update this ep's container's svc records
|
2017-04-07 20:31:44 +00:00
|
|
|
n.updateSvcRecord(ep, c.getLocalEps(nw), true)
|
2015-06-05 20:31:12 +00:00
|
|
|
|
|
|
|
c.Lock()
|
2015-10-05 11:21:15 +00:00
|
|
|
nw.localEps[ep.ID()] = ep
|
2017-04-07 20:31:44 +00:00
|
|
|
nmap[n.ID()] = nw
|
2015-10-05 11:21:15 +00:00
|
|
|
nw.stopCh = make(chan struct{})
|
2015-06-05 20:31:12 +00:00
|
|
|
c.Unlock()
|
|
|
|
|
2017-04-07 20:31:44 +00:00
|
|
|
store := c.getStore(n.DataScope())
|
2015-10-05 11:21:15 +00:00
|
|
|
if store == nil {
|
|
|
|
return
|
2015-06-05 20:31:12 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
if !store.Watchable() {
|
|
|
|
return
|
|
|
|
}
|
2015-08-17 08:07:43 +00:00
|
|
|
|
2017-04-07 20:31:44 +00:00
|
|
|
ch, err := store.Watch(n.getEpCnt(), nw.stopCh)
|
2015-08-17 08:07:43 +00:00
|
|
|
if err != nil {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Warnf("Error creating watch for network: %v", err)
|
2015-10-05 11:21:15 +00:00
|
|
|
return
|
2015-08-17 08:07:43 +00:00
|
|
|
}
|
2015-09-16 11:39:46 +00:00
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
go c.networkWatchLoop(nw, ep, ch)
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 11:21:15 +00:00
|
|
|
func (c *controller) processEndpointDelete(nmap map[string]*netWatch, ep *endpoint) {
|
2017-04-07 20:31:44 +00:00
|
|
|
n := ep.getNetwork()
|
|
|
|
if !c.isDistributedControl() && n.Scope() == datastore.SwarmScope && n.driverIsMultihost() {
|
2016-08-23 21:03:52 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-09-16 11:39:46 +00:00
|
|
|
c.Lock()
|
2017-04-07 20:31:44 +00:00
|
|
|
nw, ok := nmap[n.ID()]
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
if ok {
|
|
|
|
delete(nw.localEps, ep.ID())
|
|
|
|
c.Unlock()
|
|
|
|
|
|
|
|
// Update the svc db about local endpoint leave right away
|
|
|
|
// Do this after we remove this ep from localEps so that we
|
|
|
|
// don't try to remove this svc record from this ep's container.
|
2017-04-07 20:31:44 +00:00
|
|
|
n.updateSvcRecord(ep, c.getLocalEps(nw), false)
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
c.Lock()
|
|
|
|
if len(nw.localEps) == 0 {
|
|
|
|
close(nw.stopCh)
|
2015-10-25 00:41:58 +00:00
|
|
|
|
|
|
|
// This is the last container going away for the network. Destroy
|
|
|
|
// this network's svc db entry
|
2017-04-07 20:31:44 +00:00
|
|
|
delete(c.svcRecords, n.ID())
|
2015-10-25 00:41:58 +00:00
|
|
|
|
2017-04-07 20:31:44 +00:00
|
|
|
delete(nmap, n.ID())
|
2015-10-05 11:21:15 +00:00
|
|
|
}
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
|
|
|
c.Unlock()
|
|
|
|
}
|
|
|
|
|
2015-10-23 03:18:25 +00:00
|
|
|
func (c *controller) watchLoop() {
|
2015-10-05 11:21:15 +00:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case ep := <-c.watchCh:
|
2015-10-23 03:18:25 +00:00
|
|
|
c.processEndpointCreate(c.nmap, ep)
|
2015-10-05 11:21:15 +00:00
|
|
|
case ep := <-c.unWatchCh:
|
2015-10-23 03:18:25 +00:00
|
|
|
c.processEndpointDelete(c.nmap, ep)
|
2015-09-16 11:39:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
|
|
|
|
func (c *controller) startWatch() {
|
2016-02-16 23:19:18 +00:00
|
|
|
if c.watchCh != nil {
|
|
|
|
return
|
|
|
|
}
|
2015-10-05 11:21:15 +00:00
|
|
|
c.watchCh = make(chan *endpoint)
|
|
|
|
c.unWatchCh = make(chan *endpoint)
|
2015-10-23 03:18:25 +00:00
|
|
|
c.nmap = make(map[string]*netWatch)
|
2015-10-05 11:21:15 +00:00
|
|
|
|
2015-10-23 03:18:25 +00:00
|
|
|
go c.watchLoop()
|
2015-10-05 11:21:15 +00:00
|
|
|
}
|
2016-03-05 10:00:31 +00:00
|
|
|
|
|
|
|
func (c *controller) networkCleanup() {
|
|
|
|
networks, err := c.getNetworksFromStore()
|
|
|
|
if err != nil {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Warnf("Could not retrieve networks from store(s) during network cleanup: %v", err)
|
2016-03-05 10:00:31 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, n := range networks {
|
|
|
|
if n.inDelete {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Infof("Removing stale network %s (%s)", n.Name(), n.ID())
|
2018-04-09 22:08:39 +00:00
|
|
|
if err := n.delete(true, true); err != nil {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Debugf("Error while removing stale network: %v", err)
|
2016-03-05 10:00:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-15 04:34:44 +00:00
|
|
|
|
|
|
|
var populateSpecial NetworkWalker = func(nw Network) bool {
|
2017-04-07 17:51:39 +00:00
|
|
|
if n := nw.(*network); n.hasSpecialDriver() && !n.ConfigOnly() {
|
2016-06-15 04:34:44 +00:00
|
|
|
if err := n.getController().addNetwork(n); err != nil {
|
2016-11-01 04:26:14 +00:00
|
|
|
logrus.Warnf("Failed to populate network %q with driver %q", nw.Name(), nw.Type())
|
2016-06-15 04:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|