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