github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/network.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "strings" 8 "sync" 9 "time" 10 11 "github.com/docker/docker/pkg/stringid" 12 "github.com/docker/libnetwork/config" 13 "github.com/docker/libnetwork/datastore" 14 "github.com/docker/libnetwork/driverapi" 15 "github.com/docker/libnetwork/etchosts" 16 "github.com/docker/libnetwork/internal/setmatrix" 17 "github.com/docker/libnetwork/ipamapi" 18 "github.com/docker/libnetwork/netlabel" 19 "github.com/docker/libnetwork/netutils" 20 "github.com/docker/libnetwork/networkdb" 21 "github.com/docker/libnetwork/options" 22 "github.com/docker/libnetwork/types" 23 "github.com/sirupsen/logrus" 24 ) 25 26 // A Network represents a logical connectivity zone that containers may 27 // join using the Link method. A Network is managed by a specific driver. 28 type Network interface { 29 // A user chosen name for this network. 30 Name() string 31 32 // A system generated id for this network. 33 ID() string 34 35 // The type of network, which corresponds to its managing driver. 36 Type() string 37 38 // Create a new endpoint to this network symbolically identified by the 39 // specified unique name. The options parameter carries driver specific options. 40 CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) 41 42 // Delete the network. 43 Delete(options ...NetworkDeleteOption) error 44 45 // Endpoints returns the list of Endpoint(s) in this network. 46 Endpoints() []Endpoint 47 48 // WalkEndpoints uses the provided function to walk the Endpoints 49 WalkEndpoints(walker EndpointWalker) 50 51 // EndpointByName returns the Endpoint which has the passed name. If not found, the error ErrNoSuchEndpoint is returned. 52 EndpointByName(name string) (Endpoint, error) 53 54 // EndpointByID returns the Endpoint which has the passed id. If not found, the error ErrNoSuchEndpoint is returned. 55 EndpointByID(id string) (Endpoint, error) 56 57 // Return certain operational data belonging to this network 58 Info() NetworkInfo 59 } 60 61 // NetworkInfo returns some configuration and operational information about the network 62 type NetworkInfo interface { 63 IpamConfig() (string, map[string]string, []*IpamConf, []*IpamConf) 64 IpamInfo() ([]*IpamInfo, []*IpamInfo) 65 DriverOptions() map[string]string 66 Scope() string 67 IPv6Enabled() bool 68 Internal() bool 69 Attachable() bool 70 Ingress() bool 71 ConfigFrom() string 72 ConfigOnly() bool 73 Labels() map[string]string 74 Dynamic() bool 75 Created() time.Time 76 // Peers returns a slice of PeerInfo structures which has the information about the peer 77 // nodes participating in the same overlay network. This is currently the per-network 78 // gossip cluster. For non-dynamic overlay networks and bridge networks it returns an 79 // empty slice 80 Peers() []networkdb.PeerInfo 81 //Services returns a map of services keyed by the service name with the details 82 //of all the tasks that belong to the service. Applicable only in swarm mode. 83 Services() map[string]ServiceInfo 84 } 85 86 // EndpointWalker is a client provided function which will be used to walk the Endpoints. 87 // When the function returns true, the walk will stop. 88 type EndpointWalker func(ep Endpoint) bool 89 90 // ipInfo is the reverse mapping from IP to service name to serve the PTR query. 91 // extResolver is set if an external server resolves a service name to this IP. 92 // Its an indication to defer PTR queries also to that external server. 93 type ipInfo struct { 94 name string 95 serviceID string 96 extResolver bool 97 } 98 99 // svcMapEntry is the body of the element into the svcMap 100 // The ip is a string because the SetMatrix does not accept non hashable values 101 type svcMapEntry struct { 102 ip string 103 serviceID string 104 } 105 106 type svcInfo struct { 107 svcMap setmatrix.SetMatrix 108 svcIPv6Map setmatrix.SetMatrix 109 ipMap setmatrix.SetMatrix 110 service map[string][]servicePorts 111 } 112 113 // backing container or host's info 114 type serviceTarget struct { 115 name string 116 ip net.IP 117 port uint16 118 } 119 120 type servicePorts struct { 121 portName string 122 proto string 123 target []serviceTarget 124 } 125 126 type networkDBTable struct { 127 name string 128 objType driverapi.ObjectType 129 } 130 131 // IpamConf contains all the ipam related configurations for a network 132 type IpamConf struct { 133 // The master address pool for containers and network interfaces 134 PreferredPool string 135 // A subset of the master pool. If specified, 136 // this becomes the container pool 137 SubPool string 138 // Preferred Network Gateway address (optional) 139 Gateway string 140 // Auxiliary addresses for network driver. Must be within the master pool. 141 // libnetwork will reserve them if they fall into the container pool 142 AuxAddresses map[string]string 143 } 144 145 // Validate checks whether the configuration is valid 146 func (c *IpamConf) Validate() error { 147 if c.Gateway != "" && nil == net.ParseIP(c.Gateway) { 148 return types.BadRequestErrorf("invalid gateway address %s in Ipam configuration", c.Gateway) 149 } 150 return nil 151 } 152 153 // IpamInfo contains all the ipam related operational info for a network 154 type IpamInfo struct { 155 PoolID string 156 Meta map[string]string 157 driverapi.IPAMData 158 } 159 160 // MarshalJSON encodes IpamInfo into json message 161 func (i *IpamInfo) MarshalJSON() ([]byte, error) { 162 m := map[string]interface{}{ 163 "PoolID": i.PoolID, 164 } 165 v, err := json.Marshal(&i.IPAMData) 166 if err != nil { 167 return nil, err 168 } 169 m["IPAMData"] = string(v) 170 171 if i.Meta != nil { 172 m["Meta"] = i.Meta 173 } 174 return json.Marshal(m) 175 } 176 177 // UnmarshalJSON decodes json message into PoolData 178 func (i *IpamInfo) UnmarshalJSON(data []byte) error { 179 var ( 180 m map[string]interface{} 181 err error 182 ) 183 if err = json.Unmarshal(data, &m); err != nil { 184 return err 185 } 186 i.PoolID = m["PoolID"].(string) 187 if v, ok := m["Meta"]; ok { 188 b, _ := json.Marshal(v) 189 if err = json.Unmarshal(b, &i.Meta); err != nil { 190 return err 191 } 192 } 193 if v, ok := m["IPAMData"]; ok { 194 if err = json.Unmarshal([]byte(v.(string)), &i.IPAMData); err != nil { 195 return err 196 } 197 } 198 return nil 199 } 200 201 type network struct { 202 ctrlr *controller 203 name string 204 networkType string 205 id string 206 created time.Time 207 scope string // network data scope 208 labels map[string]string 209 ipamType string 210 ipamOptions map[string]string 211 addrSpace string 212 ipamV4Config []*IpamConf 213 ipamV6Config []*IpamConf 214 ipamV4Info []*IpamInfo 215 ipamV6Info []*IpamInfo 216 enableIPv6 bool 217 postIPv6 bool 218 epCnt *endpointCnt 219 generic options.Generic 220 dbIndex uint64 221 dbExists bool 222 persist bool 223 stopWatchCh chan struct{} 224 drvOnce *sync.Once 225 resolverOnce sync.Once 226 resolver []Resolver 227 internal bool 228 attachable bool 229 inDelete bool 230 ingress bool 231 driverTables []networkDBTable 232 dynamic bool 233 configOnly bool 234 configFrom string 235 loadBalancerIP net.IP 236 loadBalancerMode string 237 sync.Mutex 238 } 239 240 const ( 241 loadBalancerModeNAT = "NAT" 242 loadBalancerModeDSR = "DSR" 243 loadBalancerModeDefault = loadBalancerModeNAT 244 ) 245 246 func (n *network) Name() string { 247 n.Lock() 248 defer n.Unlock() 249 250 return n.name 251 } 252 253 func (n *network) ID() string { 254 n.Lock() 255 defer n.Unlock() 256 257 return n.id 258 } 259 260 func (n *network) Created() time.Time { 261 n.Lock() 262 defer n.Unlock() 263 264 return n.created 265 } 266 267 func (n *network) Type() string { 268 n.Lock() 269 defer n.Unlock() 270 271 return n.networkType 272 } 273 274 func (n *network) Key() []string { 275 n.Lock() 276 defer n.Unlock() 277 return []string{datastore.NetworkKeyPrefix, n.id} 278 } 279 280 func (n *network) KeyPrefix() []string { 281 return []string{datastore.NetworkKeyPrefix} 282 } 283 284 func (n *network) Value() []byte { 285 n.Lock() 286 defer n.Unlock() 287 b, err := json.Marshal(n) 288 if err != nil { 289 return nil 290 } 291 return b 292 } 293 294 func (n *network) SetValue(value []byte) error { 295 return json.Unmarshal(value, n) 296 } 297 298 func (n *network) Index() uint64 { 299 n.Lock() 300 defer n.Unlock() 301 return n.dbIndex 302 } 303 304 func (n *network) SetIndex(index uint64) { 305 n.Lock() 306 n.dbIndex = index 307 n.dbExists = true 308 n.Unlock() 309 } 310 311 func (n *network) Exists() bool { 312 n.Lock() 313 defer n.Unlock() 314 return n.dbExists 315 } 316 317 func (n *network) Skip() bool { 318 n.Lock() 319 defer n.Unlock() 320 return !n.persist 321 } 322 323 func (n *network) New() datastore.KVObject { 324 n.Lock() 325 defer n.Unlock() 326 327 return &network{ 328 ctrlr: n.ctrlr, 329 drvOnce: &sync.Once{}, 330 scope: n.scope, 331 } 332 } 333 334 // CopyTo deep copies to the destination IpamConfig 335 func (c *IpamConf) CopyTo(dstC *IpamConf) error { 336 dstC.PreferredPool = c.PreferredPool 337 dstC.SubPool = c.SubPool 338 dstC.Gateway = c.Gateway 339 if c.AuxAddresses != nil { 340 dstC.AuxAddresses = make(map[string]string, len(c.AuxAddresses)) 341 for k, v := range c.AuxAddresses { 342 dstC.AuxAddresses[k] = v 343 } 344 } 345 return nil 346 } 347 348 // CopyTo deep copies to the destination IpamInfo 349 func (i *IpamInfo) CopyTo(dstI *IpamInfo) error { 350 dstI.PoolID = i.PoolID 351 if i.Meta != nil { 352 dstI.Meta = make(map[string]string) 353 for k, v := range i.Meta { 354 dstI.Meta[k] = v 355 } 356 } 357 358 dstI.AddressSpace = i.AddressSpace 359 dstI.Pool = types.GetIPNetCopy(i.Pool) 360 dstI.Gateway = types.GetIPNetCopy(i.Gateway) 361 362 if i.AuxAddresses != nil { 363 dstI.AuxAddresses = make(map[string]*net.IPNet) 364 for k, v := range i.AuxAddresses { 365 dstI.AuxAddresses[k] = types.GetIPNetCopy(v) 366 } 367 } 368 369 return nil 370 } 371 372 func (n *network) validateConfiguration() error { 373 if n.configOnly { 374 // Only supports network specific configurations. 375 // Network operator configurations are not supported. 376 if n.ingress || n.internal || n.attachable || n.scope != "" { 377 return types.ForbiddenErrorf("configuration network can only contain network " + 378 "specific fields. Network operator fields like " + 379 "[ ingress | internal | attachable | scope ] are not supported.") 380 } 381 } 382 if n.configFrom != "" { 383 if n.configOnly { 384 return types.ForbiddenErrorf("a configuration network cannot depend on another configuration network") 385 } 386 if n.ipamType != "" && 387 n.ipamType != defaultIpamForNetworkType(n.networkType) || 388 n.enableIPv6 || 389 len(n.labels) > 0 || len(n.ipamOptions) > 0 || 390 len(n.ipamV4Config) > 0 || len(n.ipamV6Config) > 0 { 391 return types.ForbiddenErrorf("user specified configurations are not supported if the network depends on a configuration network") 392 } 393 if len(n.generic) > 0 { 394 if data, ok := n.generic[netlabel.GenericData]; ok { 395 var ( 396 driverOptions map[string]string 397 opts interface{} 398 ) 399 switch t := data.(type) { 400 case map[string]interface{}, map[string]string: 401 opts = t 402 } 403 ba, err := json.Marshal(opts) 404 if err != nil { 405 return fmt.Errorf("failed to validate network configuration: %v", err) 406 } 407 if err := json.Unmarshal(ba, &driverOptions); err != nil { 408 return fmt.Errorf("failed to validate network configuration: %v", err) 409 } 410 if len(driverOptions) > 0 { 411 return types.ForbiddenErrorf("network driver options are not supported if the network depends on a configuration network") 412 } 413 } 414 } 415 } 416 return nil 417 } 418 419 // Applies network specific configurations 420 func (n *network) applyConfigurationTo(to *network) error { 421 to.enableIPv6 = n.enableIPv6 422 if len(n.labels) > 0 { 423 to.labels = make(map[string]string, len(n.labels)) 424 for k, v := range n.labels { 425 if _, ok := to.labels[k]; !ok { 426 to.labels[k] = v 427 } 428 } 429 } 430 if len(n.ipamType) != 0 { 431 to.ipamType = n.ipamType 432 } 433 if len(n.ipamOptions) > 0 { 434 to.ipamOptions = make(map[string]string, len(n.ipamOptions)) 435 for k, v := range n.ipamOptions { 436 if _, ok := to.ipamOptions[k]; !ok { 437 to.ipamOptions[k] = v 438 } 439 } 440 } 441 if len(n.ipamV4Config) > 0 { 442 to.ipamV4Config = make([]*IpamConf, 0, len(n.ipamV4Config)) 443 to.ipamV4Config = append(to.ipamV4Config, n.ipamV4Config...) 444 } 445 if len(n.ipamV6Config) > 0 { 446 to.ipamV6Config = make([]*IpamConf, 0, len(n.ipamV6Config)) 447 to.ipamV6Config = append(to.ipamV6Config, n.ipamV6Config...) 448 } 449 if len(n.generic) > 0 { 450 to.generic = options.Generic{} 451 for k, v := range n.generic { 452 to.generic[k] = v 453 } 454 } 455 return nil 456 } 457 458 func (n *network) CopyTo(o datastore.KVObject) error { 459 n.Lock() 460 defer n.Unlock() 461 462 dstN := o.(*network) 463 dstN.name = n.name 464 dstN.id = n.id 465 dstN.created = n.created 466 dstN.networkType = n.networkType 467 dstN.scope = n.scope 468 dstN.dynamic = n.dynamic 469 dstN.ipamType = n.ipamType 470 dstN.enableIPv6 = n.enableIPv6 471 dstN.persist = n.persist 472 dstN.postIPv6 = n.postIPv6 473 dstN.dbIndex = n.dbIndex 474 dstN.dbExists = n.dbExists 475 dstN.drvOnce = n.drvOnce 476 dstN.internal = n.internal 477 dstN.attachable = n.attachable 478 dstN.inDelete = n.inDelete 479 dstN.ingress = n.ingress 480 dstN.configOnly = n.configOnly 481 dstN.configFrom = n.configFrom 482 dstN.loadBalancerIP = n.loadBalancerIP 483 dstN.loadBalancerMode = n.loadBalancerMode 484 485 // copy labels 486 if dstN.labels == nil { 487 dstN.labels = make(map[string]string, len(n.labels)) 488 } 489 for k, v := range n.labels { 490 dstN.labels[k] = v 491 } 492 493 if n.ipamOptions != nil { 494 dstN.ipamOptions = make(map[string]string, len(n.ipamOptions)) 495 for k, v := range n.ipamOptions { 496 dstN.ipamOptions[k] = v 497 } 498 } 499 500 for _, v4conf := range n.ipamV4Config { 501 dstV4Conf := &IpamConf{} 502 v4conf.CopyTo(dstV4Conf) 503 dstN.ipamV4Config = append(dstN.ipamV4Config, dstV4Conf) 504 } 505 506 for _, v4info := range n.ipamV4Info { 507 dstV4Info := &IpamInfo{} 508 v4info.CopyTo(dstV4Info) 509 dstN.ipamV4Info = append(dstN.ipamV4Info, dstV4Info) 510 } 511 512 for _, v6conf := range n.ipamV6Config { 513 dstV6Conf := &IpamConf{} 514 v6conf.CopyTo(dstV6Conf) 515 dstN.ipamV6Config = append(dstN.ipamV6Config, dstV6Conf) 516 } 517 518 for _, v6info := range n.ipamV6Info { 519 dstV6Info := &IpamInfo{} 520 v6info.CopyTo(dstV6Info) 521 dstN.ipamV6Info = append(dstN.ipamV6Info, dstV6Info) 522 } 523 524 dstN.generic = options.Generic{} 525 for k, v := range n.generic { 526 dstN.generic[k] = v 527 } 528 529 return nil 530 } 531 532 func (n *network) DataScope() string { 533 s := n.Scope() 534 // All swarm scope networks have local datascope 535 if s == datastore.SwarmScope { 536 s = datastore.LocalScope 537 } 538 return s 539 } 540 541 func (n *network) getEpCnt() *endpointCnt { 542 n.Lock() 543 defer n.Unlock() 544 545 return n.epCnt 546 } 547 548 // TODO : Can be made much more generic with the help of reflection (but has some golang limitations) 549 func (n *network) MarshalJSON() ([]byte, error) { 550 netMap := make(map[string]interface{}) 551 netMap["name"] = n.name 552 netMap["id"] = n.id 553 netMap["created"] = n.created 554 netMap["networkType"] = n.networkType 555 netMap["scope"] = n.scope 556 netMap["labels"] = n.labels 557 netMap["ipamType"] = n.ipamType 558 netMap["ipamOptions"] = n.ipamOptions 559 netMap["addrSpace"] = n.addrSpace 560 netMap["enableIPv6"] = n.enableIPv6 561 if n.generic != nil { 562 netMap["generic"] = n.generic 563 } 564 netMap["persist"] = n.persist 565 netMap["postIPv6"] = n.postIPv6 566 if len(n.ipamV4Config) > 0 { 567 ics, err := json.Marshal(n.ipamV4Config) 568 if err != nil { 569 return nil, err 570 } 571 netMap["ipamV4Config"] = string(ics) 572 } 573 if len(n.ipamV4Info) > 0 { 574 iis, err := json.Marshal(n.ipamV4Info) 575 if err != nil { 576 return nil, err 577 } 578 netMap["ipamV4Info"] = string(iis) 579 } 580 if len(n.ipamV6Config) > 0 { 581 ics, err := json.Marshal(n.ipamV6Config) 582 if err != nil { 583 return nil, err 584 } 585 netMap["ipamV6Config"] = string(ics) 586 } 587 if len(n.ipamV6Info) > 0 { 588 iis, err := json.Marshal(n.ipamV6Info) 589 if err != nil { 590 return nil, err 591 } 592 netMap["ipamV6Info"] = string(iis) 593 } 594 netMap["internal"] = n.internal 595 netMap["attachable"] = n.attachable 596 netMap["inDelete"] = n.inDelete 597 netMap["ingress"] = n.ingress 598 netMap["configOnly"] = n.configOnly 599 netMap["configFrom"] = n.configFrom 600 netMap["loadBalancerIP"] = n.loadBalancerIP 601 netMap["loadBalancerMode"] = n.loadBalancerMode 602 return json.Marshal(netMap) 603 } 604 605 // TODO : Can be made much more generic with the help of reflection (but has some golang limitations) 606 func (n *network) UnmarshalJSON(b []byte) (err error) { 607 var netMap map[string]interface{} 608 if err := json.Unmarshal(b, &netMap); err != nil { 609 return err 610 } 611 n.name = netMap["name"].(string) 612 n.id = netMap["id"].(string) 613 // "created" is not available in older versions 614 if v, ok := netMap["created"]; ok { 615 // n.created is time.Time but marshalled as string 616 if err = n.created.UnmarshalText([]byte(v.(string))); err != nil { 617 logrus.Warnf("failed to unmarshal creation time %v: %v", v, err) 618 n.created = time.Time{} 619 } 620 } 621 n.networkType = netMap["networkType"].(string) 622 n.enableIPv6 = netMap["enableIPv6"].(bool) 623 624 // if we weren't unmarshaling to netMap we could simply set n.labels 625 // unfortunately, we can't because map[string]interface{} != map[string]string 626 if labels, ok := netMap["labels"].(map[string]interface{}); ok { 627 n.labels = make(map[string]string, len(labels)) 628 for label, value := range labels { 629 n.labels[label] = value.(string) 630 } 631 } 632 633 if v, ok := netMap["ipamOptions"]; ok { 634 if iOpts, ok := v.(map[string]interface{}); ok { 635 n.ipamOptions = make(map[string]string, len(iOpts)) 636 for k, v := range iOpts { 637 n.ipamOptions[k] = v.(string) 638 } 639 } 640 } 641 642 if v, ok := netMap["generic"]; ok { 643 n.generic = v.(map[string]interface{}) 644 // Restore opts in their map[string]string form 645 if v, ok := n.generic[netlabel.GenericData]; ok { 646 var lmap map[string]string 647 ba, err := json.Marshal(v) 648 if err != nil { 649 return err 650 } 651 if err := json.Unmarshal(ba, &lmap); err != nil { 652 return err 653 } 654 n.generic[netlabel.GenericData] = lmap 655 } 656 } 657 if v, ok := netMap["persist"]; ok { 658 n.persist = v.(bool) 659 } 660 if v, ok := netMap["postIPv6"]; ok { 661 n.postIPv6 = v.(bool) 662 } 663 if v, ok := netMap["ipamType"]; ok { 664 n.ipamType = v.(string) 665 } else { 666 n.ipamType = ipamapi.DefaultIPAM 667 } 668 if v, ok := netMap["addrSpace"]; ok { 669 n.addrSpace = v.(string) 670 } 671 if v, ok := netMap["ipamV4Config"]; ok { 672 if err := json.Unmarshal([]byte(v.(string)), &n.ipamV4Config); err != nil { 673 return err 674 } 675 } 676 if v, ok := netMap["ipamV4Info"]; ok { 677 if err := json.Unmarshal([]byte(v.(string)), &n.ipamV4Info); err != nil { 678 return err 679 } 680 } 681 if v, ok := netMap["ipamV6Config"]; ok { 682 if err := json.Unmarshal([]byte(v.(string)), &n.ipamV6Config); err != nil { 683 return err 684 } 685 } 686 if v, ok := netMap["ipamV6Info"]; ok { 687 if err := json.Unmarshal([]byte(v.(string)), &n.ipamV6Info); err != nil { 688 return err 689 } 690 } 691 if v, ok := netMap["internal"]; ok { 692 n.internal = v.(bool) 693 } 694 if v, ok := netMap["attachable"]; ok { 695 n.attachable = v.(bool) 696 } 697 if s, ok := netMap["scope"]; ok { 698 n.scope = s.(string) 699 } 700 if v, ok := netMap["inDelete"]; ok { 701 n.inDelete = v.(bool) 702 } 703 if v, ok := netMap["ingress"]; ok { 704 n.ingress = v.(bool) 705 } 706 if v, ok := netMap["configOnly"]; ok { 707 n.configOnly = v.(bool) 708 } 709 if v, ok := netMap["configFrom"]; ok { 710 n.configFrom = v.(string) 711 } 712 if v, ok := netMap["loadBalancerIP"]; ok { 713 n.loadBalancerIP = net.ParseIP(v.(string)) 714 } 715 n.loadBalancerMode = loadBalancerModeDefault 716 if v, ok := netMap["loadBalancerMode"]; ok { 717 n.loadBalancerMode = v.(string) 718 } 719 // Reconcile old networks with the recently added `--ipv6` flag 720 if !n.enableIPv6 { 721 n.enableIPv6 = len(n.ipamV6Info) > 0 722 } 723 return nil 724 } 725 726 // NetworkOption is an option setter function type used to pass various options to 727 // NewNetwork method. The various setter functions of type NetworkOption are 728 // provided by libnetwork, they look like NetworkOptionXXXX(...) 729 type NetworkOption func(n *network) 730 731 // NetworkOptionGeneric function returns an option setter for a Generic option defined 732 // in a Dictionary of Key-Value pair 733 func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption { 734 return func(n *network) { 735 if n.generic == nil { 736 n.generic = make(map[string]interface{}) 737 } 738 if val, ok := generic[netlabel.EnableIPv6]; ok { 739 n.enableIPv6 = val.(bool) 740 } 741 if val, ok := generic[netlabel.Internal]; ok { 742 n.internal = val.(bool) 743 } 744 for k, v := range generic { 745 n.generic[k] = v 746 } 747 } 748 } 749 750 // NetworkOptionIngress returns an option setter to indicate if a network is 751 // an ingress network. 752 func NetworkOptionIngress(ingress bool) NetworkOption { 753 return func(n *network) { 754 n.ingress = ingress 755 } 756 } 757 758 // NetworkOptionPersist returns an option setter to set persistence policy for a network 759 func NetworkOptionPersist(persist bool) NetworkOption { 760 return func(n *network) { 761 n.persist = persist 762 } 763 } 764 765 // NetworkOptionEnableIPv6 returns an option setter to explicitly configure IPv6 766 func NetworkOptionEnableIPv6(enableIPv6 bool) NetworkOption { 767 return func(n *network) { 768 if n.generic == nil { 769 n.generic = make(map[string]interface{}) 770 } 771 n.enableIPv6 = enableIPv6 772 n.generic[netlabel.EnableIPv6] = enableIPv6 773 } 774 } 775 776 // NetworkOptionInternalNetwork returns an option setter to config the network 777 // to be internal which disables default gateway service 778 func NetworkOptionInternalNetwork() NetworkOption { 779 return func(n *network) { 780 if n.generic == nil { 781 n.generic = make(map[string]interface{}) 782 } 783 n.internal = true 784 n.generic[netlabel.Internal] = true 785 } 786 } 787 788 // NetworkOptionAttachable returns an option setter to set attachable for a network 789 func NetworkOptionAttachable(attachable bool) NetworkOption { 790 return func(n *network) { 791 n.attachable = attachable 792 } 793 } 794 795 // NetworkOptionScope returns an option setter to overwrite the network's scope. 796 // By default the network's scope is set to the network driver's datascope. 797 func NetworkOptionScope(scope string) NetworkOption { 798 return func(n *network) { 799 n.scope = scope 800 } 801 } 802 803 // NetworkOptionIpam function returns an option setter for the ipam configuration for this network 804 func NetworkOptionIpam(ipamDriver string, addrSpace string, ipV4 []*IpamConf, ipV6 []*IpamConf, opts map[string]string) NetworkOption { 805 return func(n *network) { 806 if ipamDriver != "" { 807 n.ipamType = ipamDriver 808 if ipamDriver == ipamapi.DefaultIPAM { 809 n.ipamType = defaultIpamForNetworkType(n.Type()) 810 } 811 } 812 n.ipamOptions = opts 813 n.addrSpace = addrSpace 814 n.ipamV4Config = ipV4 815 n.ipamV6Config = ipV6 816 } 817 } 818 819 // NetworkOptionLBEndpoint function returns an option setter for the configuration of the load balancer endpoint for this network 820 func NetworkOptionLBEndpoint(ip net.IP) NetworkOption { 821 return func(n *network) { 822 n.loadBalancerIP = ip 823 } 824 } 825 826 // NetworkOptionDriverOpts function returns an option setter for any driver parameter described by a map 827 func NetworkOptionDriverOpts(opts map[string]string) NetworkOption { 828 return func(n *network) { 829 if n.generic == nil { 830 n.generic = make(map[string]interface{}) 831 } 832 if opts == nil { 833 opts = make(map[string]string) 834 } 835 // Store the options 836 n.generic[netlabel.GenericData] = opts 837 } 838 } 839 840 // NetworkOptionLabels function returns an option setter for labels specific to a network 841 func NetworkOptionLabels(labels map[string]string) NetworkOption { 842 return func(n *network) { 843 n.labels = labels 844 } 845 } 846 847 // NetworkOptionDynamic function returns an option setter for dynamic option for a network 848 func NetworkOptionDynamic() NetworkOption { 849 return func(n *network) { 850 n.dynamic = true 851 } 852 } 853 854 // NetworkOptionDeferIPv6Alloc instructs the network to defer the IPV6 address allocation until after the endpoint has been created 855 // It is being provided to support the specific docker daemon flags where user can deterministically assign an IPv6 address 856 // to a container as combination of fixed-cidr-v6 + mac-address 857 // TODO: Remove this option setter once we support endpoint ipam options 858 func NetworkOptionDeferIPv6Alloc(enable bool) NetworkOption { 859 return func(n *network) { 860 n.postIPv6 = enable 861 } 862 } 863 864 // NetworkOptionConfigOnly tells controller this network is 865 // a configuration only network. It serves as a configuration 866 // for other networks. 867 func NetworkOptionConfigOnly() NetworkOption { 868 return func(n *network) { 869 n.configOnly = true 870 } 871 } 872 873 // NetworkOptionConfigFrom tells controller to pick the 874 // network configuration from a configuration only network 875 func NetworkOptionConfigFrom(name string) NetworkOption { 876 return func(n *network) { 877 n.configFrom = name 878 } 879 } 880 881 func (n *network) processOptions(options ...NetworkOption) { 882 for _, opt := range options { 883 if opt != nil { 884 opt(n) 885 } 886 } 887 } 888 889 type networkDeleteParams struct { 890 rmLBEndpoint bool 891 } 892 893 // NetworkDeleteOption is a type for optional parameters to pass to the 894 // network.Delete() function. 895 type NetworkDeleteOption func(p *networkDeleteParams) 896 897 // NetworkDeleteOptionRemoveLB informs a network.Delete() operation that should 898 // remove the load balancer endpoint for this network. Note that the Delete() 899 // method will automatically remove a load balancing endpoint for most networks 900 // when the network is otherwise empty. However, this does not occur for some 901 // networks. In particular, networks marked as ingress (which are supposed to 902 // be more permanent than other overlay networks) won't automatically remove 903 // the LB endpoint on Delete(). This method allows for explicit removal of 904 // such networks provided there are no other endpoints present in the network. 905 // If the network still has non-LB endpoints present, Delete() will not 906 // remove the LB endpoint and will return an error. 907 func NetworkDeleteOptionRemoveLB(p *networkDeleteParams) { 908 p.rmLBEndpoint = true 909 } 910 911 func (n *network) resolveDriver(name string, load bool) (driverapi.Driver, *driverapi.Capability, error) { 912 c := n.getController() 913 914 // Check if a driver for the specified network type is available 915 d, cap := c.drvRegistry.Driver(name) 916 if d == nil { 917 if load { 918 err := c.loadDriver(name) 919 if err != nil { 920 return nil, nil, err 921 } 922 923 d, cap = c.drvRegistry.Driver(name) 924 if d == nil { 925 return nil, nil, fmt.Errorf("could not resolve driver %s in registry", name) 926 } 927 } else { 928 // don't fail if driver loading is not required 929 return nil, nil, nil 930 } 931 } 932 933 return d, cap, nil 934 } 935 936 func (n *network) driverScope() string { 937 _, cap, err := n.resolveDriver(n.networkType, true) 938 if err != nil { 939 // If driver could not be resolved simply return an empty string 940 return "" 941 } 942 943 return cap.DataScope 944 } 945 946 func (n *network) driverIsMultihost() bool { 947 _, cap, err := n.resolveDriver(n.networkType, true) 948 if err != nil { 949 return false 950 } 951 return cap.ConnectivityScope == datastore.GlobalScope 952 } 953 954 func (n *network) driver(load bool) (driverapi.Driver, error) { 955 d, cap, err := n.resolveDriver(n.networkType, load) 956 if err != nil { 957 return nil, err 958 } 959 960 n.Lock() 961 // If load is not required, driver, cap and err may all be nil 962 if n.scope == "" && cap != nil { 963 n.scope = cap.DataScope 964 } 965 if n.dynamic { 966 // If the network is dynamic, then it is swarm 967 // scoped regardless of the backing driver. 968 n.scope = datastore.SwarmScope 969 } 970 n.Unlock() 971 return d, nil 972 } 973 974 func (n *network) Delete(options ...NetworkDeleteOption) error { 975 var params networkDeleteParams 976 for _, opt := range options { 977 opt(¶ms) 978 } 979 return n.delete(false, params.rmLBEndpoint) 980 } 981 982 // This function gets called in 3 ways: 983 // * Delete() -- (false, false) 984 // remove if endpoint count == 0 or endpoint count == 1 and 985 // there is a load balancer IP 986 // * Delete(libnetwork.NetworkDeleteOptionRemoveLB) -- (false, true) 987 // remove load balancer and network if endpoint count == 1 988 // * controller.networkCleanup() -- (true, true) 989 // remove the network no matter what 990 func (n *network) delete(force bool, rmLBEndpoint bool) error { 991 n.Lock() 992 c := n.ctrlr 993 name := n.name 994 id := n.id 995 n.Unlock() 996 997 c.networkLocker.Lock(id) 998 defer c.networkLocker.Unlock(id) 999 1000 n, err := c.getNetworkFromStore(id) 1001 if err != nil { 1002 return &UnknownNetworkError{name: name, id: id} 1003 } 1004 1005 // Only remove ingress on force removal or explicit LB endpoint removal 1006 if n.ingress && !force && !rmLBEndpoint { 1007 return &ActiveEndpointsError{name: n.name, id: n.id} 1008 } 1009 1010 // Check that the network is empty 1011 var emptyCount uint64 1012 if n.hasLoadBalancerEndpoint() { 1013 emptyCount = 1 1014 } 1015 if !force && n.getEpCnt().EndpointCnt() > emptyCount { 1016 if n.configOnly { 1017 return types.ForbiddenErrorf("configuration network %q is in use", n.Name()) 1018 } 1019 return &ActiveEndpointsError{name: n.name, id: n.id} 1020 } 1021 1022 if n.hasLoadBalancerEndpoint() { 1023 // If we got to this point, then the following must hold: 1024 // * force is true OR endpoint count == 1 1025 if err := n.deleteLoadBalancerSandbox(); err != nil { 1026 if !force { 1027 return err 1028 } 1029 // continue deletion when force is true even on error 1030 logrus.Warnf("Error deleting load balancer sandbox: %v", err) 1031 } 1032 //Reload the network from the store to update the epcnt. 1033 n, err = c.getNetworkFromStore(id) 1034 if err != nil { 1035 return &UnknownNetworkError{name: name, id: id} 1036 } 1037 } 1038 1039 // Up to this point, errors that we returned were recoverable. 1040 // From here on, any errors leave us in an inconsistent state. 1041 // This is unfortunate, but there isn't a safe way to 1042 // reconstitute a load-balancer endpoint after removing it. 1043 1044 // Mark the network for deletion 1045 n.inDelete = true 1046 if err = c.updateToStore(n); err != nil { 1047 return fmt.Errorf("error marking network %s (%s) for deletion: %v", n.Name(), n.ID(), err) 1048 } 1049 1050 if n.ConfigFrom() != "" { 1051 if t, err := c.getConfigNetwork(n.ConfigFrom()); err == nil { 1052 if err := t.getEpCnt().DecEndpointCnt(); err != nil { 1053 logrus.Warnf("Failed to update reference count for configuration network %q on removal of network %q: %v", 1054 t.Name(), n.Name(), err) 1055 } 1056 } else { 1057 logrus.Warnf("Could not find configuration network %q during removal of network %q", n.configFrom, n.Name()) 1058 } 1059 } 1060 1061 if n.configOnly { 1062 goto removeFromStore 1063 } 1064 1065 if err = n.deleteNetwork(); err != nil { 1066 if !force { 1067 return err 1068 } 1069 logrus.Debugf("driver failed to delete stale network %s (%s): %v", n.Name(), n.ID(), err) 1070 } 1071 1072 n.ipamRelease() 1073 if err = c.updateToStore(n); err != nil { 1074 logrus.Warnf("Failed to update store after ipam release for network %s (%s): %v", n.Name(), n.ID(), err) 1075 } 1076 1077 // We are about to delete the network. Leave the gossip 1078 // cluster for the network to stop all incoming network 1079 // specific gossip updates before cleaning up all the service 1080 // bindings for the network. But cleanup service binding 1081 // before deleting the network from the store since service 1082 // bindings cleanup requires the network in the store. 1083 n.cancelDriverWatches() 1084 if err = n.leaveCluster(); err != nil { 1085 logrus.Errorf("Failed leaving network %s from the agent cluster: %v", n.Name(), err) 1086 } 1087 1088 // Cleanup the service discovery for this network 1089 c.cleanupServiceDiscovery(n.ID()) 1090 1091 // Cleanup the load balancer. On Windows this call is required 1092 // to remove remote loadbalancers in VFP. 1093 c.cleanupServiceBindings(n.ID()) 1094 1095 removeFromStore: 1096 // deleteFromStore performs an atomic delete operation and the 1097 // network.epCnt will help prevent any possible 1098 // race between endpoint join and network delete 1099 if err = c.deleteFromStore(n.getEpCnt()); err != nil { 1100 if !force { 1101 return fmt.Errorf("error deleting network endpoint count from store: %v", err) 1102 } 1103 logrus.Debugf("Error deleting endpoint count from store for stale network %s (%s) for deletion: %v", n.Name(), n.ID(), err) 1104 } 1105 1106 if err = c.deleteFromStore(n); err != nil { 1107 return fmt.Errorf("error deleting network from store: %v", err) 1108 } 1109 1110 return nil 1111 } 1112 1113 func (n *network) deleteNetwork() error { 1114 d, err := n.driver(true) 1115 if err != nil { 1116 return fmt.Errorf("failed deleting network: %v", err) 1117 } 1118 1119 if err := d.DeleteNetwork(n.ID()); err != nil { 1120 // Forbidden Errors should be honored 1121 if _, ok := err.(types.ForbiddenError); ok { 1122 return err 1123 } 1124 1125 if _, ok := err.(types.MaskableError); !ok { 1126 logrus.Warnf("driver error deleting network %s : %v", n.name, err) 1127 } 1128 } 1129 1130 for _, resolver := range n.resolver { 1131 resolver.Stop() 1132 } 1133 return nil 1134 } 1135 1136 func (n *network) addEndpoint(ep *endpoint) error { 1137 d, err := n.driver(true) 1138 if err != nil { 1139 return fmt.Errorf("failed to add endpoint: %v", err) 1140 } 1141 1142 err = d.CreateEndpoint(n.id, ep.id, ep.Interface(), ep.generic) 1143 if err != nil { 1144 return types.InternalErrorf("failed to create endpoint %s on network %s: %v", 1145 ep.Name(), n.Name(), err) 1146 } 1147 1148 return nil 1149 } 1150 1151 func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) { 1152 var err error 1153 if !config.IsValidName(name) { 1154 return nil, ErrInvalidName(name) 1155 } 1156 1157 if n.ConfigOnly() { 1158 return nil, types.ForbiddenErrorf("cannot create endpoint on configuration-only network") 1159 } 1160 1161 if _, err = n.EndpointByName(name); err == nil { 1162 return nil, types.ForbiddenErrorf("endpoint with name %s already exists in network %s", name, n.Name()) 1163 } 1164 1165 n.ctrlr.networkLocker.Lock(n.id) 1166 defer n.ctrlr.networkLocker.Unlock(n.id) 1167 1168 return n.createEndpoint(name, options...) 1169 1170 } 1171 1172 func (n *network) createEndpoint(name string, options ...EndpointOption) (Endpoint, error) { 1173 var err error 1174 1175 ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}} 1176 ep.id = stringid.GenerateRandomID() 1177 1178 // Initialize ep.network with a possibly stale copy of n. We need this to get network from 1179 // store. But once we get it from store we will have the most uptodate copy possibly. 1180 ep.network = n 1181 ep.locator = n.getController().clusterHostID() 1182 ep.network, err = ep.getNetworkFromStore() 1183 if err != nil { 1184 logrus.Errorf("failed to get network during CreateEndpoint: %v", err) 1185 return nil, err 1186 } 1187 n = ep.network 1188 1189 ep.processOptions(options...) 1190 1191 for _, llIPNet := range ep.Iface().LinkLocalAddresses() { 1192 if !llIPNet.IP.IsLinkLocalUnicast() { 1193 return nil, types.BadRequestErrorf("invalid link local IP address: %v", llIPNet.IP) 1194 } 1195 } 1196 1197 if opt, ok := ep.generic[netlabel.MacAddress]; ok { 1198 if mac, ok := opt.(net.HardwareAddr); ok { 1199 ep.iface.mac = mac 1200 } 1201 } 1202 1203 ipam, cap, err := n.getController().getIPAMDriver(n.ipamType) 1204 if err != nil { 1205 return nil, err 1206 } 1207 1208 if cap.RequiresMACAddress { 1209 if ep.iface.mac == nil { 1210 ep.iface.mac = netutils.GenerateRandomMAC() 1211 } 1212 if ep.ipamOptions == nil { 1213 ep.ipamOptions = make(map[string]string) 1214 } 1215 ep.ipamOptions[netlabel.MacAddress] = ep.iface.mac.String() 1216 } 1217 1218 if err = ep.assignAddress(ipam, true, n.enableIPv6 && !n.postIPv6); err != nil { 1219 return nil, err 1220 } 1221 defer func() { 1222 if err != nil { 1223 ep.releaseAddress() 1224 } 1225 }() 1226 1227 if err = n.addEndpoint(ep); err != nil { 1228 return nil, err 1229 } 1230 defer func() { 1231 if err != nil { 1232 if e := ep.deleteEndpoint(false); e != nil { 1233 logrus.Warnf("cleaning up endpoint failed %s : %v", name, e) 1234 } 1235 } 1236 }() 1237 1238 // We should perform updateToStore call right after addEndpoint 1239 // in order to have iface properly configured 1240 if err = n.getController().updateToStore(ep); err != nil { 1241 return nil, err 1242 } 1243 defer func() { 1244 if err != nil { 1245 if e := n.getController().deleteFromStore(ep); e != nil { 1246 logrus.Warnf("error rolling back endpoint %s from store: %v", name, e) 1247 } 1248 } 1249 }() 1250 1251 if err = ep.assignAddress(ipam, false, n.enableIPv6 && n.postIPv6); err != nil { 1252 return nil, err 1253 } 1254 1255 // Watch for service records 1256 n.getController().watchSvcRecord(ep) 1257 defer func() { 1258 if err != nil { 1259 n.getController().unWatchSvcRecord(ep) 1260 } 1261 }() 1262 1263 // Increment endpoint count to indicate completion of endpoint addition 1264 if err = n.getEpCnt().IncEndpointCnt(); err != nil { 1265 return nil, err 1266 } 1267 1268 return ep, nil 1269 } 1270 1271 func (n *network) Endpoints() []Endpoint { 1272 var list []Endpoint 1273 1274 endpoints, err := n.getEndpointsFromStore() 1275 if err != nil { 1276 logrus.Error(err) 1277 } 1278 1279 for _, ep := range endpoints { 1280 list = append(list, ep) 1281 } 1282 1283 return list 1284 } 1285 1286 func (n *network) WalkEndpoints(walker EndpointWalker) { 1287 for _, e := range n.Endpoints() { 1288 if walker(e) { 1289 return 1290 } 1291 } 1292 } 1293 1294 func (n *network) EndpointByName(name string) (Endpoint, error) { 1295 if name == "" { 1296 return nil, ErrInvalidName(name) 1297 } 1298 var e Endpoint 1299 1300 s := func(current Endpoint) bool { 1301 if current.Name() == name { 1302 e = current 1303 return true 1304 } 1305 return false 1306 } 1307 1308 n.WalkEndpoints(s) 1309 1310 if e == nil { 1311 return nil, ErrNoSuchEndpoint(name) 1312 } 1313 1314 return e, nil 1315 } 1316 1317 func (n *network) EndpointByID(id string) (Endpoint, error) { 1318 if id == "" { 1319 return nil, ErrInvalidID(id) 1320 } 1321 1322 ep, err := n.getEndpointFromStore(id) 1323 if err != nil { 1324 return nil, ErrNoSuchEndpoint(id) 1325 } 1326 1327 return ep, nil 1328 } 1329 1330 func (n *network) updateSvcRecord(ep *endpoint, localEps []*endpoint, isAdd bool) { 1331 var ipv6 net.IP 1332 epName := ep.Name() 1333 if iface := ep.Iface(); iface != nil && iface.Address() != nil { 1334 myAliases := ep.MyAliases() 1335 if iface.AddressIPv6() != nil { 1336 ipv6 = iface.AddressIPv6().IP 1337 } 1338 1339 serviceID := ep.svcID 1340 if serviceID == "" { 1341 serviceID = ep.ID() 1342 } 1343 if isAdd { 1344 // If anonymous endpoint has an alias use the first alias 1345 // for ip->name mapping. Not having the reverse mapping 1346 // breaks some apps 1347 if ep.isAnonymous() { 1348 if len(myAliases) > 0 { 1349 n.addSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") 1350 } 1351 } else { 1352 n.addSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") 1353 } 1354 for _, alias := range myAliases { 1355 n.addSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") 1356 } 1357 } else { 1358 if ep.isAnonymous() { 1359 if len(myAliases) > 0 { 1360 n.deleteSvcRecords(ep.ID(), myAliases[0], serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") 1361 } 1362 } else { 1363 n.deleteSvcRecords(ep.ID(), epName, serviceID, iface.Address().IP, ipv6, true, "updateSvcRecord") 1364 } 1365 for _, alias := range myAliases { 1366 n.deleteSvcRecords(ep.ID(), alias, serviceID, iface.Address().IP, ipv6, false, "updateSvcRecord") 1367 } 1368 } 1369 } 1370 } 1371 1372 func addIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) { 1373 reverseIP := netutils.ReverseIP(ip.String()) 1374 ipMap.Insert(reverseIP, ipInfo{ 1375 name: name, 1376 serviceID: serviceID, 1377 }) 1378 } 1379 1380 func delIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) { 1381 reverseIP := netutils.ReverseIP(ip.String()) 1382 ipMap.Remove(reverseIP, ipInfo{ 1383 name: name, 1384 serviceID: serviceID, 1385 }) 1386 } 1387 1388 func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) { 1389 // Since DNS name resolution is case-insensitive, Use the lower-case form 1390 // of the name as the key into svcMap 1391 lowerCaseName := strings.ToLower(name) 1392 svcMap.Insert(lowerCaseName, svcMapEntry{ 1393 ip: epIP.String(), 1394 serviceID: serviceID, 1395 }) 1396 } 1397 1398 func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) { 1399 lowerCaseName := strings.ToLower(name) 1400 svcMap.Remove(lowerCaseName, svcMapEntry{ 1401 ip: epIP.String(), 1402 serviceID: serviceID, 1403 }) 1404 } 1405 1406 func (n *network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP, ipMapUpdate bool, method string) { 1407 // Do not add service names for ingress network as this is a 1408 // routing only network 1409 if n.ingress { 1410 return 1411 } 1412 1413 logrus.Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, n.ID(), name, epIP, epIPv6, ipMapUpdate, method, serviceID) 1414 1415 c := n.getController() 1416 c.Lock() 1417 defer c.Unlock() 1418 1419 sr, ok := c.svcRecords[n.ID()] 1420 if !ok { 1421 sr = svcInfo{ 1422 svcMap: setmatrix.NewSetMatrix(), 1423 svcIPv6Map: setmatrix.NewSetMatrix(), 1424 ipMap: setmatrix.NewSetMatrix(), 1425 } 1426 c.svcRecords[n.ID()] = sr 1427 } 1428 1429 if ipMapUpdate { 1430 addIPToName(sr.ipMap, name, serviceID, epIP) 1431 if epIPv6 != nil { 1432 addIPToName(sr.ipMap, name, serviceID, epIPv6) 1433 } 1434 } 1435 1436 addNameToIP(sr.svcMap, name, serviceID, epIP) 1437 if epIPv6 != nil { 1438 addNameToIP(sr.svcIPv6Map, name, serviceID, epIPv6) 1439 } 1440 } 1441 1442 func (n *network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) { 1443 // Do not delete service names from ingress network as this is a 1444 // routing only network 1445 if n.ingress { 1446 return 1447 } 1448 1449 logrus.Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, n.ID(), name, epIP, epIPv6, ipMapUpdate, method, serviceID) 1450 1451 c := n.getController() 1452 c.Lock() 1453 defer c.Unlock() 1454 1455 sr, ok := c.svcRecords[n.ID()] 1456 if !ok { 1457 return 1458 } 1459 1460 if ipMapUpdate { 1461 delIPToName(sr.ipMap, name, serviceID, epIP) 1462 1463 if epIPv6 != nil { 1464 delIPToName(sr.ipMap, name, serviceID, epIPv6) 1465 } 1466 } 1467 1468 delNameToIP(sr.svcMap, name, serviceID, epIP) 1469 1470 if epIPv6 != nil { 1471 delNameToIP(sr.svcIPv6Map, name, serviceID, epIPv6) 1472 } 1473 } 1474 1475 func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record { 1476 n.Lock() 1477 defer n.Unlock() 1478 1479 if ep == nil { 1480 return nil 1481 } 1482 1483 var recs []etchosts.Record 1484 1485 epName := ep.Name() 1486 1487 n.ctrlr.Lock() 1488 defer n.ctrlr.Unlock() 1489 sr, ok := n.ctrlr.svcRecords[n.id] 1490 if !ok || sr.svcMap == nil { 1491 return nil 1492 } 1493 1494 svcMapKeys := sr.svcMap.Keys() 1495 // Loop on service names on this network 1496 for _, k := range svcMapKeys { 1497 if strings.Split(k, ".")[0] == epName { 1498 continue 1499 } 1500 // Get all the IPs associated to this service 1501 mapEntryList, ok := sr.svcMap.Get(k) 1502 if !ok { 1503 // The key got deleted 1504 continue 1505 } 1506 if len(mapEntryList) == 0 { 1507 logrus.Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id) 1508 continue 1509 } 1510 1511 recs = append(recs, etchosts.Record{ 1512 Hosts: k, 1513 IP: mapEntryList[0].(svcMapEntry).ip, 1514 }) 1515 } 1516 1517 return recs 1518 } 1519 1520 func (n *network) getController() *controller { 1521 n.Lock() 1522 defer n.Unlock() 1523 return n.ctrlr 1524 } 1525 1526 func (n *network) ipamAllocate() error { 1527 if n.hasSpecialDriver() { 1528 return nil 1529 } 1530 1531 ipam, _, err := n.getController().getIPAMDriver(n.ipamType) 1532 if err != nil { 1533 return err 1534 } 1535 1536 if n.addrSpace == "" { 1537 if n.addrSpace, err = n.deriveAddressSpace(); err != nil { 1538 return err 1539 } 1540 } 1541 1542 err = n.ipamAllocateVersion(4, ipam) 1543 if err != nil { 1544 return err 1545 } 1546 1547 defer func() { 1548 if err != nil { 1549 n.ipamReleaseVersion(4, ipam) 1550 } 1551 }() 1552 1553 if !n.enableIPv6 { 1554 return nil 1555 } 1556 1557 err = n.ipamAllocateVersion(6, ipam) 1558 return err 1559 } 1560 1561 func (n *network) requestPoolHelper(ipam ipamapi.Ipam, addressSpace, preferredPool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) { 1562 for { 1563 poolID, pool, meta, err := ipam.RequestPool(addressSpace, preferredPool, subPool, options, v6) 1564 if err != nil { 1565 return "", nil, nil, err 1566 } 1567 1568 // If the network belongs to global scope or the pool was 1569 // explicitly chosen or it is invalid, do not perform the overlap check. 1570 if n.Scope() == datastore.GlobalScope || preferredPool != "" || !types.IsIPNetValid(pool) { 1571 return poolID, pool, meta, nil 1572 } 1573 1574 // Check for overlap and if none found, we have found the right pool. 1575 if _, err := netutils.FindAvailableNetwork([]*net.IPNet{pool}); err == nil { 1576 return poolID, pool, meta, nil 1577 } 1578 1579 // Pool obtained in this iteration is 1580 // overlapping. Hold onto the pool and don't release 1581 // it yet, because we don't want ipam to give us back 1582 // the same pool over again. But make sure we still do 1583 // a deferred release when we have either obtained a 1584 // non-overlapping pool or ran out of pre-defined 1585 // pools. 1586 defer func() { 1587 if err := ipam.ReleasePool(poolID); err != nil { 1588 logrus.Warnf("Failed to release overlapping pool %s while returning from pool request helper for network %s", pool, n.Name()) 1589 } 1590 }() 1591 1592 // If this is a preferred pool request and the network 1593 // is local scope and there is an overlap, we fail the 1594 // network creation right here. The pool will be 1595 // released in the defer. 1596 if preferredPool != "" { 1597 return "", nil, nil, fmt.Errorf("requested subnet %s overlaps in the host", preferredPool) 1598 } 1599 } 1600 } 1601 1602 func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error { 1603 var ( 1604 cfgList *[]*IpamConf 1605 infoList *[]*IpamInfo 1606 err error 1607 ) 1608 1609 switch ipVer { 1610 case 4: 1611 cfgList = &n.ipamV4Config 1612 infoList = &n.ipamV4Info 1613 case 6: 1614 cfgList = &n.ipamV6Config 1615 infoList = &n.ipamV6Info 1616 default: 1617 return types.InternalErrorf("incorrect ip version passed to ipam allocate: %d", ipVer) 1618 } 1619 1620 if len(*cfgList) == 0 { 1621 *cfgList = []*IpamConf{{}} 1622 } 1623 1624 *infoList = make([]*IpamInfo, len(*cfgList)) 1625 1626 logrus.Debugf("Allocating IPv%d pools for network %s (%s)", ipVer, n.Name(), n.ID()) 1627 1628 for i, cfg := range *cfgList { 1629 if err = cfg.Validate(); err != nil { 1630 return err 1631 } 1632 d := &IpamInfo{} 1633 (*infoList)[i] = d 1634 1635 d.AddressSpace = n.addrSpace 1636 d.PoolID, d.Pool, d.Meta, err = n.requestPoolHelper(ipam, n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6) 1637 if err != nil { 1638 return err 1639 } 1640 1641 defer func() { 1642 if err != nil { 1643 if err := ipam.ReleasePool(d.PoolID); err != nil { 1644 logrus.Warnf("Failed to release address pool %s after failure to create network %s (%s)", d.PoolID, n.Name(), n.ID()) 1645 } 1646 } 1647 }() 1648 1649 if gws, ok := d.Meta[netlabel.Gateway]; ok { 1650 if d.Gateway, err = types.ParseCIDR(gws); err != nil { 1651 return types.BadRequestErrorf("failed to parse gateway address (%v) returned by ipam driver: %v", gws, err) 1652 } 1653 } 1654 1655 // If user requested a specific gateway, libnetwork will allocate it 1656 // irrespective of whether ipam driver returned a gateway already. 1657 // If none of the above is true, libnetwork will allocate one. 1658 if cfg.Gateway != "" || d.Gateway == nil { 1659 var gatewayOpts = map[string]string{ 1660 ipamapi.RequestAddressType: netlabel.Gateway, 1661 } 1662 if d.Gateway, _, err = ipam.RequestAddress(d.PoolID, net.ParseIP(cfg.Gateway), gatewayOpts); err != nil { 1663 return types.InternalErrorf("failed to allocate gateway (%v): %v", cfg.Gateway, err) 1664 } 1665 } 1666 1667 // Auxiliary addresses must be part of the master address pool 1668 // If they fall into the container addressable pool, libnetwork will reserve them 1669 if cfg.AuxAddresses != nil { 1670 var ip net.IP 1671 d.IPAMData.AuxAddresses = make(map[string]*net.IPNet, len(cfg.AuxAddresses)) 1672 for k, v := range cfg.AuxAddresses { 1673 if ip = net.ParseIP(v); ip == nil { 1674 return types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name()) 1675 } 1676 if !d.Pool.Contains(ip) { 1677 return types.ForbiddenErrorf("auxiliary address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool) 1678 } 1679 // Attempt reservation in the container addressable pool, silent the error if address does not belong to that pool 1680 if d.IPAMData.AuxAddresses[k], _, err = ipam.RequestAddress(d.PoolID, ip, nil); err != nil && err != ipamapi.ErrIPOutOfRange { 1681 return types.InternalErrorf("failed to allocate secondary ip address (%s:%s): %v", k, v, err) 1682 } 1683 } 1684 } 1685 } 1686 1687 return nil 1688 } 1689 1690 func (n *network) ipamRelease() { 1691 if n.hasSpecialDriver() { 1692 return 1693 } 1694 ipam, _, err := n.getController().getIPAMDriver(n.ipamType) 1695 if err != nil { 1696 logrus.Warnf("Failed to retrieve ipam driver to release address pool(s) on delete of network %s (%s): %v", n.Name(), n.ID(), err) 1697 return 1698 } 1699 n.ipamReleaseVersion(4, ipam) 1700 n.ipamReleaseVersion(6, ipam) 1701 } 1702 1703 func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) { 1704 var infoList *[]*IpamInfo 1705 1706 switch ipVer { 1707 case 4: 1708 infoList = &n.ipamV4Info 1709 case 6: 1710 infoList = &n.ipamV6Info 1711 default: 1712 logrus.Warnf("incorrect ip version passed to ipam release: %d", ipVer) 1713 return 1714 } 1715 1716 if len(*infoList) == 0 { 1717 return 1718 } 1719 1720 logrus.Debugf("releasing IPv%d pools from network %s (%s)", ipVer, n.Name(), n.ID()) 1721 1722 for _, d := range *infoList { 1723 if d.Gateway != nil { 1724 if err := ipam.ReleaseAddress(d.PoolID, d.Gateway.IP); err != nil { 1725 logrus.Warnf("Failed to release gateway ip address %s on delete of network %s (%s): %v", d.Gateway.IP, n.Name(), n.ID(), err) 1726 } 1727 } 1728 if d.IPAMData.AuxAddresses != nil { 1729 for k, nw := range d.IPAMData.AuxAddresses { 1730 if d.Pool.Contains(nw.IP) { 1731 if err := ipam.ReleaseAddress(d.PoolID, nw.IP); err != nil && err != ipamapi.ErrIPOutOfRange { 1732 logrus.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err) 1733 } 1734 } 1735 } 1736 } 1737 if err := ipam.ReleasePool(d.PoolID); err != nil { 1738 logrus.Warnf("Failed to release address pool %s on delete of network %s (%s): %v", d.PoolID, n.Name(), n.ID(), err) 1739 } 1740 } 1741 1742 *infoList = nil 1743 } 1744 1745 func (n *network) getIPInfo(ipVer int) []*IpamInfo { 1746 var info []*IpamInfo 1747 switch ipVer { 1748 case 4: 1749 info = n.ipamV4Info 1750 case 6: 1751 info = n.ipamV6Info 1752 default: 1753 return nil 1754 } 1755 l := make([]*IpamInfo, 0, len(info)) 1756 n.Lock() 1757 l = append(l, info...) 1758 n.Unlock() 1759 return l 1760 } 1761 1762 func (n *network) getIPData(ipVer int) []driverapi.IPAMData { 1763 var info []*IpamInfo 1764 switch ipVer { 1765 case 4: 1766 info = n.ipamV4Info 1767 case 6: 1768 info = n.ipamV6Info 1769 default: 1770 return nil 1771 } 1772 l := make([]driverapi.IPAMData, 0, len(info)) 1773 n.Lock() 1774 for _, d := range info { 1775 l = append(l, d.IPAMData) 1776 } 1777 n.Unlock() 1778 return l 1779 } 1780 1781 func (n *network) deriveAddressSpace() (string, error) { 1782 local, global, err := n.getController().drvRegistry.IPAMDefaultAddressSpaces(n.ipamType) 1783 if err != nil { 1784 return "", types.NotFoundErrorf("failed to get default address space: %v", err) 1785 } 1786 if n.DataScope() == datastore.GlobalScope { 1787 return global, nil 1788 } 1789 return local, nil 1790 } 1791 1792 func (n *network) Info() NetworkInfo { 1793 return n 1794 } 1795 1796 func (n *network) Peers() []networkdb.PeerInfo { 1797 if !n.Dynamic() { 1798 return []networkdb.PeerInfo{} 1799 } 1800 1801 agent := n.getController().getAgent() 1802 if agent == nil { 1803 return []networkdb.PeerInfo{} 1804 } 1805 1806 return agent.networkDB.Peers(n.ID()) 1807 } 1808 1809 func (n *network) DriverOptions() map[string]string { 1810 n.Lock() 1811 defer n.Unlock() 1812 if n.generic != nil { 1813 if m, ok := n.generic[netlabel.GenericData]; ok { 1814 return m.(map[string]string) 1815 } 1816 } 1817 return map[string]string{} 1818 } 1819 1820 func (n *network) Scope() string { 1821 n.Lock() 1822 defer n.Unlock() 1823 return n.scope 1824 } 1825 1826 func (n *network) IpamConfig() (string, map[string]string, []*IpamConf, []*IpamConf) { 1827 n.Lock() 1828 defer n.Unlock() 1829 1830 v4L := make([]*IpamConf, len(n.ipamV4Config)) 1831 v6L := make([]*IpamConf, len(n.ipamV6Config)) 1832 1833 for i, c := range n.ipamV4Config { 1834 cc := &IpamConf{} 1835 c.CopyTo(cc) 1836 v4L[i] = cc 1837 } 1838 1839 for i, c := range n.ipamV6Config { 1840 cc := &IpamConf{} 1841 c.CopyTo(cc) 1842 v6L[i] = cc 1843 } 1844 1845 return n.ipamType, n.ipamOptions, v4L, v6L 1846 } 1847 1848 func (n *network) IpamInfo() ([]*IpamInfo, []*IpamInfo) { 1849 n.Lock() 1850 defer n.Unlock() 1851 1852 v4Info := make([]*IpamInfo, len(n.ipamV4Info)) 1853 v6Info := make([]*IpamInfo, len(n.ipamV6Info)) 1854 1855 for i, info := range n.ipamV4Info { 1856 ic := &IpamInfo{} 1857 info.CopyTo(ic) 1858 v4Info[i] = ic 1859 } 1860 1861 for i, info := range n.ipamV6Info { 1862 ic := &IpamInfo{} 1863 info.CopyTo(ic) 1864 v6Info[i] = ic 1865 } 1866 1867 return v4Info, v6Info 1868 } 1869 1870 func (n *network) Internal() bool { 1871 n.Lock() 1872 defer n.Unlock() 1873 1874 return n.internal 1875 } 1876 1877 func (n *network) Attachable() bool { 1878 n.Lock() 1879 defer n.Unlock() 1880 1881 return n.attachable 1882 } 1883 1884 func (n *network) Ingress() bool { 1885 n.Lock() 1886 defer n.Unlock() 1887 1888 return n.ingress 1889 } 1890 1891 func (n *network) Dynamic() bool { 1892 n.Lock() 1893 defer n.Unlock() 1894 1895 return n.dynamic 1896 } 1897 1898 func (n *network) IPv6Enabled() bool { 1899 n.Lock() 1900 defer n.Unlock() 1901 1902 return n.enableIPv6 1903 } 1904 1905 func (n *network) ConfigFrom() string { 1906 n.Lock() 1907 defer n.Unlock() 1908 1909 return n.configFrom 1910 } 1911 1912 func (n *network) ConfigOnly() bool { 1913 n.Lock() 1914 defer n.Unlock() 1915 1916 return n.configOnly 1917 } 1918 1919 func (n *network) Labels() map[string]string { 1920 n.Lock() 1921 defer n.Unlock() 1922 1923 var lbls = make(map[string]string, len(n.labels)) 1924 for k, v := range n.labels { 1925 lbls[k] = v 1926 } 1927 1928 return lbls 1929 } 1930 1931 func (n *network) TableEventRegister(tableName string, objType driverapi.ObjectType) error { 1932 if !driverapi.IsValidType(objType) { 1933 return fmt.Errorf("invalid object type %v in registering table, %s", objType, tableName) 1934 } 1935 1936 t := networkDBTable{ 1937 name: tableName, 1938 objType: objType, 1939 } 1940 n.Lock() 1941 defer n.Unlock() 1942 n.driverTables = append(n.driverTables, t) 1943 return nil 1944 } 1945 1946 func (n *network) UpdateIpamConfig(ipV4Data []driverapi.IPAMData) { 1947 1948 ipamV4Config := make([]*IpamConf, len(ipV4Data)) 1949 1950 for i, data := range ipV4Data { 1951 ic := &IpamConf{} 1952 ic.PreferredPool = data.Pool.String() 1953 ic.Gateway = data.Gateway.IP.String() 1954 ipamV4Config[i] = ic 1955 } 1956 1957 n.Lock() 1958 defer n.Unlock() 1959 n.ipamV4Config = ipamV4Config 1960 } 1961 1962 // Special drivers are ones which do not need to perform any network plumbing 1963 func (n *network) hasSpecialDriver() bool { 1964 return n.Type() == "host" || n.Type() == "null" 1965 } 1966 1967 func (n *network) hasLoadBalancerEndpoint() bool { 1968 return len(n.loadBalancerIP) != 0 1969 } 1970 1971 func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) { 1972 var ipv6Miss bool 1973 1974 c := n.getController() 1975 c.Lock() 1976 defer c.Unlock() 1977 sr, ok := c.svcRecords[n.ID()] 1978 1979 if !ok { 1980 return nil, false 1981 } 1982 1983 req = strings.TrimSuffix(req, ".") 1984 req = strings.ToLower(req) 1985 ipSet, ok := sr.svcMap.Get(req) 1986 1987 if ipType == types.IPv6 { 1988 // If the name resolved to v4 address then its a valid name in 1989 // the docker network domain. If the network is not v6 enabled 1990 // set ipv6Miss to filter the DNS query from going to external 1991 // resolvers. 1992 if ok && !n.enableIPv6 { 1993 ipv6Miss = true 1994 } 1995 ipSet, ok = sr.svcIPv6Map.Get(req) 1996 } 1997 1998 if ok && len(ipSet) > 0 { 1999 // this map is to avoid IP duplicates, this can happen during a transition period where 2 services are using the same IP 2000 noDup := make(map[string]bool) 2001 var ipLocal []net.IP 2002 for _, ip := range ipSet { 2003 if _, dup := noDup[ip.(svcMapEntry).ip]; !dup { 2004 noDup[ip.(svcMapEntry).ip] = true 2005 ipLocal = append(ipLocal, net.ParseIP(ip.(svcMapEntry).ip)) 2006 } 2007 } 2008 return ipLocal, ok 2009 } 2010 2011 return nil, ipv6Miss 2012 } 2013 2014 func (n *network) HandleQueryResp(name string, ip net.IP) { 2015 c := n.getController() 2016 c.Lock() 2017 defer c.Unlock() 2018 sr, ok := c.svcRecords[n.ID()] 2019 2020 if !ok { 2021 return 2022 } 2023 2024 ipStr := netutils.ReverseIP(ip.String()) 2025 // If an object with extResolver == true is already in the set this call will fail 2026 // but anyway it means that has already been inserted before 2027 if ok, _ := sr.ipMap.Contains(ipStr, ipInfo{name: name}); ok { 2028 sr.ipMap.Remove(ipStr, ipInfo{name: name}) 2029 sr.ipMap.Insert(ipStr, ipInfo{name: name, extResolver: true}) 2030 } 2031 } 2032 2033 func (n *network) ResolveIP(ip string) string { 2034 c := n.getController() 2035 c.Lock() 2036 defer c.Unlock() 2037 sr, ok := c.svcRecords[n.ID()] 2038 2039 if !ok { 2040 return "" 2041 } 2042 2043 nwName := n.Name() 2044 2045 elemSet, ok := sr.ipMap.Get(ip) 2046 if !ok || len(elemSet) == 0 { 2047 return "" 2048 } 2049 // NOTE it is possible to have more than one element in the Set, this will happen 2050 // because of interleave of different events from different sources (local container create vs 2051 // network db notifications) 2052 // In such cases the resolution will be based on the first element of the set, and can vary 2053 // during the system stabilitation 2054 elem, ok := elemSet[0].(ipInfo) 2055 if !ok { 2056 setStr, b := sr.ipMap.String(ip) 2057 logrus.Errorf("expected set of ipInfo type for key %s set:%t %s", ip, b, setStr) 2058 return "" 2059 } 2060 2061 if elem.extResolver { 2062 return "" 2063 } 2064 2065 return elem.name + "." + nwName 2066 } 2067 2068 func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) { 2069 c := n.getController() 2070 2071 srv := []*net.SRV{} 2072 ip := []net.IP{} 2073 2074 logrus.Debugf("Service name To resolve: %v", name) 2075 2076 // There are DNS implementations that allow SRV queries for names not in 2077 // the format defined by RFC 2782. Hence specific validations checks are 2078 // not done 2079 parts := strings.Split(name, ".") 2080 if len(parts) < 3 { 2081 return nil, nil 2082 } 2083 2084 portName := parts[0] 2085 proto := parts[1] 2086 svcName := strings.Join(parts[2:], ".") 2087 2088 c.Lock() 2089 defer c.Unlock() 2090 sr, ok := c.svcRecords[n.ID()] 2091 2092 if !ok { 2093 return nil, nil 2094 } 2095 2096 svcs, ok := sr.service[svcName] 2097 if !ok { 2098 return nil, nil 2099 } 2100 2101 for _, svc := range svcs { 2102 if svc.portName != portName { 2103 continue 2104 } 2105 if svc.proto != proto { 2106 continue 2107 } 2108 for _, t := range svc.target { 2109 srv = append(srv, 2110 &net.SRV{ 2111 Target: t.name, 2112 Port: t.port, 2113 }) 2114 2115 ip = append(ip, t.ip) 2116 } 2117 } 2118 2119 return srv, ip 2120 } 2121 2122 func (n *network) ExecFunc(f func()) error { 2123 return types.NotImplementedErrorf("ExecFunc not supported by network") 2124 } 2125 2126 func (n *network) NdotsSet() bool { 2127 return false 2128 } 2129 2130 // config-only network is looked up by name 2131 func (c *controller) getConfigNetwork(name string) (*network, error) { 2132 var n Network 2133 2134 s := func(current Network) bool { 2135 if current.Info().ConfigOnly() && current.Name() == name { 2136 n = current 2137 return true 2138 } 2139 return false 2140 } 2141 2142 c.WalkNetworks(s) 2143 2144 if n == nil { 2145 return nil, types.NotFoundErrorf("configuration network %q not found", name) 2146 } 2147 2148 return n.(*network), nil 2149 } 2150 2151 func (n *network) lbSandboxName() string { 2152 name := "lb-" + n.name 2153 if n.ingress { 2154 name = n.name + "-sbox" 2155 } 2156 return name 2157 } 2158 2159 func (n *network) lbEndpointName() string { 2160 return n.name + "-endpoint" 2161 } 2162 2163 func (n *network) createLoadBalancerSandbox() (retErr error) { 2164 sandboxName := n.lbSandboxName() 2165 // Mark the sandbox to be a load balancer 2166 sbOptions := []SandboxOption{OptionLoadBalancer(n.id)} 2167 if n.ingress { 2168 sbOptions = append(sbOptions, OptionIngress()) 2169 } 2170 sb, err := n.ctrlr.NewSandbox(sandboxName, sbOptions...) 2171 if err != nil { 2172 return err 2173 } 2174 defer func() { 2175 if retErr != nil { 2176 if e := n.ctrlr.SandboxDestroy(sandboxName); e != nil { 2177 logrus.Warnf("could not delete sandbox %s on failure on failure (%v): %v", sandboxName, retErr, e) 2178 } 2179 } 2180 }() 2181 2182 endpointName := n.lbEndpointName() 2183 epOptions := []EndpointOption{ 2184 CreateOptionIpam(n.loadBalancerIP, nil, nil, nil), 2185 CreateOptionLoadBalancer(), 2186 } 2187 if n.hasLoadBalancerEndpoint() && !n.ingress { 2188 // Mark LB endpoints as anonymous so they don't show up in DNS 2189 epOptions = append(epOptions, CreateOptionAnonymous()) 2190 } 2191 ep, err := n.createEndpoint(endpointName, epOptions...) 2192 if err != nil { 2193 return err 2194 } 2195 defer func() { 2196 if retErr != nil { 2197 if e := ep.Delete(true); e != nil { 2198 logrus.Warnf("could not delete endpoint %s on failure on failure (%v): %v", endpointName, retErr, e) 2199 } 2200 } 2201 }() 2202 2203 if err := ep.Join(sb, nil); err != nil { 2204 return err 2205 } 2206 2207 return sb.EnableService() 2208 } 2209 2210 func (n *network) deleteLoadBalancerSandbox() error { 2211 n.Lock() 2212 c := n.ctrlr 2213 name := n.name 2214 n.Unlock() 2215 2216 sandboxName := n.lbSandboxName() 2217 endpointName := n.lbEndpointName() 2218 2219 endpoint, err := n.EndpointByName(endpointName) 2220 if err != nil { 2221 logrus.Warnf("Failed to find load balancer endpoint %s on network %s: %v", endpointName, name, err) 2222 } else { 2223 2224 info := endpoint.Info() 2225 if info != nil { 2226 sb := info.Sandbox() 2227 if sb != nil { 2228 if err := sb.DisableService(); err != nil { 2229 logrus.Warnf("Failed to disable service on sandbox %s: %v", sandboxName, err) 2230 //Ignore error and attempt to delete the load balancer endpoint 2231 } 2232 } 2233 } 2234 2235 if err := endpoint.Delete(true); err != nil { 2236 logrus.Warnf("Failed to delete endpoint %s (%s) in %s: %v", endpoint.Name(), endpoint.ID(), sandboxName, err) 2237 //Ignore error and attempt to delete the sandbox. 2238 } 2239 } 2240 2241 if err := c.SandboxDestroy(sandboxName); err != nil { 2242 return fmt.Errorf("Failed to delete %s sandbox: %v", sandboxName, err) 2243 } 2244 return nil 2245 }