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 }