github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/endpoint.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "strings" 8 "sync" 9 10 "github.com/docker/libnetwork/datastore" 11 "github.com/docker/libnetwork/ipamapi" 12 "github.com/docker/libnetwork/netlabel" 13 "github.com/docker/libnetwork/options" 14 "github.com/docker/libnetwork/types" 15 "github.com/sirupsen/logrus" 16 ) 17 18 // Endpoint represents a logical connection between a network and a sandbox. 19 type Endpoint interface { 20 // A system generated id for this endpoint. 21 ID() string 22 23 // Name returns the name of this endpoint. 24 Name() string 25 26 // Network returns the name of the network to which this endpoint is attached. 27 Network() string 28 29 // Join joins the sandbox to the endpoint and populates into the sandbox 30 // the network resources allocated for the endpoint. 31 Join(sandbox Sandbox, options ...EndpointOption) error 32 33 // Leave detaches the network resources populated in the sandbox. 34 Leave(sandbox Sandbox, options ...EndpointOption) error 35 36 // Return certain operational data belonging to this endpoint 37 Info() EndpointInfo 38 39 // DriverInfo returns a collection of driver operational data related to this endpoint retrieved from the driver 40 DriverInfo() (map[string]interface{}, error) 41 42 // Delete and detaches this endpoint from the network. 43 Delete(force bool) error 44 } 45 46 // EndpointOption is an option setter function type used to pass various options to Network 47 // and Endpoint interfaces methods. The various setter functions of type EndpointOption are 48 // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...) 49 type EndpointOption func(ep *endpoint) 50 51 type endpoint struct { 52 name string 53 id string 54 network *network 55 iface *endpointInterface 56 joinInfo *endpointJoinInfo 57 sandboxID string 58 locator string 59 exposedPorts []types.TransportPort 60 anonymous bool 61 disableResolution bool 62 generic map[string]interface{} 63 joinLeaveDone chan struct{} 64 prefAddress net.IP 65 prefAddressV6 net.IP 66 ipamOptions map[string]string 67 aliases map[string]string 68 myAliases []string 69 svcID string 70 svcName string 71 virtualIP net.IP 72 svcAliases []string 73 ingressPorts []*PortConfig 74 dbIndex uint64 75 dbExists bool 76 serviceEnabled bool 77 loadBalancer bool 78 sync.Mutex 79 } 80 81 func (ep *endpoint) MarshalJSON() ([]byte, error) { 82 ep.Lock() 83 defer ep.Unlock() 84 85 epMap := make(map[string]interface{}) 86 epMap["name"] = ep.name 87 epMap["id"] = ep.id 88 epMap["ep_iface"] = ep.iface 89 epMap["joinInfo"] = ep.joinInfo 90 epMap["exposed_ports"] = ep.exposedPorts 91 if ep.generic != nil { 92 epMap["generic"] = ep.generic 93 } 94 epMap["sandbox"] = ep.sandboxID 95 epMap["locator"] = ep.locator 96 epMap["anonymous"] = ep.anonymous 97 epMap["disableResolution"] = ep.disableResolution 98 epMap["myAliases"] = ep.myAliases 99 epMap["svcName"] = ep.svcName 100 epMap["svcID"] = ep.svcID 101 epMap["virtualIP"] = ep.virtualIP.String() 102 epMap["ingressPorts"] = ep.ingressPorts 103 epMap["svcAliases"] = ep.svcAliases 104 epMap["loadBalancer"] = ep.loadBalancer 105 106 return json.Marshal(epMap) 107 } 108 109 func (ep *endpoint) UnmarshalJSON(b []byte) (err error) { 110 ep.Lock() 111 defer ep.Unlock() 112 113 var epMap map[string]interface{} 114 if err := json.Unmarshal(b, &epMap); err != nil { 115 return err 116 } 117 ep.name = epMap["name"].(string) 118 ep.id = epMap["id"].(string) 119 120 ib, _ := json.Marshal(epMap["ep_iface"]) 121 json.Unmarshal(ib, &ep.iface) 122 123 jb, _ := json.Marshal(epMap["joinInfo"]) 124 json.Unmarshal(jb, &ep.joinInfo) 125 126 tb, _ := json.Marshal(epMap["exposed_ports"]) 127 var tPorts []types.TransportPort 128 json.Unmarshal(tb, &tPorts) 129 ep.exposedPorts = tPorts 130 131 cb, _ := json.Marshal(epMap["sandbox"]) 132 json.Unmarshal(cb, &ep.sandboxID) 133 134 if v, ok := epMap["generic"]; ok { 135 ep.generic = v.(map[string]interface{}) 136 137 if opt, ok := ep.generic[netlabel.PortMap]; ok { 138 pblist := []types.PortBinding{} 139 140 for i := 0; i < len(opt.([]interface{})); i++ { 141 pb := types.PortBinding{} 142 tmp := opt.([]interface{})[i].(map[string]interface{}) 143 144 bytes, err := json.Marshal(tmp) 145 if err != nil { 146 logrus.Error(err) 147 break 148 } 149 err = json.Unmarshal(bytes, &pb) 150 if err != nil { 151 logrus.Error(err) 152 break 153 } 154 pblist = append(pblist, pb) 155 } 156 ep.generic[netlabel.PortMap] = pblist 157 } 158 159 if opt, ok := ep.generic[netlabel.ExposedPorts]; ok { 160 tplist := []types.TransportPort{} 161 162 for i := 0; i < len(opt.([]interface{})); i++ { 163 tp := types.TransportPort{} 164 tmp := opt.([]interface{})[i].(map[string]interface{}) 165 166 bytes, err := json.Marshal(tmp) 167 if err != nil { 168 logrus.Error(err) 169 break 170 } 171 err = json.Unmarshal(bytes, &tp) 172 if err != nil { 173 logrus.Error(err) 174 break 175 } 176 tplist = append(tplist, tp) 177 } 178 ep.generic[netlabel.ExposedPorts] = tplist 179 180 } 181 } 182 183 if v, ok := epMap["anonymous"]; ok { 184 ep.anonymous = v.(bool) 185 } 186 if v, ok := epMap["disableResolution"]; ok { 187 ep.disableResolution = v.(bool) 188 } 189 if l, ok := epMap["locator"]; ok { 190 ep.locator = l.(string) 191 } 192 193 if sn, ok := epMap["svcName"]; ok { 194 ep.svcName = sn.(string) 195 } 196 197 if si, ok := epMap["svcID"]; ok { 198 ep.svcID = si.(string) 199 } 200 201 if vip, ok := epMap["virtualIP"]; ok { 202 ep.virtualIP = net.ParseIP(vip.(string)) 203 } 204 205 if v, ok := epMap["loadBalancer"]; ok { 206 ep.loadBalancer = v.(bool) 207 } 208 209 sal, _ := json.Marshal(epMap["svcAliases"]) 210 var svcAliases []string 211 json.Unmarshal(sal, &svcAliases) 212 ep.svcAliases = svcAliases 213 214 pc, _ := json.Marshal(epMap["ingressPorts"]) 215 var ingressPorts []*PortConfig 216 json.Unmarshal(pc, &ingressPorts) 217 ep.ingressPorts = ingressPorts 218 219 ma, _ := json.Marshal(epMap["myAliases"]) 220 var myAliases []string 221 json.Unmarshal(ma, &myAliases) 222 ep.myAliases = myAliases 223 return nil 224 } 225 226 func (ep *endpoint) New() datastore.KVObject { 227 return &endpoint{network: ep.getNetwork()} 228 } 229 230 func (ep *endpoint) CopyTo(o datastore.KVObject) error { 231 ep.Lock() 232 defer ep.Unlock() 233 234 dstEp := o.(*endpoint) 235 dstEp.name = ep.name 236 dstEp.id = ep.id 237 dstEp.sandboxID = ep.sandboxID 238 dstEp.locator = ep.locator 239 dstEp.dbIndex = ep.dbIndex 240 dstEp.dbExists = ep.dbExists 241 dstEp.anonymous = ep.anonymous 242 dstEp.disableResolution = ep.disableResolution 243 dstEp.svcName = ep.svcName 244 dstEp.svcID = ep.svcID 245 dstEp.virtualIP = ep.virtualIP 246 dstEp.loadBalancer = ep.loadBalancer 247 248 dstEp.svcAliases = make([]string, len(ep.svcAliases)) 249 copy(dstEp.svcAliases, ep.svcAliases) 250 251 dstEp.ingressPorts = make([]*PortConfig, len(ep.ingressPorts)) 252 copy(dstEp.ingressPorts, ep.ingressPorts) 253 254 if ep.iface != nil { 255 dstEp.iface = &endpointInterface{} 256 ep.iface.CopyTo(dstEp.iface) 257 } 258 259 if ep.joinInfo != nil { 260 dstEp.joinInfo = &endpointJoinInfo{} 261 ep.joinInfo.CopyTo(dstEp.joinInfo) 262 } 263 264 dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts)) 265 copy(dstEp.exposedPorts, ep.exposedPorts) 266 267 dstEp.myAliases = make([]string, len(ep.myAliases)) 268 copy(dstEp.myAliases, ep.myAliases) 269 270 dstEp.generic = options.Generic{} 271 for k, v := range ep.generic { 272 dstEp.generic[k] = v 273 } 274 275 return nil 276 } 277 278 func (ep *endpoint) ID() string { 279 ep.Lock() 280 defer ep.Unlock() 281 282 return ep.id 283 } 284 285 func (ep *endpoint) Name() string { 286 ep.Lock() 287 defer ep.Unlock() 288 289 return ep.name 290 } 291 292 func (ep *endpoint) MyAliases() []string { 293 ep.Lock() 294 defer ep.Unlock() 295 296 return ep.myAliases 297 } 298 299 func (ep *endpoint) Network() string { 300 if ep.network == nil { 301 return "" 302 } 303 304 return ep.network.name 305 } 306 307 func (ep *endpoint) isAnonymous() bool { 308 ep.Lock() 309 defer ep.Unlock() 310 return ep.anonymous 311 } 312 313 // isServiceEnabled check if service is enabled on the endpoint 314 func (ep *endpoint) isServiceEnabled() bool { 315 ep.Lock() 316 defer ep.Unlock() 317 return ep.serviceEnabled 318 } 319 320 // enableService sets service enabled on the endpoint 321 func (ep *endpoint) enableService() { 322 ep.Lock() 323 defer ep.Unlock() 324 ep.serviceEnabled = true 325 } 326 327 // disableService disables service on the endpoint 328 func (ep *endpoint) disableService() { 329 ep.Lock() 330 defer ep.Unlock() 331 ep.serviceEnabled = false 332 } 333 334 func (ep *endpoint) needResolver() bool { 335 ep.Lock() 336 defer ep.Unlock() 337 return !ep.disableResolution 338 } 339 340 // endpoint Key structure : endpoint/network-id/endpoint-id 341 func (ep *endpoint) Key() []string { 342 if ep.network == nil { 343 return nil 344 } 345 346 return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id} 347 } 348 349 func (ep *endpoint) KeyPrefix() []string { 350 if ep.network == nil { 351 return nil 352 } 353 354 return []string{datastore.EndpointKeyPrefix, ep.network.id} 355 } 356 357 func (ep *endpoint) networkIDFromKey(key string) (string, error) { 358 // endpoint Key structure : docker/libnetwork/endpoint/${network-id}/${endpoint-id} 359 // it's an invalid key if the key doesn't have all the 5 key elements above 360 keyElements := strings.Split(key, "/") 361 if !strings.HasPrefix(key, datastore.Key(datastore.EndpointKeyPrefix)) || len(keyElements) < 5 { 362 return "", fmt.Errorf("invalid endpoint key : %v", key) 363 } 364 // network-id is placed at index=3. pls refer to endpoint.Key() method 365 return strings.Split(key, "/")[3], nil 366 } 367 368 func (ep *endpoint) Value() []byte { 369 b, err := json.Marshal(ep) 370 if err != nil { 371 return nil 372 } 373 return b 374 } 375 376 func (ep *endpoint) SetValue(value []byte) error { 377 return json.Unmarshal(value, ep) 378 } 379 380 func (ep *endpoint) Index() uint64 { 381 ep.Lock() 382 defer ep.Unlock() 383 return ep.dbIndex 384 } 385 386 func (ep *endpoint) SetIndex(index uint64) { 387 ep.Lock() 388 defer ep.Unlock() 389 ep.dbIndex = index 390 ep.dbExists = true 391 } 392 393 func (ep *endpoint) Exists() bool { 394 ep.Lock() 395 defer ep.Unlock() 396 return ep.dbExists 397 } 398 399 func (ep *endpoint) Skip() bool { 400 return ep.getNetwork().Skip() 401 } 402 403 func (ep *endpoint) processOptions(options ...EndpointOption) { 404 ep.Lock() 405 defer ep.Unlock() 406 407 for _, opt := range options { 408 if opt != nil { 409 opt(ep) 410 } 411 } 412 } 413 414 func (ep *endpoint) getNetwork() *network { 415 ep.Lock() 416 defer ep.Unlock() 417 418 return ep.network 419 } 420 421 func (ep *endpoint) getNetworkFromStore() (*network, error) { 422 if ep.network == nil { 423 return nil, fmt.Errorf("invalid network object in endpoint %s", ep.Name()) 424 } 425 426 return ep.network.getController().getNetworkFromStore(ep.network.id) 427 } 428 429 func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error { 430 if sbox == nil { 431 return types.BadRequestErrorf("endpoint cannot be joined by nil container") 432 } 433 434 sb, ok := sbox.(*sandbox) 435 if !ok { 436 return types.BadRequestErrorf("not a valid Sandbox interface") 437 } 438 439 sb.joinLeaveStart() 440 defer sb.joinLeaveEnd() 441 442 return ep.sbJoin(sb, options...) 443 } 444 445 func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) { 446 n, err := ep.getNetworkFromStore() 447 if err != nil { 448 return fmt.Errorf("failed to get network from store during join: %v", err) 449 } 450 451 ep, err = n.getEndpointFromStore(ep.ID()) 452 if err != nil { 453 return fmt.Errorf("failed to get endpoint from store during join: %v", err) 454 } 455 456 ep.Lock() 457 if ep.sandboxID != "" { 458 ep.Unlock() 459 return types.ForbiddenErrorf("another container is attached to the same network endpoint") 460 } 461 ep.network = n 462 ep.sandboxID = sb.ID() 463 ep.joinInfo = &endpointJoinInfo{} 464 epid := ep.id 465 ep.Unlock() 466 defer func() { 467 if err != nil { 468 ep.Lock() 469 ep.sandboxID = "" 470 ep.Unlock() 471 } 472 }() 473 474 nid := n.ID() 475 476 ep.processOptions(options...) 477 478 d, err := n.driver(true) 479 if err != nil { 480 return fmt.Errorf("failed to get driver during join: %v", err) 481 } 482 483 err = d.Join(nid, epid, sb.Key(), ep, sb.Labels()) 484 if err != nil { 485 return err 486 } 487 defer func() { 488 if err != nil { 489 if e := d.Leave(nid, epid); e != nil { 490 logrus.Warnf("driver leave failed while rolling back join: %v", e) 491 } 492 } 493 }() 494 495 // Watch for service records 496 if !n.getController().isAgent() { 497 n.getController().watchSvcRecord(ep) 498 } 499 500 if doUpdateHostsFile(n, sb) { 501 var addresses []string 502 if ip := ep.getFirstInterfaceIPv4Address(); ip != nil { 503 addresses = append(addresses, ip.String()) 504 } 505 if ip := ep.getFirstInterfaceIPv6Address(); ip != nil { 506 addresses = append(addresses, ip.String()) 507 } 508 if err = sb.updateHostsFile(addresses); err != nil { 509 return err 510 } 511 } 512 if err = sb.updateDNS(n.enableIPv6); err != nil { 513 return err 514 } 515 516 // Current endpoint providing external connectivity for the sandbox 517 extEp := sb.getGatewayEndpoint() 518 519 sb.addEndpoint(ep) 520 defer func() { 521 if err != nil { 522 sb.removeEndpoint(ep) 523 } 524 }() 525 526 if err = sb.populateNetworkResources(ep); err != nil { 527 return err 528 } 529 530 if err = n.getController().updateToStore(ep); err != nil { 531 return err 532 } 533 534 if err = ep.addDriverInfoToCluster(); err != nil { 535 return err 536 } 537 538 defer func() { 539 if err != nil { 540 if e := ep.deleteDriverInfoFromCluster(); e != nil { 541 logrus.Errorf("Could not delete endpoint state for endpoint %s from cluster on join failure: %v", ep.Name(), e) 542 } 543 } 544 }() 545 546 // Load balancing endpoints should never have a default gateway nor 547 // should they alter the status of a network's default gateway 548 if ep.loadBalancer && !sb.ingress { 549 return nil 550 } 551 552 if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil { 553 return sb.setupDefaultGW() 554 } 555 556 moveExtConn := sb.getGatewayEndpoint() != extEp 557 558 if moveExtConn { 559 if extEp != nil { 560 logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID()) 561 extN, err := extEp.getNetworkFromStore() 562 if err != nil { 563 return fmt.Errorf("failed to get network from store for revoking external connectivity during join: %v", err) 564 } 565 extD, err := extN.driver(true) 566 if err != nil { 567 return fmt.Errorf("failed to get driver for revoking external connectivity during join: %v", err) 568 } 569 if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil { 570 return types.InternalErrorf( 571 "driver failed revoking external connectivity on endpoint %s (%s): %v", 572 extEp.Name(), extEp.ID(), err) 573 } 574 defer func() { 575 if err != nil { 576 if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil { 577 logrus.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v", 578 extEp.Name(), extEp.ID(), e) 579 } 580 } 581 }() 582 } 583 if !n.internal { 584 logrus.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID()) 585 if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil { 586 return types.InternalErrorf( 587 "driver failed programming external connectivity on endpoint %s (%s): %v", 588 ep.Name(), ep.ID(), err) 589 } 590 } 591 592 } 593 594 if !sb.needDefaultGW() { 595 if e := sb.clearDefaultGW(); e != nil { 596 logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v", 597 sb.ID(), sb.ContainerID(), e) 598 } 599 } 600 601 return nil 602 } 603 604 func doUpdateHostsFile(n *network, sb *sandbox) bool { 605 return !n.ingress && n.Name() != libnGWNetwork 606 } 607 608 func (ep *endpoint) rename(name string) error { 609 var ( 610 err error 611 netWatch *netWatch 612 ok bool 613 ) 614 615 n := ep.getNetwork() 616 if n == nil { 617 return fmt.Errorf("network not connected for ep %q", ep.name) 618 } 619 620 c := n.getController() 621 622 sb, ok := ep.getSandbox() 623 if !ok { 624 logrus.Warnf("rename for %s aborted, sandbox %s is not anymore present", ep.ID(), ep.sandboxID) 625 return nil 626 } 627 628 if c.isAgent() { 629 if err = ep.deleteServiceInfoFromCluster(sb, true, "rename"); err != nil { 630 return types.InternalErrorf("Could not delete service state for endpoint %s from cluster on rename: %v", ep.Name(), err) 631 } 632 } else { 633 c.Lock() 634 netWatch, ok = c.nmap[n.ID()] 635 c.Unlock() 636 if !ok { 637 return fmt.Errorf("watch null for network %q", n.Name()) 638 } 639 n.updateSvcRecord(ep, c.getLocalEps(netWatch), false) 640 } 641 642 oldName := ep.name 643 oldAnonymous := ep.anonymous 644 ep.name = name 645 ep.anonymous = false 646 647 if c.isAgent() { 648 if err = ep.addServiceInfoToCluster(sb); err != nil { 649 return types.InternalErrorf("Could not add service state for endpoint %s to cluster on rename: %v", ep.Name(), err) 650 } 651 defer func() { 652 if err != nil { 653 ep.deleteServiceInfoFromCluster(sb, true, "rename") 654 ep.name = oldName 655 ep.anonymous = oldAnonymous 656 ep.addServiceInfoToCluster(sb) 657 } 658 }() 659 } else { 660 n.updateSvcRecord(ep, c.getLocalEps(netWatch), true) 661 defer func() { 662 if err != nil { 663 n.updateSvcRecord(ep, c.getLocalEps(netWatch), false) 664 ep.name = oldName 665 ep.anonymous = oldAnonymous 666 n.updateSvcRecord(ep, c.getLocalEps(netWatch), true) 667 } 668 }() 669 } 670 671 // Update the store with the updated name 672 if err = c.updateToStore(ep); err != nil { 673 return err 674 } 675 // After the name change do a dummy endpoint count update to 676 // trigger the service record update in the peer nodes 677 678 // Ignore the error because updateStore fail for EpCnt is a 679 // benign error. Besides there is no meaningful recovery that 680 // we can do. When the cluster recovers subsequent EpCnt update 681 // will force the peers to get the correct EP name. 682 n.getEpCnt().updateStore() 683 684 return err 685 } 686 687 func (ep *endpoint) hasInterface(iName string) bool { 688 ep.Lock() 689 defer ep.Unlock() 690 691 return ep.iface != nil && ep.iface.srcName == iName 692 } 693 694 func (ep *endpoint) Leave(sbox Sandbox, options ...EndpointOption) error { 695 if sbox == nil || sbox.ID() == "" || sbox.Key() == "" { 696 return types.BadRequestErrorf("invalid Sandbox passed to endpoint leave: %v", sbox) 697 } 698 699 sb, ok := sbox.(*sandbox) 700 if !ok { 701 return types.BadRequestErrorf("not a valid Sandbox interface") 702 } 703 704 sb.joinLeaveStart() 705 defer sb.joinLeaveEnd() 706 707 return ep.sbLeave(sb, false, options...) 708 } 709 710 func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) error { 711 n, err := ep.getNetworkFromStore() 712 if err != nil { 713 return fmt.Errorf("failed to get network from store during leave: %v", err) 714 } 715 716 ep, err = n.getEndpointFromStore(ep.ID()) 717 if err != nil { 718 return fmt.Errorf("failed to get endpoint from store during leave: %v", err) 719 } 720 721 ep.Lock() 722 sid := ep.sandboxID 723 ep.Unlock() 724 725 if sid == "" { 726 return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox") 727 } 728 if sid != sb.ID() { 729 return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID()) 730 } 731 732 ep.processOptions(options...) 733 734 d, err := n.driver(!force) 735 if err != nil { 736 return fmt.Errorf("failed to get driver during endpoint leave: %v", err) 737 } 738 739 ep.Lock() 740 ep.sandboxID = "" 741 ep.network = n 742 ep.Unlock() 743 744 // Current endpoint providing external connectivity to the sandbox 745 extEp := sb.getGatewayEndpoint() 746 moveExtConn := extEp != nil && (extEp.ID() == ep.ID()) 747 748 if d != nil { 749 if moveExtConn { 750 logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID()) 751 if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil { 752 logrus.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v", 753 ep.Name(), ep.ID(), err) 754 } 755 } 756 757 if err := d.Leave(n.id, ep.id); err != nil { 758 if _, ok := err.(types.MaskableError); !ok { 759 logrus.Warnf("driver error disconnecting container %s : %v", ep.name, err) 760 } 761 } 762 } 763 764 if err := ep.deleteServiceInfoFromCluster(sb, true, "sbLeave"); err != nil { 765 logrus.Warnf("Failed to clean up service info on container %s disconnect: %v", ep.name, err) 766 } 767 768 if err := sb.clearNetworkResources(ep); err != nil { 769 logrus.Warnf("Failed to clean up network resources on container %s disconnect: %v", ep.name, err) 770 } 771 772 // Update the store about the sandbox detach only after we 773 // have completed sb.clearNetworkresources above to avoid 774 // spurious logs when cleaning up the sandbox when the daemon 775 // ungracefully exits and restarts before completing sandbox 776 // detach but after store has been updated. 777 if err := n.getController().updateToStore(ep); err != nil { 778 return err 779 } 780 781 if e := ep.deleteDriverInfoFromCluster(); e != nil { 782 logrus.Errorf("Failed to delete endpoint state for endpoint %s from cluster: %v", ep.Name(), e) 783 } 784 785 sb.deleteHostsEntries(n.getSvcRecords(ep)) 786 if !sb.inDelete && sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil { 787 return sb.setupDefaultGW() 788 } 789 790 // New endpoint providing external connectivity for the sandbox 791 extEp = sb.getGatewayEndpoint() 792 if moveExtConn && extEp != nil { 793 logrus.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID()) 794 extN, err := extEp.getNetworkFromStore() 795 if err != nil { 796 return fmt.Errorf("failed to get network from store for programming external connectivity during leave: %v", err) 797 } 798 extD, err := extN.driver(true) 799 if err != nil { 800 return fmt.Errorf("failed to get driver for programming external connectivity during leave: %v", err) 801 } 802 if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil { 803 logrus.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v", 804 extEp.Name(), extEp.ID(), err) 805 } 806 } 807 808 if !sb.needDefaultGW() { 809 if err := sb.clearDefaultGW(); err != nil { 810 logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v", 811 sb.ID(), sb.ContainerID(), err) 812 } 813 } 814 815 return nil 816 } 817 818 func (ep *endpoint) Delete(force bool) error { 819 var err error 820 n, err := ep.getNetworkFromStore() 821 if err != nil { 822 return fmt.Errorf("failed to get network during Delete: %v", err) 823 } 824 825 ep, err = n.getEndpointFromStore(ep.ID()) 826 if err != nil { 827 return fmt.Errorf("failed to get endpoint from store during Delete: %v", err) 828 } 829 830 ep.Lock() 831 epid := ep.id 832 name := ep.name 833 sbid := ep.sandboxID 834 ep.Unlock() 835 836 sb, _ := n.getController().SandboxByID(sbid) 837 if sb != nil && !force { 838 return &ActiveContainerError{name: name, id: epid} 839 } 840 841 if sb != nil { 842 if e := ep.sbLeave(sb.(*sandbox), force); e != nil { 843 logrus.Warnf("failed to leave sandbox for endpoint %s : %v", name, e) 844 } 845 } 846 847 if err = n.getController().deleteFromStore(ep); err != nil { 848 return err 849 } 850 851 defer func() { 852 if err != nil && !force { 853 ep.dbExists = false 854 if e := n.getController().updateToStore(ep); e != nil { 855 logrus.Warnf("failed to recreate endpoint in store %s : %v", name, e) 856 } 857 } 858 }() 859 860 // unwatch for service records 861 n.getController().unWatchSvcRecord(ep) 862 863 if err = ep.deleteEndpoint(force); err != nil && !force { 864 return err 865 } 866 867 ep.releaseAddress() 868 869 if err := n.getEpCnt().DecEndpointCnt(); err != nil { 870 logrus.Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err) 871 } 872 873 return nil 874 } 875 876 func (ep *endpoint) deleteEndpoint(force bool) error { 877 ep.Lock() 878 n := ep.network 879 name := ep.name 880 epid := ep.id 881 ep.Unlock() 882 883 driver, err := n.driver(!force) 884 if err != nil { 885 return fmt.Errorf("failed to delete endpoint: %v", err) 886 } 887 888 if driver == nil { 889 return nil 890 } 891 892 if err := driver.DeleteEndpoint(n.id, epid); err != nil { 893 if _, ok := err.(types.ForbiddenError); ok { 894 return err 895 } 896 897 if _, ok := err.(types.MaskableError); !ok { 898 logrus.Warnf("driver error deleting endpoint %s : %v", name, err) 899 } 900 } 901 902 return nil 903 } 904 905 func (ep *endpoint) getSandbox() (*sandbox, bool) { 906 c := ep.network.getController() 907 ep.Lock() 908 sid := ep.sandboxID 909 ep.Unlock() 910 911 c.Lock() 912 ps, ok := c.sandboxes[sid] 913 c.Unlock() 914 915 return ps, ok 916 } 917 918 func (ep *endpoint) getFirstInterfaceIPv4Address() net.IP { 919 ep.Lock() 920 defer ep.Unlock() 921 922 if ep.iface.addr != nil { 923 return ep.iface.addr.IP 924 } 925 926 return nil 927 } 928 929 func (ep *endpoint) getFirstInterfaceIPv6Address() net.IP { 930 ep.Lock() 931 defer ep.Unlock() 932 933 if ep.iface.addrv6 != nil { 934 return ep.iface.addrv6.IP 935 } 936 937 return nil 938 } 939 940 // EndpointOptionGeneric function returns an option setter for a Generic option defined 941 // in a Dictionary of Key-Value pair 942 func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption { 943 return func(ep *endpoint) { 944 for k, v := range generic { 945 ep.generic[k] = v 946 } 947 } 948 } 949 950 var ( 951 linkLocalMask = net.CIDRMask(16, 32) 952 linkLocalMaskIPv6 = net.CIDRMask(64, 128) 953 ) 954 955 // CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint 956 func CreateOptionIpam(ipV4, ipV6 net.IP, llIPs []net.IP, ipamOptions map[string]string) EndpointOption { 957 return func(ep *endpoint) { 958 ep.prefAddress = ipV4 959 ep.prefAddressV6 = ipV6 960 if len(llIPs) != 0 { 961 for _, ip := range llIPs { 962 nw := &net.IPNet{IP: ip, Mask: linkLocalMask} 963 if ip.To4() == nil { 964 nw.Mask = linkLocalMaskIPv6 965 } 966 ep.iface.llAddrs = append(ep.iface.llAddrs, nw) 967 } 968 } 969 ep.ipamOptions = ipamOptions 970 } 971 } 972 973 // CreateOptionExposedPorts function returns an option setter for the container exposed 974 // ports option to be passed to network.CreateEndpoint() method. 975 func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption { 976 return func(ep *endpoint) { 977 // Defensive copy 978 eps := make([]types.TransportPort, len(exposedPorts)) 979 copy(eps, exposedPorts) 980 // Store endpoint label and in generic because driver needs it 981 ep.exposedPorts = eps 982 ep.generic[netlabel.ExposedPorts] = eps 983 } 984 } 985 986 // CreateOptionPortMapping function returns an option setter for the mapping 987 // ports option to be passed to network.CreateEndpoint() method. 988 func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption { 989 return func(ep *endpoint) { 990 // Store a copy of the bindings as generic data to pass to the driver 991 pbs := make([]types.PortBinding, len(portBindings)) 992 copy(pbs, portBindings) 993 ep.generic[netlabel.PortMap] = pbs 994 } 995 } 996 997 // CreateOptionDNS function returns an option setter for dns entry option to 998 // be passed to container Create method. 999 func CreateOptionDNS(dns []string) EndpointOption { 1000 return func(ep *endpoint) { 1001 ep.generic[netlabel.DNSServers] = dns 1002 } 1003 } 1004 1005 // CreateOptionAnonymous function returns an option setter for setting 1006 // this endpoint as anonymous 1007 func CreateOptionAnonymous() EndpointOption { 1008 return func(ep *endpoint) { 1009 ep.anonymous = true 1010 } 1011 } 1012 1013 // CreateOptionDisableResolution function returns an option setter to indicate 1014 // this endpoint doesn't want embedded DNS server functionality 1015 func CreateOptionDisableResolution() EndpointOption { 1016 return func(ep *endpoint) { 1017 ep.disableResolution = true 1018 } 1019 } 1020 1021 // CreateOptionAlias function returns an option setter for setting endpoint alias 1022 func CreateOptionAlias(name string, alias string) EndpointOption { 1023 return func(ep *endpoint) { 1024 if ep.aliases == nil { 1025 ep.aliases = make(map[string]string) 1026 } 1027 ep.aliases[alias] = name 1028 } 1029 } 1030 1031 // CreateOptionService function returns an option setter for setting service binding configuration 1032 func CreateOptionService(name, id string, vip net.IP, ingressPorts []*PortConfig, aliases []string) EndpointOption { 1033 return func(ep *endpoint) { 1034 ep.svcName = name 1035 ep.svcID = id 1036 ep.virtualIP = vip 1037 ep.ingressPorts = ingressPorts 1038 ep.svcAliases = aliases 1039 } 1040 } 1041 1042 // CreateOptionMyAlias function returns an option setter for setting endpoint's self alias 1043 func CreateOptionMyAlias(alias string) EndpointOption { 1044 return func(ep *endpoint) { 1045 ep.myAliases = append(ep.myAliases, alias) 1046 } 1047 } 1048 1049 // CreateOptionLoadBalancer function returns an option setter for denoting the endpoint is a load balancer for a network 1050 func CreateOptionLoadBalancer() EndpointOption { 1051 return func(ep *endpoint) { 1052 ep.loadBalancer = true 1053 } 1054 } 1055 1056 // JoinOptionPriority function returns an option setter for priority option to 1057 // be passed to the endpoint.Join() method. 1058 func JoinOptionPriority(prio int) EndpointOption { 1059 return func(ep *endpoint) { 1060 // ep lock already acquired 1061 c := ep.network.getController() 1062 c.Lock() 1063 sb, ok := c.sandboxes[ep.sandboxID] 1064 c.Unlock() 1065 if !ok { 1066 logrus.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id) 1067 return 1068 } 1069 sb.epPriority[ep.id] = prio 1070 } 1071 } 1072 1073 func (ep *endpoint) DataScope() string { 1074 return ep.getNetwork().DataScope() 1075 } 1076 1077 func (ep *endpoint) assignAddress(ipam ipamapi.Ipam, assignIPv4, assignIPv6 bool) error { 1078 var err error 1079 1080 n := ep.getNetwork() 1081 if n.hasSpecialDriver() { 1082 return nil 1083 } 1084 1085 logrus.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name()) 1086 1087 if assignIPv4 { 1088 if err = ep.assignAddressVersion(4, ipam); err != nil { 1089 return err 1090 } 1091 } 1092 1093 if assignIPv6 { 1094 err = ep.assignAddressVersion(6, ipam) 1095 } 1096 1097 return err 1098 } 1099 1100 func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error { 1101 var ( 1102 poolID *string 1103 address **net.IPNet 1104 prefAdd net.IP 1105 progAdd net.IP 1106 ) 1107 1108 n := ep.getNetwork() 1109 switch ipVer { 1110 case 4: 1111 poolID = &ep.iface.v4PoolID 1112 address = &ep.iface.addr 1113 prefAdd = ep.prefAddress 1114 case 6: 1115 poolID = &ep.iface.v6PoolID 1116 address = &ep.iface.addrv6 1117 prefAdd = ep.prefAddressV6 1118 default: 1119 return types.InternalErrorf("incorrect ip version number passed: %d", ipVer) 1120 } 1121 1122 ipInfo := n.getIPInfo(ipVer) 1123 1124 // ipv6 address is not mandatory 1125 if len(ipInfo) == 0 && ipVer == 6 { 1126 return nil 1127 } 1128 1129 // The address to program may be chosen by the user or by the network driver in one specific 1130 // case to support backward compatibility with `docker daemon --fixed-cidrv6` use case 1131 if prefAdd != nil { 1132 progAdd = prefAdd 1133 } else if *address != nil { 1134 progAdd = (*address).IP 1135 } 1136 1137 for _, d := range ipInfo { 1138 if progAdd != nil && !d.Pool.Contains(progAdd) { 1139 continue 1140 } 1141 addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions) 1142 if err == nil { 1143 ep.Lock() 1144 *address = addr 1145 *poolID = d.PoolID 1146 ep.Unlock() 1147 return nil 1148 } 1149 if err != ipamapi.ErrNoAvailableIPs || progAdd != nil { 1150 return err 1151 } 1152 } 1153 if progAdd != nil { 1154 return types.BadRequestErrorf("Invalid address %s: It does not belong to any of this network's subnets", prefAdd) 1155 } 1156 return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID()) 1157 } 1158 1159 func (ep *endpoint) releaseAddress() { 1160 n := ep.getNetwork() 1161 if n.hasSpecialDriver() { 1162 return 1163 } 1164 1165 logrus.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name()) 1166 1167 ipam, _, err := n.getController().getIPAMDriver(n.ipamType) 1168 if err != nil { 1169 logrus.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err) 1170 return 1171 } 1172 1173 if ep.iface.addr != nil { 1174 if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil { 1175 logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err) 1176 } 1177 } 1178 1179 if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() { 1180 if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil { 1181 logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err) 1182 } 1183 } 1184 } 1185 1186 func (c *controller) cleanupLocalEndpoints() { 1187 // Get used endpoints 1188 eps := make(map[string]interface{}) 1189 for _, sb := range c.sandboxes { 1190 for _, ep := range sb.endpoints { 1191 eps[ep.id] = true 1192 } 1193 } 1194 nl, err := c.getNetworksForScope(datastore.LocalScope) 1195 if err != nil { 1196 logrus.Warnf("Could not get list of networks during endpoint cleanup: %v", err) 1197 return 1198 } 1199 1200 for _, n := range nl { 1201 if n.ConfigOnly() { 1202 continue 1203 } 1204 epl, err := n.getEndpointsFromStore() 1205 if err != nil { 1206 logrus.Warnf("Could not get list of endpoints in network %s during endpoint cleanup: %v", n.name, err) 1207 continue 1208 } 1209 1210 for _, ep := range epl { 1211 if _, ok := eps[ep.id]; ok { 1212 continue 1213 } 1214 logrus.Infof("Removing stale endpoint %s (%s)", ep.name, ep.id) 1215 if err := ep.Delete(true); err != nil { 1216 logrus.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err) 1217 } 1218 } 1219 1220 epl, err = n.getEndpointsFromStore() 1221 if err != nil { 1222 logrus.Warnf("Could not get list of endpoints in network %s for count update: %v", n.name, err) 1223 continue 1224 } 1225 1226 epCnt := n.getEpCnt().EndpointCnt() 1227 if epCnt != uint64(len(epl)) { 1228 logrus.Infof("Fixing inconsistent endpoint_cnt for network %s. Expected=%d, Actual=%d", n.name, len(epl), epCnt) 1229 n.getEpCnt().setCnt(uint64(len(epl))) 1230 } 1231 } 1232 }