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 }