Browse Source

Avoid duplicate entries in /etc/hosts

Currently the local containers of a global scope
network will get it's service records updated
from both a local update and global update. There
is no way to check if this is a local endpoint when
a remote update comes in via watch because we add
the endpoint to local endpoint list during join, while
the remote update happens during createendpoint.

The right thing to do is update the local endpoint list
and start watching during createndpoint and remove the watch
during delete endpoint. But this might result in the container
getting it's own record in it's /etc/hosts. So added a filtering
logic to filter out self records when updating the container's
/etc/hosts

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 9 years ago
parent
commit
4850c5f1e6
2 changed files with 37 additions and 14 deletions
  1. 11 11
      libnetwork/endpoint.go
  2. 26 3
      libnetwork/network.go

+ 11 - 11
libnetwork/endpoint.go

@@ -345,7 +345,7 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
 	if ip := ep.getFirstInterfaceAddress(); ip != nil {
 	if ip := ep.getFirstInterfaceAddress(); ip != nil {
 		address = ip.String()
 		address = ip.String()
 	}
 	}
-	if err = sb.updateHostsFile(address, network.getSvcRecords()); err != nil {
+	if err = sb.updateHostsFile(address, network.getSvcRecords(ep)); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -467,9 +467,6 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
 		return err
 		return err
 	}
 	}
 
 
-	// unwatch for service records
-	n.getController().unWatchSvcRecord(ep)
-
 	if sb.needDefaultGW() {
 	if sb.needDefaultGW() {
 		ep := sb.getEPwithoutGateway()
 		ep := sb.getEPwithoutGateway()
 		if ep == nil {
 		if ep == nil {
@@ -501,29 +498,32 @@ func (ep *endpoint) Delete() error {
 	}
 	}
 	ep.Unlock()
 	ep.Unlock()
 
 
-	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
+	if err = n.getController().deleteFromStore(ep); err != nil {
 		return err
 		return err
 	}
 	}
 	defer func() {
 	defer func() {
 		if err != nil {
 		if err != nil {
-			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
-				log.Warnf("failed to update network %s : %v", n.name, e)
+			ep.dbExists = false
+			if e := n.getController().updateToStore(ep); e != nil {
+				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
 			}
 			}
 		}
 		}
 	}()
 	}()
 
 
-	if err = n.getController().deleteFromStore(ep); err != nil {
+	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
 		return err
 		return err
 	}
 	}
 	defer func() {
 	defer func() {
 		if err != nil {
 		if err != nil {
-			ep.dbExists = false
-			if e := n.getController().updateToStore(ep); e != nil {
-				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
+			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
+				log.Warnf("failed to update network %s : %v", n.name, e)
 			}
 			}
 		}
 		}
 	}()
 	}()
 
 
+	// unwatch for service records
+	n.getController().unWatchSvcRecord(ep)
+
 	if err = ep.deleteEndpoint(); err != nil {
 	if err = ep.deleteEndpoint(); err != nil {
 		return err
 		return err
 	}
 	}

+ 26 - 3
libnetwork/network.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 	"strconv"
 	"strconv"
+	"strings"
 	"sync"
 	"sync"
 
 
 	log "github.com/Sirupsen/logrus"
 	log "github.com/Sirupsen/logrus"
@@ -685,6 +686,14 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
 		}
 		}
 	}()
 	}()
 
 
+	// Watch for service records
+	n.getController().watchSvcRecord(ep)
+	defer func() {
+		if err != nil {
+			n.getController().unWatchSvcRecord(ep)
+		}
+	}()
+
 	// Increment endpoint count to indicate completion of endpoint addition
 	// Increment endpoint count to indicate completion of endpoint addition
 	if err = n.getEpCnt().IncEndpointCnt(); err != nil {
 	if err = n.getEpCnt().IncEndpointCnt(); err != nil {
 		return nil, err
 		return nil, err
@@ -768,6 +777,12 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	var recs []etchosts.Record
 	var recs []etchosts.Record
 	if iface := ep.Iface(); iface.Address() != nil {
 	if iface := ep.Iface(); iface.Address() != nil {
 		if isAdd {
 		if isAdd {
+			// If we already have this endpoint in service db just return
+			if _, ok := sr[ep.Name()]; ok {
+				n.Unlock()
+				return
+			}
+
 			sr[ep.Name()] = iface.Address().IP
 			sr[ep.Name()] = iface.Address().IP
 			sr[ep.Name()+"."+n.name] = iface.Address().IP
 			sr[ep.Name()+"."+n.name] = iface.Address().IP
 		} else {
 		} else {
@@ -793,8 +808,12 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	}
 	}
 
 
 	var sbList []*sandbox
 	var sbList []*sandbox
-	for _, ep := range localEps {
-		if sb, hasSandbox := ep.getSandbox(); hasSandbox {
+	for _, lEp := range localEps {
+		if ep.ID() == lEp.ID() {
+			continue
+		}
+
+		if sb, hasSandbox := lEp.getSandbox(); hasSandbox {
 			sbList = append(sbList, sb)
 			sbList = append(sbList, sb)
 		}
 		}
 	}
 	}
@@ -808,7 +827,7 @@ func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool
 	}
 	}
 }
 }
 
 
-func (n *network) getSvcRecords() []etchosts.Record {
+func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
 	n.Lock()
 	n.Lock()
 	defer n.Unlock()
 	defer n.Unlock()
 
 
@@ -816,6 +835,10 @@ func (n *network) getSvcRecords() []etchosts.Record {
 	sr, _ := n.ctrlr.svcDb[n.id]
 	sr, _ := n.ctrlr.svcDb[n.id]
 
 
 	for h, ip := range sr {
 	for h, ip := range sr {
+		if ep != nil && strings.Split(h, ".")[0] == ep.Name() {
+			continue
+		}
+
 		recs = append(recs, etchosts.Record{
 		recs = append(recs, etchosts.Record{
 			Hosts: h,
 			Hosts: h,
 			IP:    ip.String(),
 			IP:    ip.String(),