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