github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/endpoint.go (about)

     1  package libnetwork
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/docker/libnetwork/datastore"
    11  	"github.com/docker/libnetwork/ipamapi"
    12  	"github.com/docker/libnetwork/netlabel"
    13  	"github.com/docker/libnetwork/options"
    14  	"github.com/docker/libnetwork/types"
    15  	"github.com/sirupsen/logrus"
    16  )
    17  
    18  // Endpoint represents a logical connection between a network and a sandbox.
    19  type Endpoint interface {
    20  	// A system generated id for this endpoint.
    21  	ID() string
    22  
    23  	// Name returns the name of this endpoint.
    24  	Name() string
    25  
    26  	// Network returns the name of the network to which this endpoint is attached.
    27  	Network() string
    28  
    29  	// Join joins the sandbox to the endpoint and populates into the sandbox
    30  	// the network resources allocated for the endpoint.
    31  	Join(sandbox Sandbox, options ...EndpointOption) error
    32  
    33  	// Leave detaches the network resources populated in the sandbox.
    34  	Leave(sandbox Sandbox, options ...EndpointOption) error
    35  
    36  	// Return certain operational data belonging to this endpoint
    37  	Info() EndpointInfo
    38  
    39  	// DriverInfo returns a collection of driver operational data related to this endpoint retrieved from the driver
    40  	DriverInfo() (map[string]interface{}, error)
    41  
    42  	// Delete and detaches this endpoint from the network.
    43  	Delete(force bool) error
    44  }
    45  
    46  // EndpointOption is an option setter function type used to pass various options to Network
    47  // and Endpoint interfaces methods. The various setter functions of type EndpointOption are
    48  // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
    49  type EndpointOption func(ep *endpoint)
    50  
    51  type endpoint struct {
    52  	name              string
    53  	id                string
    54  	network           *network
    55  	iface             *endpointInterface
    56  	joinInfo          *endpointJoinInfo
    57  	sandboxID         string
    58  	locator           string
    59  	exposedPorts      []types.TransportPort
    60  	anonymous         bool
    61  	disableResolution bool
    62  	generic           map[string]interface{}
    63  	joinLeaveDone     chan struct{}
    64  	prefAddress       net.IP
    65  	prefAddressV6     net.IP
    66  	ipamOptions       map[string]string
    67  	aliases           map[string]string
    68  	myAliases         []string
    69  	svcID             string
    70  	svcName           string
    71  	virtualIP         net.IP
    72  	svcAliases        []string
    73  	ingressPorts      []*PortConfig
    74  	dbIndex           uint64
    75  	dbExists          bool
    76  	serviceEnabled    bool
    77  	loadBalancer      bool
    78  	sync.Mutex
    79  }
    80  
    81  func (ep *endpoint) MarshalJSON() ([]byte, error) {
    82  	ep.Lock()
    83  	defer ep.Unlock()
    84  
    85  	epMap := make(map[string]interface{})
    86  	epMap["name"] = ep.name
    87  	epMap["id"] = ep.id
    88  	epMap["ep_iface"] = ep.iface
    89  	epMap["joinInfo"] = ep.joinInfo
    90  	epMap["exposed_ports"] = ep.exposedPorts
    91  	if ep.generic != nil {
    92  		epMap["generic"] = ep.generic
    93  	}
    94  	epMap["sandbox"] = ep.sandboxID
    95  	epMap["locator"] = ep.locator
    96  	epMap["anonymous"] = ep.anonymous
    97  	epMap["disableResolution"] = ep.disableResolution
    98  	epMap["myAliases"] = ep.myAliases
    99  	epMap["svcName"] = ep.svcName
   100  	epMap["svcID"] = ep.svcID
   101  	epMap["virtualIP"] = ep.virtualIP.String()
   102  	epMap["ingressPorts"] = ep.ingressPorts
   103  	epMap["svcAliases"] = ep.svcAliases
   104  	epMap["loadBalancer"] = ep.loadBalancer
   105  
   106  	return json.Marshal(epMap)
   107  }
   108  
   109  func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
   110  	ep.Lock()
   111  	defer ep.Unlock()
   112  
   113  	var epMap map[string]interface{}
   114  	if err := json.Unmarshal(b, &epMap); err != nil {
   115  		return err
   116  	}
   117  	ep.name = epMap["name"].(string)
   118  	ep.id = epMap["id"].(string)
   119  
   120  	ib, _ := json.Marshal(epMap["ep_iface"])
   121  	json.Unmarshal(ib, &ep.iface)
   122  
   123  	jb, _ := json.Marshal(epMap["joinInfo"])
   124  	json.Unmarshal(jb, &ep.joinInfo)
   125  
   126  	tb, _ := json.Marshal(epMap["exposed_ports"])
   127  	var tPorts []types.TransportPort
   128  	json.Unmarshal(tb, &tPorts)
   129  	ep.exposedPorts = tPorts
   130  
   131  	cb, _ := json.Marshal(epMap["sandbox"])
   132  	json.Unmarshal(cb, &ep.sandboxID)
   133  
   134  	if v, ok := epMap["generic"]; ok {
   135  		ep.generic = v.(map[string]interface{})
   136  
   137  		if opt, ok := ep.generic[netlabel.PortMap]; ok {
   138  			pblist := []types.PortBinding{}
   139  
   140  			for i := 0; i < len(opt.([]interface{})); i++ {
   141  				pb := types.PortBinding{}
   142  				tmp := opt.([]interface{})[i].(map[string]interface{})
   143  
   144  				bytes, err := json.Marshal(tmp)
   145  				if err != nil {
   146  					logrus.Error(err)
   147  					break
   148  				}
   149  				err = json.Unmarshal(bytes, &pb)
   150  				if err != nil {
   151  					logrus.Error(err)
   152  					break
   153  				}
   154  				pblist = append(pblist, pb)
   155  			}
   156  			ep.generic[netlabel.PortMap] = pblist
   157  		}
   158  
   159  		if opt, ok := ep.generic[netlabel.ExposedPorts]; ok {
   160  			tplist := []types.TransportPort{}
   161  
   162  			for i := 0; i < len(opt.([]interface{})); i++ {
   163  				tp := types.TransportPort{}
   164  				tmp := opt.([]interface{})[i].(map[string]interface{})
   165  
   166  				bytes, err := json.Marshal(tmp)
   167  				if err != nil {
   168  					logrus.Error(err)
   169  					break
   170  				}
   171  				err = json.Unmarshal(bytes, &tp)
   172  				if err != nil {
   173  					logrus.Error(err)
   174  					break
   175  				}
   176  				tplist = append(tplist, tp)
   177  			}
   178  			ep.generic[netlabel.ExposedPorts] = tplist
   179  
   180  		}
   181  	}
   182  
   183  	if v, ok := epMap["anonymous"]; ok {
   184  		ep.anonymous = v.(bool)
   185  	}
   186  	if v, ok := epMap["disableResolution"]; ok {
   187  		ep.disableResolution = v.(bool)
   188  	}
   189  	if l, ok := epMap["locator"]; ok {
   190  		ep.locator = l.(string)
   191  	}
   192  
   193  	if sn, ok := epMap["svcName"]; ok {
   194  		ep.svcName = sn.(string)
   195  	}
   196  
   197  	if si, ok := epMap["svcID"]; ok {
   198  		ep.svcID = si.(string)
   199  	}
   200  
   201  	if vip, ok := epMap["virtualIP"]; ok {
   202  		ep.virtualIP = net.ParseIP(vip.(string))
   203  	}
   204  
   205  	if v, ok := epMap["loadBalancer"]; ok {
   206  		ep.loadBalancer = v.(bool)
   207  	}
   208  
   209  	sal, _ := json.Marshal(epMap["svcAliases"])
   210  	var svcAliases []string
   211  	json.Unmarshal(sal, &svcAliases)
   212  	ep.svcAliases = svcAliases
   213  
   214  	pc, _ := json.Marshal(epMap["ingressPorts"])
   215  	var ingressPorts []*PortConfig
   216  	json.Unmarshal(pc, &ingressPorts)
   217  	ep.ingressPorts = ingressPorts
   218  
   219  	ma, _ := json.Marshal(epMap["myAliases"])
   220  	var myAliases []string
   221  	json.Unmarshal(ma, &myAliases)
   222  	ep.myAliases = myAliases
   223  	return nil
   224  }
   225  
   226  func (ep *endpoint) New() datastore.KVObject {
   227  	return &endpoint{network: ep.getNetwork()}
   228  }
   229  
   230  func (ep *endpoint) CopyTo(o datastore.KVObject) error {
   231  	ep.Lock()
   232  	defer ep.Unlock()
   233  
   234  	dstEp := o.(*endpoint)
   235  	dstEp.name = ep.name
   236  	dstEp.id = ep.id
   237  	dstEp.sandboxID = ep.sandboxID
   238  	dstEp.locator = ep.locator
   239  	dstEp.dbIndex = ep.dbIndex
   240  	dstEp.dbExists = ep.dbExists
   241  	dstEp.anonymous = ep.anonymous
   242  	dstEp.disableResolution = ep.disableResolution
   243  	dstEp.svcName = ep.svcName
   244  	dstEp.svcID = ep.svcID
   245  	dstEp.virtualIP = ep.virtualIP
   246  	dstEp.loadBalancer = ep.loadBalancer
   247  
   248  	dstEp.svcAliases = make([]string, len(ep.svcAliases))
   249  	copy(dstEp.svcAliases, ep.svcAliases)
   250  
   251  	dstEp.ingressPorts = make([]*PortConfig, len(ep.ingressPorts))
   252  	copy(dstEp.ingressPorts, ep.ingressPorts)
   253  
   254  	if ep.iface != nil {
   255  		dstEp.iface = &endpointInterface{}
   256  		ep.iface.CopyTo(dstEp.iface)
   257  	}
   258  
   259  	if ep.joinInfo != nil {
   260  		dstEp.joinInfo = &endpointJoinInfo{}
   261  		ep.joinInfo.CopyTo(dstEp.joinInfo)
   262  	}
   263  
   264  	dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
   265  	copy(dstEp.exposedPorts, ep.exposedPorts)
   266  
   267  	dstEp.myAliases = make([]string, len(ep.myAliases))
   268  	copy(dstEp.myAliases, ep.myAliases)
   269  
   270  	dstEp.generic = options.Generic{}
   271  	for k, v := range ep.generic {
   272  		dstEp.generic[k] = v
   273  	}
   274  
   275  	return nil
   276  }
   277  
   278  func (ep *endpoint) ID() string {
   279  	ep.Lock()
   280  	defer ep.Unlock()
   281  
   282  	return ep.id
   283  }
   284  
   285  func (ep *endpoint) Name() string {
   286  	ep.Lock()
   287  	defer ep.Unlock()
   288  
   289  	return ep.name
   290  }
   291  
   292  func (ep *endpoint) MyAliases() []string {
   293  	ep.Lock()
   294  	defer ep.Unlock()
   295  
   296  	return ep.myAliases
   297  }
   298  
   299  func (ep *endpoint) Network() string {
   300  	if ep.network == nil {
   301  		return ""
   302  	}
   303  
   304  	return ep.network.name
   305  }
   306  
   307  func (ep *endpoint) isAnonymous() bool {
   308  	ep.Lock()
   309  	defer ep.Unlock()
   310  	return ep.anonymous
   311  }
   312  
   313  // isServiceEnabled check if service is enabled on the endpoint
   314  func (ep *endpoint) isServiceEnabled() bool {
   315  	ep.Lock()
   316  	defer ep.Unlock()
   317  	return ep.serviceEnabled
   318  }
   319  
   320  // enableService sets service enabled on the endpoint
   321  func (ep *endpoint) enableService() {
   322  	ep.Lock()
   323  	defer ep.Unlock()
   324  	ep.serviceEnabled = true
   325  }
   326  
   327  // disableService disables service on the endpoint
   328  func (ep *endpoint) disableService() {
   329  	ep.Lock()
   330  	defer ep.Unlock()
   331  	ep.serviceEnabled = false
   332  }
   333  
   334  func (ep *endpoint) needResolver() bool {
   335  	ep.Lock()
   336  	defer ep.Unlock()
   337  	return !ep.disableResolution
   338  }
   339  
   340  // endpoint Key structure : endpoint/network-id/endpoint-id
   341  func (ep *endpoint) Key() []string {
   342  	if ep.network == nil {
   343  		return nil
   344  	}
   345  
   346  	return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id}
   347  }
   348  
   349  func (ep *endpoint) KeyPrefix() []string {
   350  	if ep.network == nil {
   351  		return nil
   352  	}
   353  
   354  	return []string{datastore.EndpointKeyPrefix, ep.network.id}
   355  }
   356  
   357  func (ep *endpoint) networkIDFromKey(key string) (string, error) {
   358  	// endpoint Key structure : docker/libnetwork/endpoint/${network-id}/${endpoint-id}
   359  	// it's an invalid key if the key doesn't have all the 5 key elements above
   360  	keyElements := strings.Split(key, "/")
   361  	if !strings.HasPrefix(key, datastore.Key(datastore.EndpointKeyPrefix)) || len(keyElements) < 5 {
   362  		return "", fmt.Errorf("invalid endpoint key : %v", key)
   363  	}
   364  	// network-id is placed at index=3. pls refer to endpoint.Key() method
   365  	return strings.Split(key, "/")[3], nil
   366  }
   367  
   368  func (ep *endpoint) Value() []byte {
   369  	b, err := json.Marshal(ep)
   370  	if err != nil {
   371  		return nil
   372  	}
   373  	return b
   374  }
   375  
   376  func (ep *endpoint) SetValue(value []byte) error {
   377  	return json.Unmarshal(value, ep)
   378  }
   379  
   380  func (ep *endpoint) Index() uint64 {
   381  	ep.Lock()
   382  	defer ep.Unlock()
   383  	return ep.dbIndex
   384  }
   385  
   386  func (ep *endpoint) SetIndex(index uint64) {
   387  	ep.Lock()
   388  	defer ep.Unlock()
   389  	ep.dbIndex = index
   390  	ep.dbExists = true
   391  }
   392  
   393  func (ep *endpoint) Exists() bool {
   394  	ep.Lock()
   395  	defer ep.Unlock()
   396  	return ep.dbExists
   397  }
   398  
   399  func (ep *endpoint) Skip() bool {
   400  	return ep.getNetwork().Skip()
   401  }
   402  
   403  func (ep *endpoint) processOptions(options ...EndpointOption) {
   404  	ep.Lock()
   405  	defer ep.Unlock()
   406  
   407  	for _, opt := range options {
   408  		if opt != nil {
   409  			opt(ep)
   410  		}
   411  	}
   412  }
   413  
   414  func (ep *endpoint) getNetwork() *network {
   415  	ep.Lock()
   416  	defer ep.Unlock()
   417  
   418  	return ep.network
   419  }
   420  
   421  func (ep *endpoint) getNetworkFromStore() (*network, error) {
   422  	if ep.network == nil {
   423  		return nil, fmt.Errorf("invalid network object in endpoint %s", ep.Name())
   424  	}
   425  
   426  	return ep.network.getController().getNetworkFromStore(ep.network.id)
   427  }
   428  
   429  func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error {
   430  	if sbox == nil {
   431  		return types.BadRequestErrorf("endpoint cannot be joined by nil container")
   432  	}
   433  
   434  	sb, ok := sbox.(*sandbox)
   435  	if !ok {
   436  		return types.BadRequestErrorf("not a valid Sandbox interface")
   437  	}
   438  
   439  	sb.joinLeaveStart()
   440  	defer sb.joinLeaveEnd()
   441  
   442  	return ep.sbJoin(sb, options...)
   443  }
   444  
   445  func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) {
   446  	n, err := ep.getNetworkFromStore()
   447  	if err != nil {
   448  		return fmt.Errorf("failed to get network from store during join: %v", err)
   449  	}
   450  
   451  	ep, err = n.getEndpointFromStore(ep.ID())
   452  	if err != nil {
   453  		return fmt.Errorf("failed to get endpoint from store during join: %v", err)
   454  	}
   455  
   456  	ep.Lock()
   457  	if ep.sandboxID != "" {
   458  		ep.Unlock()
   459  		return types.ForbiddenErrorf("another container is attached to the same network endpoint")
   460  	}
   461  	ep.network = n
   462  	ep.sandboxID = sb.ID()
   463  	ep.joinInfo = &endpointJoinInfo{}
   464  	epid := ep.id
   465  	ep.Unlock()
   466  	defer func() {
   467  		if err != nil {
   468  			ep.Lock()
   469  			ep.sandboxID = ""
   470  			ep.Unlock()
   471  		}
   472  	}()
   473  
   474  	nid := n.ID()
   475  
   476  	ep.processOptions(options...)
   477  
   478  	d, err := n.driver(true)
   479  	if err != nil {
   480  		return fmt.Errorf("failed to get driver during join: %v", err)
   481  	}
   482  
   483  	err = d.Join(nid, epid, sb.Key(), ep, sb.Labels())
   484  	if err != nil {
   485  		return err
   486  	}
   487  	defer func() {
   488  		if err != nil {
   489  			if e := d.Leave(nid, epid); e != nil {
   490  				logrus.Warnf("driver leave failed while rolling back join: %v", e)
   491  			}
   492  		}
   493  	}()
   494  
   495  	// Watch for service records
   496  	if !n.getController().isAgent() {
   497  		n.getController().watchSvcRecord(ep)
   498  	}
   499  
   500  	if doUpdateHostsFile(n, sb) {
   501  		var addresses []string
   502  		if ip := ep.getFirstInterfaceIPv4Address(); ip != nil {
   503  			addresses = append(addresses, ip.String())
   504  		}
   505  		if ip := ep.getFirstInterfaceIPv6Address(); ip != nil {
   506  			addresses = append(addresses, ip.String())
   507  		}
   508  		if err = sb.updateHostsFile(addresses); err != nil {
   509  			return err
   510  		}
   511  	}
   512  	if err = sb.updateDNS(n.enableIPv6); err != nil {
   513  		return err
   514  	}
   515  
   516  	// Current endpoint providing external connectivity for the sandbox
   517  	extEp := sb.getGatewayEndpoint()
   518  
   519  	sb.addEndpoint(ep)
   520  	defer func() {
   521  		if err != nil {
   522  			sb.removeEndpoint(ep)
   523  		}
   524  	}()
   525  
   526  	if err = sb.populateNetworkResources(ep); err != nil {
   527  		return err
   528  	}
   529  
   530  	if err = n.getController().updateToStore(ep); err != nil {
   531  		return err
   532  	}
   533  
   534  	if err = ep.addDriverInfoToCluster(); err != nil {
   535  		return err
   536  	}
   537  
   538  	defer func() {
   539  		if err != nil {
   540  			if e := ep.deleteDriverInfoFromCluster(); e != nil {
   541  				logrus.Errorf("Could not delete endpoint state for endpoint %s from cluster on join failure: %v", ep.Name(), e)
   542  			}
   543  		}
   544  	}()
   545  
   546  	// Load balancing endpoints should never have a default gateway nor
   547  	// should they alter the status of a network's default gateway
   548  	if ep.loadBalancer && !sb.ingress {
   549  		return nil
   550  	}
   551  
   552  	if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
   553  		return sb.setupDefaultGW()
   554  	}
   555  
   556  	moveExtConn := sb.getGatewayEndpoint() != extEp
   557  
   558  	if moveExtConn {
   559  		if extEp != nil {
   560  			logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
   561  			extN, err := extEp.getNetworkFromStore()
   562  			if err != nil {
   563  				return fmt.Errorf("failed to get network from store for revoking external connectivity during join: %v", err)
   564  			}
   565  			extD, err := extN.driver(true)
   566  			if err != nil {
   567  				return fmt.Errorf("failed to get driver for revoking external connectivity during join: %v", err)
   568  			}
   569  			if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
   570  				return types.InternalErrorf(
   571  					"driver failed revoking external connectivity on endpoint %s (%s): %v",
   572  					extEp.Name(), extEp.ID(), err)
   573  			}
   574  			defer func() {
   575  				if err != nil {
   576  					if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
   577  						logrus.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
   578  							extEp.Name(), extEp.ID(), e)
   579  					}
   580  				}
   581  			}()
   582  		}
   583  		if !n.internal {
   584  			logrus.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
   585  			if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
   586  				return types.InternalErrorf(
   587  					"driver failed programming external connectivity on endpoint %s (%s): %v",
   588  					ep.Name(), ep.ID(), err)
   589  			}
   590  		}
   591  
   592  	}
   593  
   594  	if !sb.needDefaultGW() {
   595  		if e := sb.clearDefaultGW(); e != nil {
   596  			logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
   597  				sb.ID(), sb.ContainerID(), e)
   598  		}
   599  	}
   600  
   601  	return nil
   602  }
   603  
   604  func doUpdateHostsFile(n *network, sb *sandbox) bool {
   605  	return !n.ingress && n.Name() != libnGWNetwork
   606  }
   607  
   608  func (ep *endpoint) rename(name string) error {
   609  	var (
   610  		err      error
   611  		netWatch *netWatch
   612  		ok       bool
   613  	)
   614  
   615  	n := ep.getNetwork()
   616  	if n == nil {
   617  		return fmt.Errorf("network not connected for ep %q", ep.name)
   618  	}
   619  
   620  	c := n.getController()
   621  
   622  	sb, ok := ep.getSandbox()
   623  	if !ok {
   624  		logrus.Warnf("rename for %s aborted, sandbox %s is not anymore present", ep.ID(), ep.sandboxID)
   625  		return nil
   626  	}
   627  
   628  	if c.isAgent() {
   629  		if err = ep.deleteServiceInfoFromCluster(sb, true, "rename"); err != nil {
   630  			return types.InternalErrorf("Could not delete service state for endpoint %s from cluster on rename: %v", ep.Name(), err)
   631  		}
   632  	} else {
   633  		c.Lock()
   634  		netWatch, ok = c.nmap[n.ID()]
   635  		c.Unlock()
   636  		if !ok {
   637  			return fmt.Errorf("watch null for network %q", n.Name())
   638  		}
   639  		n.updateSvcRecord(ep, c.getLocalEps(netWatch), false)
   640  	}
   641  
   642  	oldName := ep.name
   643  	oldAnonymous := ep.anonymous
   644  	ep.name = name
   645  	ep.anonymous = false
   646  
   647  	if c.isAgent() {
   648  		if err = ep.addServiceInfoToCluster(sb); err != nil {
   649  			return types.InternalErrorf("Could not add service state for endpoint %s to cluster on rename: %v", ep.Name(), err)
   650  		}
   651  		defer func() {
   652  			if err != nil {
   653  				ep.deleteServiceInfoFromCluster(sb, true, "rename")
   654  				ep.name = oldName
   655  				ep.anonymous = oldAnonymous
   656  				ep.addServiceInfoToCluster(sb)
   657  			}
   658  		}()
   659  	} else {
   660  		n.updateSvcRecord(ep, c.getLocalEps(netWatch), true)
   661  		defer func() {
   662  			if err != nil {
   663  				n.updateSvcRecord(ep, c.getLocalEps(netWatch), false)
   664  				ep.name = oldName
   665  				ep.anonymous = oldAnonymous
   666  				n.updateSvcRecord(ep, c.getLocalEps(netWatch), true)
   667  			}
   668  		}()
   669  	}
   670  
   671  	// Update the store with the updated name
   672  	if err = c.updateToStore(ep); err != nil {
   673  		return err
   674  	}
   675  	// After the name change do a dummy endpoint count update to
   676  	// trigger the service record update in the peer nodes
   677  
   678  	// Ignore the error because updateStore fail for EpCnt is a
   679  	// benign error. Besides there is no meaningful recovery that
   680  	// we can do. When the cluster recovers subsequent EpCnt update
   681  	// will force the peers to get the correct EP name.
   682  	n.getEpCnt().updateStore()
   683  
   684  	return err
   685  }
   686  
   687  func (ep *endpoint) hasInterface(iName string) bool {
   688  	ep.Lock()
   689  	defer ep.Unlock()
   690  
   691  	return ep.iface != nil && ep.iface.srcName == iName
   692  }
   693  
   694  func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error {
   695  	if sbox == nil || sbox.ID() == "" || sbox.Key() == "" {
   696  		return types.BadRequestErrorf("invalid Sandbox passed to endpoint leave: %v", sbox)
   697  	}
   698  
   699  	sb, ok := sbox.(*sandbox)
   700  	if !ok {
   701  		return types.BadRequestErrorf("not a valid Sandbox interface")
   702  	}
   703  
   704  	sb.joinLeaveStart()
   705  	defer sb.joinLeaveEnd()
   706  
   707  	return ep.sbLeave(sb, false, options...)
   708  }
   709  
   710  func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) error {
   711  	n, err := ep.getNetworkFromStore()
   712  	if err != nil {
   713  		return fmt.Errorf("failed to get network from store during leave: %v", err)
   714  	}
   715  
   716  	ep, err = n.getEndpointFromStore(ep.ID())
   717  	if err != nil {
   718  		return fmt.Errorf("failed to get endpoint from store during leave: %v", err)
   719  	}
   720  
   721  	ep.Lock()
   722  	sid := ep.sandboxID
   723  	ep.Unlock()
   724  
   725  	if sid == "" {
   726  		return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
   727  	}
   728  	if sid != sb.ID() {
   729  		return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID())
   730  	}
   731  
   732  	ep.processOptions(options...)
   733  
   734  	d, err := n.driver(!force)
   735  	if err != nil {
   736  		return fmt.Errorf("failed to get driver during endpoint leave: %v", err)
   737  	}
   738  
   739  	ep.Lock()
   740  	ep.sandboxID = ""
   741  	ep.network = n
   742  	ep.Unlock()
   743  
   744  	// Current endpoint providing external connectivity to the sandbox
   745  	extEp := sb.getGatewayEndpoint()
   746  	moveExtConn := extEp != nil && (extEp.ID() == ep.ID())
   747  
   748  	if d != nil {
   749  		if moveExtConn {
   750  			logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
   751  			if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
   752  				logrus.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
   753  					ep.Name(), ep.ID(), err)
   754  			}
   755  		}
   756  
   757  		if err := d.Leave(n.id, ep.id); err != nil {
   758  			if _, ok := err.(types.MaskableError); !ok {
   759  				logrus.Warnf("driver error disconnecting container %s : %v", ep.name, err)
   760  			}
   761  		}
   762  	}
   763  
   764  	if err := ep.deleteServiceInfoFromCluster(sb, true, "sbLeave"); err != nil {
   765  		logrus.Warnf("Failed to clean up service info on container %s disconnect: %v", ep.name, err)
   766  	}
   767  
   768  	if err := sb.clearNetworkResources(ep); err != nil {
   769  		logrus.Warnf("Failed to clean up network resources on container %s disconnect: %v", ep.name, err)
   770  	}
   771  
   772  	// Update the store about the sandbox detach only after we
   773  	// have completed sb.clearNetworkresources above to avoid
   774  	// spurious logs when cleaning up the sandbox when the daemon
   775  	// ungracefully exits and restarts before completing sandbox
   776  	// detach but after store has been updated.
   777  	if err := n.getController().updateToStore(ep); err != nil {
   778  		return err
   779  	}
   780  
   781  	if e := ep.deleteDriverInfoFromCluster(); e != nil {
   782  		logrus.Errorf("Failed to delete endpoint state for endpoint %s from cluster: %v", ep.Name(), e)
   783  	}
   784  
   785  	sb.deleteHostsEntries(n.getSvcRecords(ep))
   786  	if !sb.inDelete && sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
   787  		return sb.setupDefaultGW()
   788  	}
   789  
   790  	// New endpoint providing external connectivity for the sandbox
   791  	extEp = sb.getGatewayEndpoint()
   792  	if moveExtConn && extEp != nil {
   793  		logrus.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
   794  		extN, err := extEp.getNetworkFromStore()
   795  		if err != nil {
   796  			return fmt.Errorf("failed to get network from store for programming external connectivity during leave: %v", err)
   797  		}
   798  		extD, err := extN.driver(true)
   799  		if err != nil {
   800  			return fmt.Errorf("failed to get driver for programming external connectivity during leave: %v", err)
   801  		}
   802  		if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
   803  			logrus.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
   804  				extEp.Name(), extEp.ID(), err)
   805  		}
   806  	}
   807  
   808  	if !sb.needDefaultGW() {
   809  		if err := sb.clearDefaultGW(); err != nil {
   810  			logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
   811  				sb.ID(), sb.ContainerID(), err)
   812  		}
   813  	}
   814  
   815  	return nil
   816  }
   817  
   818  func (ep *endpoint) Delete(force bool) error {
   819  	var err error
   820  	n, err := ep.getNetworkFromStore()
   821  	if err != nil {
   822  		return fmt.Errorf("failed to get network during Delete: %v", err)
   823  	}
   824  
   825  	ep, err = n.getEndpointFromStore(ep.ID())
   826  	if err != nil {
   827  		return fmt.Errorf("failed to get endpoint from store during Delete: %v", err)
   828  	}
   829  
   830  	ep.Lock()
   831  	epid := ep.id
   832  	name := ep.name
   833  	sbid := ep.sandboxID
   834  	ep.Unlock()
   835  
   836  	sb, _ := n.getController().SandboxByID(sbid)
   837  	if sb != nil && !force {
   838  		return &ActiveContainerError{name: name, id: epid}
   839  	}
   840  
   841  	if sb != nil {
   842  		if e := ep.sbLeave(sb.(*sandbox), force); e != nil {
   843  			logrus.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
   844  		}
   845  	}
   846  
   847  	if err = n.getController().deleteFromStore(ep); err != nil {
   848  		return err
   849  	}
   850  
   851  	defer func() {
   852  		if err != nil && !force {
   853  			ep.dbExists = false
   854  			if e := n.getController().updateToStore(ep); e != nil {
   855  				logrus.Warnf("failed to recreate endpoint in store %s : %v", name, e)
   856  			}
   857  		}
   858  	}()
   859  
   860  	// unwatch for service records
   861  	n.getController().unWatchSvcRecord(ep)
   862  
   863  	if err = ep.deleteEndpoint(force); err != nil && !force {
   864  		return err
   865  	}
   866  
   867  	ep.releaseAddress()
   868  
   869  	if err := n.getEpCnt().DecEndpointCnt(); err != nil {
   870  		logrus.Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err)
   871  	}
   872  
   873  	return nil
   874  }
   875  
   876  func (ep *endpoint) deleteEndpoint(force bool) error {
   877  	ep.Lock()
   878  	n := ep.network
   879  	name := ep.name
   880  	epid := ep.id
   881  	ep.Unlock()
   882  
   883  	driver, err := n.driver(!force)
   884  	if err != nil {
   885  		return fmt.Errorf("failed to delete endpoint: %v", err)
   886  	}
   887  
   888  	if driver == nil {
   889  		return nil
   890  	}
   891  
   892  	if err := driver.DeleteEndpoint(n.id, epid); err != nil {
   893  		if _, ok := err.(types.ForbiddenError); ok {
   894  			return err
   895  		}
   896  
   897  		if _, ok := err.(types.MaskableError); !ok {
   898  			logrus.Warnf("driver error deleting endpoint %s : %v", name, err)
   899  		}
   900  	}
   901  
   902  	return nil
   903  }
   904  
   905  func (ep *endpoint) getSandbox() (*sandbox, bool) {
   906  	c := ep.network.getController()
   907  	ep.Lock()
   908  	sid := ep.sandboxID
   909  	ep.Unlock()
   910  
   911  	c.Lock()
   912  	ps, ok := c.sandboxes[sid]
   913  	c.Unlock()
   914  
   915  	return ps, ok
   916  }
   917  
   918  func (ep *endpoint) getFirstInterfaceIPv4Address() net.IP {
   919  	ep.Lock()
   920  	defer ep.Unlock()
   921  
   922  	if ep.iface.addr != nil {
   923  		return ep.iface.addr.IP
   924  	}
   925  
   926  	return nil
   927  }
   928  
   929  func (ep *endpoint) getFirstInterfaceIPv6Address() net.IP {
   930  	ep.Lock()
   931  	defer ep.Unlock()
   932  
   933  	if ep.iface.addrv6 != nil {
   934  		return ep.iface.addrv6.IP
   935  	}
   936  
   937  	return nil
   938  }
   939  
   940  // EndpointOptionGeneric function returns an option setter for a Generic option defined
   941  // in a Dictionary of Key-Value pair
   942  func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
   943  	return func(ep *endpoint) {
   944  		for k, v := range generic {
   945  			ep.generic[k] = v
   946  		}
   947  	}
   948  }
   949  
   950  var (
   951  	linkLocalMask     = net.CIDRMask(16, 32)
   952  	linkLocalMaskIPv6 = net.CIDRMask(64, 128)
   953  )
   954  
   955  // CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint
   956  func CreateOptionIpam(ipV4, ipV6 net.IP, llIPs []net.IP, ipamOptions map[string]string) EndpointOption {
   957  	return func(ep *endpoint) {
   958  		ep.prefAddress = ipV4
   959  		ep.prefAddressV6 = ipV6
   960  		if len(llIPs) != 0 {
   961  			for _, ip := range llIPs {
   962  				nw := &net.IPNet{IP: ip, Mask: linkLocalMask}
   963  				if ip.To4() == nil {
   964  					nw.Mask = linkLocalMaskIPv6
   965  				}
   966  				ep.iface.llAddrs = append(ep.iface.llAddrs, nw)
   967  			}
   968  		}
   969  		ep.ipamOptions = ipamOptions
   970  	}
   971  }
   972  
   973  // CreateOptionExposedPorts function returns an option setter for the container exposed
   974  // ports option to be passed to network.CreateEndpoint() method.
   975  func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
   976  	return func(ep *endpoint) {
   977  		// Defensive copy
   978  		eps := make([]types.TransportPort, len(exposedPorts))
   979  		copy(eps, exposedPorts)
   980  		// Store endpoint label and in generic because driver needs it
   981  		ep.exposedPorts = eps
   982  		ep.generic[netlabel.ExposedPorts] = eps
   983  	}
   984  }
   985  
   986  // CreateOptionPortMapping function returns an option setter for the mapping
   987  // ports option to be passed to network.CreateEndpoint() method.
   988  func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
   989  	return func(ep *endpoint) {
   990  		// Store a copy of the bindings as generic data to pass to the driver
   991  		pbs := make([]types.PortBinding, len(portBindings))
   992  		copy(pbs, portBindings)
   993  		ep.generic[netlabel.PortMap] = pbs
   994  	}
   995  }
   996  
   997  // CreateOptionDNS function returns an option setter for dns entry option to
   998  // be passed to container Create method.
   999  func CreateOptionDNS(dns []string) EndpointOption {
  1000  	return func(ep *endpoint) {
  1001  		ep.generic[netlabel.DNSServers] = dns
  1002  	}
  1003  }
  1004  
  1005  // CreateOptionAnonymous function returns an option setter for setting
  1006  // this endpoint as anonymous
  1007  func CreateOptionAnonymous() EndpointOption {
  1008  	return func(ep *endpoint) {
  1009  		ep.anonymous = true
  1010  	}
  1011  }
  1012  
  1013  // CreateOptionDisableResolution function returns an option setter to indicate
  1014  // this endpoint doesn't want embedded DNS server functionality
  1015  func CreateOptionDisableResolution() EndpointOption {
  1016  	return func(ep *endpoint) {
  1017  		ep.disableResolution = true
  1018  	}
  1019  }
  1020  
  1021  // CreateOptionAlias function returns an option setter for setting endpoint alias
  1022  func CreateOptionAlias(name string, alias string) EndpointOption {
  1023  	return func(ep *endpoint) {
  1024  		if ep.aliases == nil {
  1025  			ep.aliases = make(map[string]string)
  1026  		}
  1027  		ep.aliases[alias] = name
  1028  	}
  1029  }
  1030  
  1031  // CreateOptionService function returns an option setter for setting service binding configuration
  1032  func CreateOptionService(name, id string, vip net.IP, ingressPorts []*PortConfig, aliases []string) EndpointOption {
  1033  	return func(ep *endpoint) {
  1034  		ep.svcName = name
  1035  		ep.svcID = id
  1036  		ep.virtualIP = vip
  1037  		ep.ingressPorts = ingressPorts
  1038  		ep.svcAliases = aliases
  1039  	}
  1040  }
  1041  
  1042  // CreateOptionMyAlias function returns an option setter for setting endpoint's self alias
  1043  func CreateOptionMyAlias(alias string) EndpointOption {
  1044  	return func(ep *endpoint) {
  1045  		ep.myAliases = append(ep.myAliases, alias)
  1046  	}
  1047  }
  1048  
  1049  // CreateOptionLoadBalancer function returns an option setter for denoting the endpoint is a load balancer for a network
  1050  func CreateOptionLoadBalancer() EndpointOption {
  1051  	return func(ep *endpoint) {
  1052  		ep.loadBalancer = true
  1053  	}
  1054  }
  1055  
  1056  // JoinOptionPriority function returns an option setter for priority option to
  1057  // be passed to the endpoint.Join() method.
  1058  func JoinOptionPriority(prio int) EndpointOption {
  1059  	return func(ep *endpoint) {
  1060  		// ep lock already acquired
  1061  		c := ep.network.getController()
  1062  		c.Lock()
  1063  		sb, ok := c.sandboxes[ep.sandboxID]
  1064  		c.Unlock()
  1065  		if !ok {
  1066  			logrus.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
  1067  			return
  1068  		}
  1069  		sb.epPriority[ep.id] = prio
  1070  	}
  1071  }
  1072  
  1073  func (ep *endpoint) DataScope() string {
  1074  	return ep.getNetwork().DataScope()
  1075  }
  1076  
  1077  func (ep *endpoint) assignAddress(ipam ipamapi.Ipam, assignIPv4, assignIPv6 bool) error {
  1078  	var err error
  1079  
  1080  	n := ep.getNetwork()
  1081  	if n.hasSpecialDriver() {
  1082  		return nil
  1083  	}
  1084  
  1085  	logrus.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  1086  
  1087  	if assignIPv4 {
  1088  		if err = ep.assignAddressVersion(4, ipam); err != nil {
  1089  			return err
  1090  		}
  1091  	}
  1092  
  1093  	if assignIPv6 {
  1094  		err = ep.assignAddressVersion(6, ipam)
  1095  	}
  1096  
  1097  	return err
  1098  }
  1099  
  1100  func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
  1101  	var (
  1102  		poolID  *string
  1103  		address **net.IPNet
  1104  		prefAdd net.IP
  1105  		progAdd net.IP
  1106  	)
  1107  
  1108  	n := ep.getNetwork()
  1109  	switch ipVer {
  1110  	case 4:
  1111  		poolID = &ep.iface.v4PoolID
  1112  		address = &ep.iface.addr
  1113  		prefAdd = ep.prefAddress
  1114  	case 6:
  1115  		poolID = &ep.iface.v6PoolID
  1116  		address = &ep.iface.addrv6
  1117  		prefAdd = ep.prefAddressV6
  1118  	default:
  1119  		return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
  1120  	}
  1121  
  1122  	ipInfo := n.getIPInfo(ipVer)
  1123  
  1124  	// ipv6 address is not mandatory
  1125  	if len(ipInfo) == 0 && ipVer == 6 {
  1126  		return nil
  1127  	}
  1128  
  1129  	// The address to program may be chosen by the user or by the network driver in one specific
  1130  	// case to support backward compatibility with `docker daemon --fixed-cidrv6` use case
  1131  	if prefAdd != nil {
  1132  		progAdd = prefAdd
  1133  	} else if *address != nil {
  1134  		progAdd = (*address).IP
  1135  	}
  1136  
  1137  	for _, d := range ipInfo {
  1138  		if progAdd != nil && !d.Pool.Contains(progAdd) {
  1139  			continue
  1140  		}
  1141  		addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions)
  1142  		if err == nil {
  1143  			ep.Lock()
  1144  			*address = addr
  1145  			*poolID = d.PoolID
  1146  			ep.Unlock()
  1147  			return nil
  1148  		}
  1149  		if err != ipamapi.ErrNoAvailableIPs || progAdd != nil {
  1150  			return err
  1151  		}
  1152  	}
  1153  	if progAdd != nil {
  1154  		return types.BadRequestErrorf("Invalid address %s: It does not belong to any of this network's subnets", prefAdd)
  1155  	}
  1156  	return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
  1157  }
  1158  
  1159  func (ep *endpoint) releaseAddress() {
  1160  	n := ep.getNetwork()
  1161  	if n.hasSpecialDriver() {
  1162  		return
  1163  	}
  1164  
  1165  	logrus.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  1166  
  1167  	ipam, _, err := n.getController().getIPAMDriver(n.ipamType)
  1168  	if err != nil {
  1169  		logrus.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
  1170  		return
  1171  	}
  1172  
  1173  	if ep.iface.addr != nil {
  1174  		if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
  1175  			logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
  1176  		}
  1177  	}
  1178  
  1179  	if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
  1180  		if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
  1181  			logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
  1182  		}
  1183  	}
  1184  }
  1185  
  1186  func (c *controller) cleanupLocalEndpoints() {
  1187  	// Get used endpoints
  1188  	eps := make(map[string]interface{})
  1189  	for _, sb := range c.sandboxes {
  1190  		for _, ep := range sb.endpoints {
  1191  			eps[ep.id] = true
  1192  		}
  1193  	}
  1194  	nl, err := c.getNetworksForScope(datastore.LocalScope)
  1195  	if err != nil {
  1196  		logrus.Warnf("Could not get list of networks during endpoint cleanup: %v", err)
  1197  		return
  1198  	}
  1199  
  1200  	for _, n := range nl {
  1201  		if n.ConfigOnly() {
  1202  			continue
  1203  		}
  1204  		epl, err := n.getEndpointsFromStore()
  1205  		if err != nil {
  1206  			logrus.Warnf("Could not get list of endpoints in network %s during endpoint cleanup: %v", n.name, err)
  1207  			continue
  1208  		}
  1209  
  1210  		for _, ep := range epl {
  1211  			if _, ok := eps[ep.id]; ok {
  1212  				continue
  1213  			}
  1214  			logrus.Infof("Removing stale endpoint %s (%s)", ep.name, ep.id)
  1215  			if err := ep.Delete(true); err != nil {
  1216  				logrus.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
  1217  			}
  1218  		}
  1219  
  1220  		epl, err = n.getEndpointsFromStore()
  1221  		if err != nil {
  1222  			logrus.Warnf("Could not get list of endpoints in network %s for count update: %v", n.name, err)
  1223  			continue
  1224  		}
  1225  
  1226  		epCnt := n.getEpCnt().EndpointCnt()
  1227  		if epCnt != uint64(len(epl)) {
  1228  			logrus.Infof("Fixing inconsistent endpoint_cnt for network %s. Expected=%d, Actual=%d", n.name, len(epl), epCnt)
  1229  			n.getEpCnt().setCnt(uint64(len(epl)))
  1230  		}
  1231  	}
  1232  }