github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/sandbox.go (about)

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