github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/sandbox.go (about)

     1  package libnetwork
     2  
     3  import (
     4  	"container/heap"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net"
     8  	"strings"
     9  	"sync"
    10  	"time"
    11  
    12  	log "github.com/Sirupsen/logrus"
    13  	"github.com/docker/libnetwork/etchosts"
    14  	"github.com/docker/libnetwork/netlabel"
    15  	"github.com/docker/libnetwork/osl"
    16  	"github.com/docker/libnetwork/types"
    17  )
    18  
    19  // Sandbox provides the control over the network container entity. It is a one to one mapping with the container.
    20  type Sandbox interface {
    21  	// ID returns the ID of the sandbox
    22  	ID() string
    23  	// Key returns the sandbox's key
    24  	Key() string
    25  	// ContainerID returns the container id associated to this sandbox
    26  	ContainerID() string
    27  	// Labels returns the sandbox's labels
    28  	Labels() map[string]interface{}
    29  	// Statistics retrieves the interfaces' statistics for the sandbox
    30  	Statistics() (map[string]*types.InterfaceStatistics, error)
    31  	// Refresh leaves all the endpoints, resets and re-applies the options,
    32  	// re-joins all the endpoints without destroying the osl sandbox
    33  	Refresh(options ...SandboxOption) error
    34  	// SetKey updates the Sandbox Key
    35  	SetKey(key string) error
    36  	// Rename changes the name of all attached Endpoints
    37  	Rename(name string) error
    38  	// Delete destroys this container after detaching it from all connected endpoints.
    39  	Delete() error
    40  	// Endpoints returns all the endpoints connected to the sandbox
    41  	Endpoints() []Endpoint
    42  	// ResolveService returns all the backend details about the containers or hosts
    43  	// backing a service. Its purpose is to satisfy an SRV query
    44  	ResolveService(name string) ([]*net.SRV, []net.IP)
    45  }
    46  
    47  // SandboxOption is an option setter function type used to pass various options to
    48  // NewNetContainer method. The various setter functions of type SandboxOption are
    49  // provided by libnetwork, they look like ContainerOptionXXXX(...)
    50  type SandboxOption func(sb *sandbox)
    51  
    52  func (sb *sandbox) processOptions(options ...SandboxOption) {
    53  	for _, opt := range options {
    54  		if opt != nil {
    55  			opt(sb)
    56  		}
    57  	}
    58  }
    59  
    60  type epHeap []*endpoint
    61  
    62  type sandbox struct {
    63  	id                 string
    64  	containerID        string
    65  	config             containerConfig
    66  	extDNS             []string
    67  	osSbox             osl.Sandbox
    68  	controller         *controller
    69  	resolver           Resolver
    70  	resolverOnce       sync.Once
    71  	refCnt             int
    72  	endpoints          epHeap
    73  	epPriority         map[string]int
    74  	populatedEndpoints map[string]struct{}
    75  	joinLeaveDone      chan struct{}
    76  	dbIndex            uint64
    77  	dbExists           bool
    78  	isStub             bool
    79  	inDelete           bool
    80  	ingress            bool
    81  	ndotsSet           bool
    82  	sync.Mutex
    83  }
    84  
    85  // These are the container configs used to customize container /etc/hosts file.
    86  type hostsPathConfig struct {
    87  	hostName        string
    88  	domainName      string
    89  	hostsPath       string
    90  	originHostsPath string
    91  	extraHosts      []extraHost
    92  	parentUpdates   []parentUpdate
    93  }
    94  
    95  type parentUpdate struct {
    96  	cid  string
    97  	name string
    98  	ip   string
    99  }
   100  
   101  type extraHost struct {
   102  	name string
   103  	IP   string
   104  }
   105  
   106  // These are the container configs used to customize container /etc/resolv.conf file.
   107  type resolvConfPathConfig struct {
   108  	resolvConfPath       string
   109  	originResolvConfPath string
   110  	resolvConfHashFile   string
   111  	dnsList              []string
   112  	dnsSearchList        []string
   113  	dnsOptionsList       []string
   114  }
   115  
   116  type containerConfig struct {
   117  	hostsPathConfig
   118  	resolvConfPathConfig
   119  	generic           map[string]interface{}
   120  	useDefaultSandBox bool
   121  	useExternalKey    bool
   122  	prio              int // higher the value, more the priority
   123  	exposedPorts      []types.TransportPort
   124  }
   125  
   126  const (
   127  	resolverIPSandbox = "127.0.0.11"
   128  )
   129  
   130  func (sb *sandbox) ID() string {
   131  	return sb.id
   132  }
   133  
   134  func (sb *sandbox) ContainerID() string {
   135  	return sb.containerID
   136  }
   137  
   138  func (sb *sandbox) Key() string {
   139  	if sb.config.useDefaultSandBox {
   140  		return osl.GenerateKey("default")
   141  	}
   142  	return osl.GenerateKey(sb.id)
   143  }
   144  
   145  func (sb *sandbox) Labels() map[string]interface{} {
   146  	sb.Lock()
   147  	defer sb.Unlock()
   148  	opts := make(map[string]interface{}, len(sb.config.generic))
   149  	for k, v := range sb.config.generic {
   150  		opts[k] = v
   151  	}
   152  	return opts
   153  }
   154  
   155  func (sb *sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) {
   156  	m := make(map[string]*types.InterfaceStatistics)
   157  
   158  	sb.Lock()
   159  	osb := sb.osSbox
   160  	sb.Unlock()
   161  	if osb == nil {
   162  		return m, nil
   163  	}
   164  
   165  	var err error
   166  	for _, i := range osb.Info().Interfaces() {
   167  		if m[i.DstName()], err = i.Statistics(); err != nil {
   168  			return m, err
   169  		}
   170  	}
   171  
   172  	return m, nil
   173  }
   174  
   175  func (sb *sandbox) Delete() error {
   176  	return sb.delete(false)
   177  }
   178  
   179  func (sb *sandbox) delete(force bool) error {
   180  	sb.Lock()
   181  	if sb.inDelete {
   182  		sb.Unlock()
   183  		return types.ForbiddenErrorf("another sandbox delete in progress")
   184  	}
   185  	// Set the inDelete flag. This will ensure that we don't
   186  	// update the store until we have completed all the endpoint
   187  	// leaves and deletes. And when endpoint leaves and deletes
   188  	// are completed then we can finally delete the sandbox object
   189  	// altogether from the data store. If the daemon exits
   190  	// ungracefully in the middle of a sandbox delete this way we
   191  	// will have all the references to the endpoints in the
   192  	// sandbox so that we can clean them up when we restart
   193  	sb.inDelete = true
   194  	sb.Unlock()
   195  
   196  	c := sb.controller
   197  
   198  	// Detach from all endpoints
   199  	retain := false
   200  	for _, ep := range sb.getConnectedEndpoints() {
   201  		// gw network endpoint detach and removal are automatic
   202  		if ep.endpointInGWNetwork() && !force {
   203  			continue
   204  		}
   205  		// Retain the sanbdox if we can't obtain the network from store.
   206  		if _, err := c.getNetworkFromStore(ep.getNetwork().ID()); err != nil {
   207  			if c.isDistributedControl() {
   208  				retain = true
   209  			}
   210  			log.Warnf("Failed getting network for ep %s during sandbox %s delete: %v", ep.ID(), sb.ID(), err)
   211  			continue
   212  		}
   213  
   214  		if !force {
   215  			if err := ep.Leave(sb); err != nil {
   216  				log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
   217  			}
   218  		}
   219  
   220  		if err := ep.Delete(force); err != nil {
   221  			log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
   222  		}
   223  	}
   224  
   225  	if retain {
   226  		sb.Lock()
   227  		sb.inDelete = false
   228  		sb.Unlock()
   229  		return fmt.Errorf("could not cleanup all the endpoints in container %s / sandbox %s", sb.containerID, sb.id)
   230  	}
   231  	// Container is going away. Path cache in etchosts is most
   232  	// likely not required any more. Drop it.
   233  	etchosts.Drop(sb.config.hostsPath)
   234  
   235  	if sb.resolver != nil {
   236  		sb.resolver.Stop()
   237  	}
   238  
   239  	if sb.osSbox != nil && !sb.config.useDefaultSandBox {
   240  		sb.osSbox.Destroy()
   241  	}
   242  
   243  	if err := sb.storeDelete(); err != nil {
   244  		log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err)
   245  	}
   246  
   247  	c.Lock()
   248  	if sb.ingress {
   249  		c.ingressSandbox = nil
   250  	}
   251  	delete(c.sandboxes, sb.ID())
   252  	c.Unlock()
   253  
   254  	return nil
   255  }
   256  
   257  func (sb *sandbox) Rename(name string) error {
   258  	var err error
   259  
   260  	for _, ep := range sb.getConnectedEndpoints() {
   261  		if ep.endpointInGWNetwork() {
   262  			continue
   263  		}
   264  
   265  		oldName := ep.Name()
   266  		lEp := ep
   267  		if err = ep.rename(name); err != nil {
   268  			break
   269  		}
   270  
   271  		defer func() {
   272  			if err != nil {
   273  				lEp.rename(oldName)
   274  			}
   275  		}()
   276  	}
   277  
   278  	return err
   279  }
   280  
   281  func (sb *sandbox) Refresh(options ...SandboxOption) error {
   282  	// Store connected endpoints
   283  	epList := sb.getConnectedEndpoints()
   284  
   285  	// Detach from all endpoints
   286  	for _, ep := range epList {
   287  		if err := ep.Leave(sb); err != nil {
   288  			log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
   289  		}
   290  	}
   291  
   292  	// Re-apply options
   293  	sb.config = containerConfig{}
   294  	sb.processOptions(options...)
   295  
   296  	// Setup discovery files
   297  	if err := sb.setupResolutionFiles(); err != nil {
   298  		return err
   299  	}
   300  
   301  	// Re-connect to all endpoints
   302  	for _, ep := range epList {
   303  		if err := ep.Join(sb); err != nil {
   304  			log.Warnf("Failed attach sandbox %s to endpoint %s: %v\n", sb.ID(), ep.ID(), err)
   305  		}
   306  	}
   307  
   308  	return nil
   309  }
   310  
   311  func (sb *sandbox) MarshalJSON() ([]byte, error) {
   312  	sb.Lock()
   313  	defer sb.Unlock()
   314  
   315  	// We are just interested in the container ID. This can be expanded to include all of containerInfo if there is a need
   316  	return json.Marshal(sb.id)
   317  }
   318  
   319  func (sb *sandbox) UnmarshalJSON(b []byte) (err error) {
   320  	sb.Lock()
   321  	defer sb.Unlock()
   322  
   323  	var id string
   324  	if err := json.Unmarshal(b, &id); err != nil {
   325  		return err
   326  	}
   327  	sb.id = id
   328  	return nil
   329  }
   330  
   331  func (sb *sandbox) Endpoints() []Endpoint {
   332  	sb.Lock()
   333  	defer sb.Unlock()
   334  
   335  	endpoints := make([]Endpoint, len(sb.endpoints))
   336  	for i, ep := range sb.endpoints {
   337  		endpoints[i] = ep
   338  	}
   339  	return endpoints
   340  }
   341  
   342  func (sb *sandbox) getConnectedEndpoints() []*endpoint {
   343  	sb.Lock()
   344  	defer sb.Unlock()
   345  
   346  	eps := make([]*endpoint, len(sb.endpoints))
   347  	for i, ep := range sb.endpoints {
   348  		eps[i] = ep
   349  	}
   350  
   351  	return eps
   352  }
   353  
   354  func (sb *sandbox) removeEndpoint(ep *endpoint) {
   355  	sb.Lock()
   356  	defer sb.Unlock()
   357  
   358  	for i, e := range sb.endpoints {
   359  		if e == ep {
   360  			heap.Remove(&sb.endpoints, i)
   361  			return
   362  		}
   363  	}
   364  }
   365  
   366  func (sb *sandbox) getEndpoint(id string) *endpoint {
   367  	sb.Lock()
   368  	defer sb.Unlock()
   369  
   370  	for _, ep := range sb.endpoints {
   371  		if ep.id == id {
   372  			return ep
   373  		}
   374  	}
   375  
   376  	return nil
   377  }
   378  
   379  func (sb *sandbox) updateGateway(ep *endpoint) error {
   380  	sb.Lock()
   381  	osSbox := sb.osSbox
   382  	sb.Unlock()
   383  	if osSbox == nil {
   384  		return nil
   385  	}
   386  	osSbox.UnsetGateway()
   387  	osSbox.UnsetGatewayIPv6()
   388  
   389  	if ep == nil {
   390  		return nil
   391  	}
   392  
   393  	ep.Lock()
   394  	joinInfo := ep.joinInfo
   395  	ep.Unlock()
   396  
   397  	if err := osSbox.SetGateway(joinInfo.gw); err != nil {
   398  		return fmt.Errorf("failed to set gateway while updating gateway: %v", err)
   399  	}
   400  
   401  	if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil {
   402  		return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err)
   403  	}
   404  
   405  	return nil
   406  }
   407  
   408  func (sb *sandbox) ResolveIP(ip string) string {
   409  	var svc string
   410  	log.Debugf("IP To resolve %v", ip)
   411  
   412  	for _, ep := range sb.getConnectedEndpoints() {
   413  		n := ep.getNetwork()
   414  		svc = n.ResolveIP(ip)
   415  		if len(svc) != 0 {
   416  			return svc
   417  		}
   418  	}
   419  
   420  	return svc
   421  }
   422  
   423  func (sb *sandbox) ExecFunc(f func()) error {
   424  	return sb.osSbox.InvokeFunc(f)
   425  }
   426  
   427  func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) {
   428  	srv := []*net.SRV{}
   429  	ip := []net.IP{}
   430  
   431  	log.Debugf("Service name To resolve: %v", name)
   432  
   433  	// There are DNS implementaions that allow SRV queries for names not in
   434  	// the format defined by RFC 2782. Hence specific validations checks are
   435  	// not done
   436  	parts := strings.Split(name, ".")
   437  	if len(parts) < 3 {
   438  		return nil, nil
   439  	}
   440  
   441  	for _, ep := range sb.getConnectedEndpoints() {
   442  		n := ep.getNetwork()
   443  
   444  		srv, ip = n.ResolveService(name)
   445  		if len(srv) > 0 {
   446  			break
   447  		}
   448  	}
   449  	return srv, ip
   450  }
   451  
   452  func getDynamicNwEndpoints(epList []*endpoint) []*endpoint {
   453  	eps := []*endpoint{}
   454  	for _, ep := range epList {
   455  		n := ep.getNetwork()
   456  		if n.dynamic && !n.ingress {
   457  			eps = append(eps, ep)
   458  		}
   459  	}
   460  	return eps
   461  }
   462  
   463  func getIngressNwEndpoint(epList []*endpoint) *endpoint {
   464  	for _, ep := range epList {
   465  		n := ep.getNetwork()
   466  		if n.ingress {
   467  			return ep
   468  		}
   469  	}
   470  	return nil
   471  }
   472  
   473  func getLocalNwEndpoints(epList []*endpoint) []*endpoint {
   474  	eps := []*endpoint{}
   475  	for _, ep := range epList {
   476  		n := ep.getNetwork()
   477  		if !n.dynamic && !n.ingress {
   478  			eps = append(eps, ep)
   479  		}
   480  	}
   481  	return eps
   482  }
   483  
   484  func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) {
   485  	// Embedded server owns the docker network domain. Resolution should work
   486  	// for both container_name and container_name.network_name
   487  	// We allow '.' in service name and network name. For a name a.b.c.d the
   488  	// following have to tried;
   489  	// {a.b.c.d in the networks container is connected to}
   490  	// {a.b.c in network d},
   491  	// {a.b in network c.d},
   492  	// {a in network b.c.d},
   493  
   494  	log.Debugf("Name To resolve: %v", name)
   495  	name = strings.TrimSuffix(name, ".")
   496  	reqName := []string{name}
   497  	networkName := []string{""}
   498  
   499  	if strings.Contains(name, ".") {
   500  		var i int
   501  		dup := name
   502  		for {
   503  			if i = strings.LastIndex(dup, "."); i == -1 {
   504  				break
   505  			}
   506  			networkName = append(networkName, name[i+1:])
   507  			reqName = append(reqName, name[:i])
   508  
   509  			dup = dup[:i]
   510  		}
   511  	}
   512  
   513  	epList := sb.getConnectedEndpoints()
   514  
   515  	// In swarm mode services with exposed ports are connected to user overlay
   516  	// network, ingress network and docker_gwbridge network. Name resolution
   517  	// should prioritize returning the VIP/IPs on user overlay network.
   518  	newList := []*endpoint{}
   519  	if !sb.controller.isDistributedControl() {
   520  		newList = append(newList, getDynamicNwEndpoints(epList)...)
   521  		ingressEP := getIngressNwEndpoint(epList)
   522  		if ingressEP != nil {
   523  			newList = append(newList, ingressEP)
   524  		}
   525  		newList = append(newList, getLocalNwEndpoints(epList)...)
   526  		epList = newList
   527  	}
   528  
   529  	for i := 0; i < len(reqName); i++ {
   530  
   531  		// First check for local container alias
   532  		ip, ipv6Miss := sb.resolveName(reqName[i], networkName[i], epList, true, ipType)
   533  		if ip != nil {
   534  			return ip, false
   535  		}
   536  		if ipv6Miss {
   537  			return ip, ipv6Miss
   538  		}
   539  
   540  		// Resolve the actual container name
   541  		ip, ipv6Miss = sb.resolveName(reqName[i], networkName[i], epList, false, ipType)
   542  		if ip != nil {
   543  			return ip, false
   544  		}
   545  		if ipv6Miss {
   546  			return ip, ipv6Miss
   547  		}
   548  	}
   549  	return nil, false
   550  }
   551  
   552  func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) ([]net.IP, bool) {
   553  	var ipv6Miss bool
   554  
   555  	for _, ep := range epList {
   556  		name := req
   557  		n := ep.getNetwork()
   558  
   559  		if networkName != "" && networkName != n.Name() {
   560  			continue
   561  		}
   562  
   563  		if alias {
   564  			if ep.aliases == nil {
   565  				continue
   566  			}
   567  
   568  			var ok bool
   569  			ep.Lock()
   570  			name, ok = ep.aliases[req]
   571  			ep.Unlock()
   572  			if !ok {
   573  				continue
   574  			}
   575  		} else {
   576  			// If it is a regular lookup and if the requested name is an alias
   577  			// don't perform a svc lookup for this endpoint.
   578  			ep.Lock()
   579  			if _, ok := ep.aliases[req]; ok {
   580  				ep.Unlock()
   581  				continue
   582  			}
   583  			ep.Unlock()
   584  		}
   585  
   586  		ip, miss := n.ResolveName(name, ipType)
   587  
   588  		if ip != nil {
   589  			return ip, false
   590  		}
   591  
   592  		if miss {
   593  			ipv6Miss = miss
   594  		}
   595  	}
   596  	return nil, ipv6Miss
   597  }
   598  
   599  func (sb *sandbox) SetKey(basePath string) error {
   600  	start := time.Now()
   601  	defer func() {
   602  		log.Debugf("sandbox set key processing took %s for container %s", time.Now().Sub(start), sb.ContainerID())
   603  	}()
   604  
   605  	if basePath == "" {
   606  		return types.BadRequestErrorf("invalid sandbox key")
   607  	}
   608  
   609  	sb.Lock()
   610  	oldosSbox := sb.osSbox
   611  	sb.Unlock()
   612  
   613  	if oldosSbox != nil {
   614  		// If we already have an OS sandbox, release the network resources from that
   615  		// and destroy the OS snab. We are moving into a new home further down. Note that none
   616  		// of the network resources gets destroyed during the move.
   617  		sb.releaseOSSbox()
   618  	}
   619  
   620  	osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key())
   621  	if err != nil {
   622  		return err
   623  	}
   624  
   625  	sb.Lock()
   626  	sb.osSbox = osSbox
   627  	sb.Unlock()
   628  	defer func() {
   629  		if err != nil {
   630  			sb.Lock()
   631  			sb.osSbox = nil
   632  			sb.Unlock()
   633  		}
   634  	}()
   635  
   636  	// If the resolver was setup before stop it and set it up in the
   637  	// new osl sandbox.
   638  	if oldosSbox != nil && sb.resolver != nil {
   639  		sb.resolver.Stop()
   640  
   641  		if err := sb.osSbox.InvokeFunc(sb.resolver.SetupFunc(0)); err == nil {
   642  			if err := sb.resolver.Start(); err != nil {
   643  				log.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
   644  			}
   645  		} else {
   646  			log.Errorf("Resolver Setup Function failed for container %s, %q", sb.ContainerID(), err)
   647  		}
   648  	}
   649  
   650  	for _, ep := range sb.getConnectedEndpoints() {
   651  		if err = sb.populateNetworkResources(ep); err != nil {
   652  			return err
   653  		}
   654  	}
   655  	return nil
   656  }
   657  
   658  func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) {
   659  	for _, i := range osSbox.Info().Interfaces() {
   660  		// Only remove the interfaces owned by this endpoint from the sandbox.
   661  		if ep.hasInterface(i.SrcName()) {
   662  			if err := i.Remove(); err != nil {
   663  				log.Debugf("Remove interface %s failed: %v", i.SrcName(), err)
   664  			}
   665  		}
   666  	}
   667  
   668  	ep.Lock()
   669  	joinInfo := ep.joinInfo
   670  	ep.Unlock()
   671  
   672  	if joinInfo == nil {
   673  		return
   674  	}
   675  
   676  	// Remove non-interface routes.
   677  	for _, r := range joinInfo.StaticRoutes {
   678  		if err := osSbox.RemoveStaticRoute(r); err != nil {
   679  			log.Debugf("Remove route failed: %v", err)
   680  		}
   681  	}
   682  }
   683  
   684  func (sb *sandbox) releaseOSSbox() {
   685  	sb.Lock()
   686  	osSbox := sb.osSbox
   687  	sb.osSbox = nil
   688  	sb.Unlock()
   689  
   690  	if osSbox == nil {
   691  		return
   692  	}
   693  
   694  	for _, ep := range sb.getConnectedEndpoints() {
   695  		releaseOSSboxResources(osSbox, ep)
   696  	}
   697  
   698  	osSbox.Destroy()
   699  }
   700  
   701  func (sb *sandbox) restoreOslSandbox() error {
   702  	var routes []*types.StaticRoute
   703  
   704  	// restore osl sandbox
   705  	Ifaces := make(map[string][]osl.IfaceOption)
   706  	for _, ep := range sb.endpoints {
   707  		var ifaceOptions []osl.IfaceOption
   708  		ep.Lock()
   709  		joinInfo := ep.joinInfo
   710  		i := ep.iface
   711  		ep.Unlock()
   712  
   713  		if i == nil {
   714  			log.Errorf("error restoring endpoint %s for container %s", ep.Name(), sb.ContainerID())
   715  			continue
   716  		}
   717  
   718  		ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes))
   719  		if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
   720  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
   721  		}
   722  		if i.mac != nil {
   723  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
   724  		}
   725  		if len(i.llAddrs) != 0 {
   726  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs))
   727  		}
   728  		if len(ep.virtualIP) != 0 {
   729  			vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
   730  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
   731  		}
   732  		Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions
   733  		if joinInfo != nil {
   734  			for _, r := range joinInfo.StaticRoutes {
   735  				routes = append(routes, r)
   736  			}
   737  		}
   738  		if ep.needResolver() {
   739  			sb.startResolver(true)
   740  		}
   741  	}
   742  
   743  	gwep := sb.getGatewayEndpoint()
   744  	if gwep == nil {
   745  		return nil
   746  	}
   747  
   748  	// restore osl sandbox
   749  	err := sb.osSbox.Restore(Ifaces, routes, gwep.joinInfo.gw, gwep.joinInfo.gw6)
   750  	if err != nil {
   751  		return err
   752  	}
   753  
   754  	return nil
   755  }
   756  
   757  func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
   758  	sb.Lock()
   759  	if sb.osSbox == nil {
   760  		sb.Unlock()
   761  		return nil
   762  	}
   763  	inDelete := sb.inDelete
   764  	sb.Unlock()
   765  
   766  	ep.Lock()
   767  	joinInfo := ep.joinInfo
   768  	i := ep.iface
   769  	ep.Unlock()
   770  
   771  	if ep.needResolver() {
   772  		sb.startResolver(false)
   773  	}
   774  
   775  	if i != nil && i.srcName != "" {
   776  		var ifaceOptions []osl.IfaceOption
   777  
   778  		ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes))
   779  		if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
   780  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
   781  		}
   782  		if len(i.llAddrs) != 0 {
   783  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs))
   784  		}
   785  		if len(ep.virtualIP) != 0 {
   786  			vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
   787  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
   788  		}
   789  		if i.mac != nil {
   790  			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
   791  		}
   792  
   793  		if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
   794  			return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
   795  		}
   796  	}
   797  
   798  	if joinInfo != nil {
   799  		// Set up non-interface routes.
   800  		for _, r := range joinInfo.StaticRoutes {
   801  			if err := sb.osSbox.AddStaticRoute(r); err != nil {
   802  				return fmt.Errorf("failed to add static route %s: %v", r.Destination.String(), err)
   803  			}
   804  		}
   805  	}
   806  
   807  	if ep == sb.getGatewayEndpoint() {
   808  		if err := sb.updateGateway(ep); err != nil {
   809  			return err
   810  		}
   811  	}
   812  
   813  	// Make sure to add the endpoint to the populated endpoint set
   814  	// before populating loadbalancers.
   815  	sb.Lock()
   816  	sb.populatedEndpoints[ep.ID()] = struct{}{}
   817  	sb.Unlock()
   818  
   819  	// Populate load balancer only after updating all the other
   820  	// information including gateway and other routes so that
   821  	// loadbalancers are populated all the network state is in
   822  	// place in the sandbox.
   823  	sb.populateLoadbalancers(ep)
   824  
   825  	// Only update the store if we did not come here as part of
   826  	// sandbox delete. If we came here as part of delete then do
   827  	// not bother updating the store. The sandbox object will be
   828  	// deleted anyway
   829  	if !inDelete {
   830  		return sb.storeUpdate()
   831  	}
   832  
   833  	return nil
   834  }
   835  
   836  func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
   837  	ep := sb.getEndpoint(origEp.id)
   838  	if ep == nil {
   839  		return fmt.Errorf("could not find the sandbox endpoint data for endpoint %s",
   840  			origEp.id)
   841  	}
   842  
   843  	sb.Lock()
   844  	osSbox := sb.osSbox
   845  	inDelete := sb.inDelete
   846  	sb.Unlock()
   847  	if osSbox != nil {
   848  		releaseOSSboxResources(osSbox, ep)
   849  	}
   850  
   851  	sb.Lock()
   852  	delete(sb.populatedEndpoints, ep.ID())
   853  
   854  	if len(sb.endpoints) == 0 {
   855  		// sb.endpoints should never be empty and this is unexpected error condition
   856  		// We log an error message to note this down for debugging purposes.
   857  		log.Errorf("No endpoints in sandbox while trying to remove endpoint %s", ep.Name())
   858  		sb.Unlock()
   859  		return nil
   860  	}
   861  
   862  	var (
   863  		gwepBefore, gwepAfter *endpoint
   864  		index                 = -1
   865  	)
   866  	for i, e := range sb.endpoints {
   867  		if e == ep {
   868  			index = i
   869  		}
   870  		if len(e.Gateway()) > 0 && gwepBefore == nil {
   871  			gwepBefore = e
   872  		}
   873  		if index != -1 && gwepBefore != nil {
   874  			break
   875  		}
   876  	}
   877  	heap.Remove(&sb.endpoints, index)
   878  	for _, e := range sb.endpoints {
   879  		if len(e.Gateway()) > 0 {
   880  			gwepAfter = e
   881  			break
   882  		}
   883  	}
   884  	delete(sb.epPriority, ep.ID())
   885  	sb.Unlock()
   886  
   887  	if gwepAfter != nil && gwepBefore != gwepAfter {
   888  		sb.updateGateway(gwepAfter)
   889  	}
   890  
   891  	// Only update the store if we did not come here as part of
   892  	// sandbox delete. If we came here as part of delete then do
   893  	// not bother updating the store. The sandbox object will be
   894  	// deleted anyway
   895  	if !inDelete {
   896  		return sb.storeUpdate()
   897  	}
   898  
   899  	return nil
   900  }
   901  
   902  func (sb *sandbox) isEndpointPopulated(ep *endpoint) bool {
   903  	sb.Lock()
   904  	_, ok := sb.populatedEndpoints[ep.ID()]
   905  	sb.Unlock()
   906  	return ok
   907  }
   908  
   909  // joinLeaveStart waits to ensure there are no joins or leaves in progress and
   910  // marks this join/leave in progress without race
   911  func (sb *sandbox) joinLeaveStart() {
   912  	sb.Lock()
   913  	defer sb.Unlock()
   914  
   915  	for sb.joinLeaveDone != nil {
   916  		joinLeaveDone := sb.joinLeaveDone
   917  		sb.Unlock()
   918  
   919  		select {
   920  		case <-joinLeaveDone:
   921  		}
   922  
   923  		sb.Lock()
   924  	}
   925  
   926  	sb.joinLeaveDone = make(chan struct{})
   927  }
   928  
   929  // joinLeaveEnd marks the end of this join/leave operation and
   930  // signals the same without race to other join and leave waiters
   931  func (sb *sandbox) joinLeaveEnd() {
   932  	sb.Lock()
   933  	defer sb.Unlock()
   934  
   935  	if sb.joinLeaveDone != nil {
   936  		close(sb.joinLeaveDone)
   937  		sb.joinLeaveDone = nil
   938  	}
   939  }
   940  
   941  func (sb *sandbox) hasPortConfigs() bool {
   942  	opts := sb.Labels()
   943  	_, hasExpPorts := opts[netlabel.ExposedPorts]
   944  	_, hasPortMaps := opts[netlabel.PortMap]
   945  	return hasExpPorts || hasPortMaps
   946  }
   947  
   948  // OptionHostname function returns an option setter for hostname option to
   949  // be passed to NewSandbox method.
   950  func OptionHostname(name string) SandboxOption {
   951  	return func(sb *sandbox) {
   952  		sb.config.hostName = name
   953  	}
   954  }
   955  
   956  // OptionDomainname function returns an option setter for domainname option to
   957  // be passed to NewSandbox method.
   958  func OptionDomainname(name string) SandboxOption {
   959  	return func(sb *sandbox) {
   960  		sb.config.domainName = name
   961  	}
   962  }
   963  
   964  // OptionHostsPath function returns an option setter for hostspath option to
   965  // be passed to NewSandbox method.
   966  func OptionHostsPath(path string) SandboxOption {
   967  	return func(sb *sandbox) {
   968  		sb.config.hostsPath = path
   969  	}
   970  }
   971  
   972  // OptionOriginHostsPath function returns an option setter for origin hosts file path
   973  // to be passed to NewSandbox method.
   974  func OptionOriginHostsPath(path string) SandboxOption {
   975  	return func(sb *sandbox) {
   976  		sb.config.originHostsPath = path
   977  	}
   978  }
   979  
   980  // OptionExtraHost function returns an option setter for extra /etc/hosts options
   981  // which is a name and IP as strings.
   982  func OptionExtraHost(name string, IP string) SandboxOption {
   983  	return func(sb *sandbox) {
   984  		sb.config.extraHosts = append(sb.config.extraHosts, extraHost{name: name, IP: IP})
   985  	}
   986  }
   987  
   988  // OptionParentUpdate function returns an option setter for parent container
   989  // which needs to update the IP address for the linked container.
   990  func OptionParentUpdate(cid string, name, ip string) SandboxOption {
   991  	return func(sb *sandbox) {
   992  		sb.config.parentUpdates = append(sb.config.parentUpdates, parentUpdate{cid: cid, name: name, ip: ip})
   993  	}
   994  }
   995  
   996  // OptionResolvConfPath function returns an option setter for resolvconfpath option to
   997  // be passed to net container methods.
   998  func OptionResolvConfPath(path string) SandboxOption {
   999  	return func(sb *sandbox) {
  1000  		sb.config.resolvConfPath = path
  1001  	}
  1002  }
  1003  
  1004  // OptionOriginResolvConfPath function returns an option setter to set the path to the
  1005  // origin resolv.conf file to be passed to net container methods.
  1006  func OptionOriginResolvConfPath(path string) SandboxOption {
  1007  	return func(sb *sandbox) {
  1008  		sb.config.originResolvConfPath = path
  1009  	}
  1010  }
  1011  
  1012  // OptionDNS function returns an option setter for dns entry option to
  1013  // be passed to container Create method.
  1014  func OptionDNS(dns string) SandboxOption {
  1015  	return func(sb *sandbox) {
  1016  		sb.config.dnsList = append(sb.config.dnsList, dns)
  1017  	}
  1018  }
  1019  
  1020  // OptionDNSSearch function returns an option setter for dns search entry option to
  1021  // be passed to container Create method.
  1022  func OptionDNSSearch(search string) SandboxOption {
  1023  	return func(sb *sandbox) {
  1024  		sb.config.dnsSearchList = append(sb.config.dnsSearchList, search)
  1025  	}
  1026  }
  1027  
  1028  // OptionDNSOptions function returns an option setter for dns options entry option to
  1029  // be passed to container Create method.
  1030  func OptionDNSOptions(options string) SandboxOption {
  1031  	return func(sb *sandbox) {
  1032  		sb.config.dnsOptionsList = append(sb.config.dnsOptionsList, options)
  1033  	}
  1034  }
  1035  
  1036  // OptionUseDefaultSandbox function returns an option setter for using default sandbox to
  1037  // be passed to container Create method.
  1038  func OptionUseDefaultSandbox() SandboxOption {
  1039  	return func(sb *sandbox) {
  1040  		sb.config.useDefaultSandBox = true
  1041  	}
  1042  }
  1043  
  1044  // OptionUseExternalKey function returns an option setter for using provided namespace
  1045  // instead of creating one.
  1046  func OptionUseExternalKey() SandboxOption {
  1047  	return func(sb *sandbox) {
  1048  		sb.config.useExternalKey = true
  1049  	}
  1050  }
  1051  
  1052  // OptionGeneric function returns an option setter for Generic configuration
  1053  // that is not managed by libNetwork but can be used by the Drivers during the call to
  1054  // net container creation method. Container Labels are a good example.
  1055  func OptionGeneric(generic map[string]interface{}) SandboxOption {
  1056  	return func(sb *sandbox) {
  1057  		if sb.config.generic == nil {
  1058  			sb.config.generic = make(map[string]interface{}, len(generic))
  1059  		}
  1060  		for k, v := range generic {
  1061  			sb.config.generic[k] = v
  1062  		}
  1063  	}
  1064  }
  1065  
  1066  // OptionExposedPorts function returns an option setter for the container exposed
  1067  // ports option to be passed to container Create method.
  1068  func OptionExposedPorts(exposedPorts []types.TransportPort) SandboxOption {
  1069  	return func(sb *sandbox) {
  1070  		if sb.config.generic == nil {
  1071  			sb.config.generic = make(map[string]interface{})
  1072  		}
  1073  		// Defensive copy
  1074  		eps := make([]types.TransportPort, len(exposedPorts))
  1075  		copy(eps, exposedPorts)
  1076  		// Store endpoint label and in generic because driver needs it
  1077  		sb.config.exposedPorts = eps
  1078  		sb.config.generic[netlabel.ExposedPorts] = eps
  1079  	}
  1080  }
  1081  
  1082  // OptionPortMapping function returns an option setter for the mapping
  1083  // ports option to be passed to container Create method.
  1084  func OptionPortMapping(portBindings []types.PortBinding) SandboxOption {
  1085  	return func(sb *sandbox) {
  1086  		if sb.config.generic == nil {
  1087  			sb.config.generic = make(map[string]interface{})
  1088  		}
  1089  		// Store a copy of the bindings as generic data to pass to the driver
  1090  		pbs := make([]types.PortBinding, len(portBindings))
  1091  		copy(pbs, portBindings)
  1092  		sb.config.generic[netlabel.PortMap] = pbs
  1093  	}
  1094  }
  1095  
  1096  // OptionIngress function returns an option setter for marking a
  1097  // sandbox as the controller's ingress sandbox.
  1098  func OptionIngress() SandboxOption {
  1099  	return func(sb *sandbox) {
  1100  		sb.ingress = true
  1101  	}
  1102  }
  1103  
  1104  func (eh epHeap) Len() int { return len(eh) }
  1105  
  1106  func (eh epHeap) Less(i, j int) bool {
  1107  	var (
  1108  		cip, cjp int
  1109  		ok       bool
  1110  	)
  1111  
  1112  	ci, _ := eh[i].getSandbox()
  1113  	cj, _ := eh[j].getSandbox()
  1114  
  1115  	epi := eh[i]
  1116  	epj := eh[j]
  1117  
  1118  	if epi.endpointInGWNetwork() {
  1119  		return false
  1120  	}
  1121  
  1122  	if epj.endpointInGWNetwork() {
  1123  		return true
  1124  	}
  1125  
  1126  	if epi.getNetwork().Internal() {
  1127  		return false
  1128  	}
  1129  
  1130  	if epj.getNetwork().Internal() {
  1131  		return true
  1132  	}
  1133  
  1134  	if ci != nil {
  1135  		cip, ok = ci.epPriority[eh[i].ID()]
  1136  		if !ok {
  1137  			cip = 0
  1138  		}
  1139  	}
  1140  
  1141  	if cj != nil {
  1142  		cjp, ok = cj.epPriority[eh[j].ID()]
  1143  		if !ok {
  1144  			cjp = 0
  1145  		}
  1146  	}
  1147  
  1148  	if cip == cjp {
  1149  		return eh[i].network.Name() < eh[j].network.Name()
  1150  	}
  1151  
  1152  	return cip > cjp
  1153  }
  1154  
  1155  func (eh epHeap) Swap(i, j int) { eh[i], eh[j] = eh[j], eh[i] }
  1156  
  1157  func (eh *epHeap) Push(x interface{}) {
  1158  	*eh = append(*eh, x.(*endpoint))
  1159  }
  1160  
  1161  func (eh *epHeap) Pop() interface{} {
  1162  	old := *eh
  1163  	n := len(old)
  1164  	x := old[n-1]
  1165  	*eh = old[0 : n-1]
  1166  	return x
  1167  }
  1168  
  1169  func (sb *sandbox) NdotsSet() bool {
  1170  	return sb.ndotsSet
  1171  }