github.com/adityamillind98/moby@v23.0.0-rc.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 109 svcIPv6Map setmatrix.SetMatrix 110 ipMap setmatrix.SetMatrix 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 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 // 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.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 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.Lock() 551 defer n.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, nil, err 929 } 930 931 d, cap = c.drvRegistry.Driver(name) 932 if d == nil { 933 return nil, nil, 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, nil, 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.Lock() 959 // If load is not required, driver, cap and err may all be nil 960 if n.scope == "" && cap != nil { 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.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.Lock() 990 c := n.ctrlr 991 name := n.name 992 id := n.id 993 n.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 if err = c.updateToStore(n); err != nil { 1065 logrus.Warnf("Failed to update store after ipam release for network %s (%s): %v", n.Name(), n.ID(), err) 1066 } 1067 1068 // We are about to delete the network. Leave the gossip 1069 // cluster for the network to stop all incoming network 1070 // specific gossip updates before cleaning up all the service 1071 // bindings for the network. But cleanup service binding 1072 // before deleting the network from the store since service 1073 // bindings cleanup requires the network in the store. 1074 n.cancelDriverWatches() 1075 if err = n.leaveCluster(); err != nil { 1076 logrus.Errorf("Failed leaving network %s from the agent cluster: %v", n.Name(), err) 1077 } 1078 1079 // Cleanup the service discovery for this network 1080 c.cleanupServiceDiscovery(n.ID()) 1081 1082 // Cleanup the load balancer. On Windows this call is required 1083 // to remove remote loadbalancers in VFP, and must be performed before 1084 // dataplane network deletion. 1085 if runtime.GOOS == "windows" { 1086 c.cleanupServiceBindings(n.ID()) 1087 } 1088 1089 // Delete the network from the dataplane 1090 if err = n.deleteNetwork(); err != nil { 1091 if !force { 1092 return err 1093 } 1094 logrus.Debugf("driver failed to delete stale network %s (%s): %v", n.Name(), n.ID(), err) 1095 } 1096 1097 removeFromStore: 1098 // deleteFromStore performs an atomic delete operation and the 1099 // network.epCnt will help prevent any possible 1100 // race between endpoint join and network delete 1101 if err = c.deleteFromStore(n.getEpCnt()); err != nil { 1102 if !force { 1103 return fmt.Errorf("error deleting network endpoint count from store: %v", err) 1104 } 1105 logrus.Debugf("Error deleting endpoint count from store for stale network %s (%s) for deletion: %v", n.Name(), n.ID(), err) 1106 } 1107 1108 if err = c.deleteFromStore(n); err != nil { 1109 return fmt.Errorf("error deleting network from store: %v", err) 1110 } 1111 1112 return nil 1113 } 1114 1115 func (n *network) deleteNetwork() error { 1116 d, err := n.driver(true) 1117 if err != nil { 1118 return fmt.Errorf("failed deleting network: %v", err) 1119 } 1120 1121 if err := d.DeleteNetwork(n.ID()); err != nil { 1122 // Forbidden Errors should be honored 1123 if _, ok := err.(types.ForbiddenError); ok { 1124 return err 1125 } 1126 1127 if _, ok := err.(types.MaskableError); !ok { 1128 logrus.Warnf("driver error deleting network %s : %v", n.name, err) 1129 } 1130 } 1131 1132 for _, resolver := range n.resolver { 1133 resolver.Stop() 1134 } 1135 return nil 1136 } 1137 1138 func (n *network) addEndpoint(ep *endpoint) error { 1139 d, err := n.driver(true) 1140 if err != nil { 1141 return fmt.Errorf("failed to add endpoint: %v", err) 1142 } 1143 1144 err = d.CreateEndpoint(n.id, ep.id, ep.Interface(), ep.generic) 1145 if err != nil { 1146 return types.InternalErrorf("failed to create endpoint %s on network %s: %v", 1147 ep.Name(), n.Name(), err) 1148 } 1149 1150 return nil 1151 } 1152 1153 func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) { 1154 var err error 1155 if !config.IsValidName(name) { 1156 return nil, ErrInvalidName(name) 1157 } 1158 1159 if n.ConfigOnly() { 1160 return nil, types.ForbiddenErrorf("cannot create endpoint on configuration-only network") 1161 } 1162 1163 if _, err = n.EndpointByName(name); err == nil { 1164 return nil, types.ForbiddenErrorf("endpoint with name %s already exists in network %s", name, n.Name()) 1165 } 1166 1167 n.ctrlr.networkLocker.Lock(n.id) 1168 defer n.ctrlr.networkLocker.Unlock(n.id) //nolint:errcheck 1169 1170 return n.createEndpoint(name, options...) 1171 } 1172 1173 func (n *network) createEndpoint(name string, options ...EndpointOption) (Endpoint, error) { 1174 var err error 1175 1176 ep := &endpoint{name: name, generic: make(map[string]interface{}), iface: &endpointInterface{}} 1177 ep.id = stringid.GenerateRandomID() 1178 1179 // Initialize ep.network with a possibly stale copy of n. We need this to get network from 1180 // store. But once we get it from store we will have the most uptodate copy possibly. 1181 ep.network = n 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, capability, err := n.getController().getIPAMDriver(n.ipamType) 1204 if err != nil { 1205 return nil, err 1206 } 1207 1208 if capability.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 networkID := n.ID() 1413 logrus.Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) 1414 1415 c := n.getController() 1416 c.Lock() 1417 defer c.Unlock() 1418 1419 sr, ok := c.svcRecords[networkID] 1420 if !ok { 1421 sr = svcInfo{ 1422 svcMap: setmatrix.NewSetMatrix(), 1423 svcIPv6Map: setmatrix.NewSetMatrix(), 1424 ipMap: setmatrix.NewSetMatrix(), 1425 } 1426 c.svcRecords[networkID] = 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 networkID := n.ID() 1449 logrus.Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) 1450 1451 c := n.getController() 1452 c.Lock() 1453 defer c.Unlock() 1454 1455 sr, ok := c.svcRecords[networkID] 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 if err := c.CopyTo(cc); err != nil { 1836 logrus.WithError(err).Error("Error copying ipam ipv4 config") 1837 } 1838 v4L[i] = cc 1839 } 1840 1841 for i, c := range n.ipamV6Config { 1842 cc := &IpamConf{} 1843 if err := c.CopyTo(cc); err != nil { 1844 logrus.WithError(err).Debug("Error copying ipam ipv6 config") 1845 } 1846 v6L[i] = cc 1847 } 1848 1849 return n.ipamType, n.ipamOptions, v4L, v6L 1850 } 1851 1852 func (n *network) IpamInfo() ([]*IpamInfo, []*IpamInfo) { 1853 n.Lock() 1854 defer n.Unlock() 1855 1856 v4Info := make([]*IpamInfo, len(n.ipamV4Info)) 1857 v6Info := make([]*IpamInfo, len(n.ipamV6Info)) 1858 1859 for i, info := range n.ipamV4Info { 1860 ic := &IpamInfo{} 1861 if err := info.CopyTo(ic); err != nil { 1862 logrus.WithError(err).Error("Error copying ipv4 ipam config") 1863 } 1864 v4Info[i] = ic 1865 } 1866 1867 for i, info := range n.ipamV6Info { 1868 ic := &IpamInfo{} 1869 if err := info.CopyTo(ic); err != nil { 1870 logrus.WithError(err).Error("Error copying ipv6 ipam config") 1871 } 1872 v6Info[i] = ic 1873 } 1874 1875 return v4Info, v6Info 1876 } 1877 1878 func (n *network) Internal() bool { 1879 n.Lock() 1880 defer n.Unlock() 1881 1882 return n.internal 1883 } 1884 1885 func (n *network) Attachable() bool { 1886 n.Lock() 1887 defer n.Unlock() 1888 1889 return n.attachable 1890 } 1891 1892 func (n *network) Ingress() bool { 1893 n.Lock() 1894 defer n.Unlock() 1895 1896 return n.ingress 1897 } 1898 1899 func (n *network) Dynamic() bool { 1900 n.Lock() 1901 defer n.Unlock() 1902 1903 return n.dynamic 1904 } 1905 1906 func (n *network) IPv6Enabled() bool { 1907 n.Lock() 1908 defer n.Unlock() 1909 1910 return n.enableIPv6 1911 } 1912 1913 func (n *network) ConfigFrom() string { 1914 n.Lock() 1915 defer n.Unlock() 1916 1917 return n.configFrom 1918 } 1919 1920 func (n *network) ConfigOnly() bool { 1921 n.Lock() 1922 defer n.Unlock() 1923 1924 return n.configOnly 1925 } 1926 1927 func (n *network) Labels() map[string]string { 1928 n.Lock() 1929 defer n.Unlock() 1930 1931 var lbls = make(map[string]string, len(n.labels)) 1932 for k, v := range n.labels { 1933 lbls[k] = v 1934 } 1935 1936 return lbls 1937 } 1938 1939 func (n *network) TableEventRegister(tableName string, objType driverapi.ObjectType) error { 1940 if !driverapi.IsValidType(objType) { 1941 return fmt.Errorf("invalid object type %v in registering table, %s", objType, tableName) 1942 } 1943 1944 t := networkDBTable{ 1945 name: tableName, 1946 objType: objType, 1947 } 1948 n.Lock() 1949 defer n.Unlock() 1950 n.driverTables = append(n.driverTables, t) 1951 return nil 1952 } 1953 1954 func (n *network) UpdateIpamConfig(ipV4Data []driverapi.IPAMData) { 1955 ipamV4Config := make([]*IpamConf, len(ipV4Data)) 1956 1957 for i, data := range ipV4Data { 1958 ic := &IpamConf{} 1959 ic.PreferredPool = data.Pool.String() 1960 ic.Gateway = data.Gateway.IP.String() 1961 ipamV4Config[i] = ic 1962 } 1963 1964 n.Lock() 1965 defer n.Unlock() 1966 n.ipamV4Config = ipamV4Config 1967 } 1968 1969 // Special drivers are ones which do not need to perform any network plumbing 1970 func (n *network) hasSpecialDriver() bool { 1971 return n.Type() == "host" || n.Type() == "null" 1972 } 1973 1974 func (n *network) hasLoadBalancerEndpoint() bool { 1975 return len(n.loadBalancerIP) != 0 1976 } 1977 1978 func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) { 1979 var ipv6Miss bool 1980 1981 c := n.getController() 1982 networkID := n.ID() 1983 c.Lock() 1984 defer c.Unlock() 1985 sr, ok := c.svcRecords[networkID] 1986 1987 if !ok { 1988 return nil, false 1989 } 1990 1991 req = strings.TrimSuffix(req, ".") 1992 req = strings.ToLower(req) 1993 ipSet, ok := sr.svcMap.Get(req) 1994 1995 if ipType == types.IPv6 { 1996 // If the name resolved to v4 address then its a valid name in 1997 // the docker network domain. If the network is not v6 enabled 1998 // set ipv6Miss to filter the DNS query from going to external 1999 // resolvers. 2000 if ok && !n.enableIPv6 { 2001 ipv6Miss = true 2002 } 2003 ipSet, ok = sr.svcIPv6Map.Get(req) 2004 } 2005 2006 if ok && len(ipSet) > 0 { 2007 // this map is to avoid IP duplicates, this can happen during a transition period where 2 services are using the same IP 2008 noDup := make(map[string]bool) 2009 var ipLocal []net.IP 2010 for _, ip := range ipSet { 2011 if _, dup := noDup[ip.(svcMapEntry).ip]; !dup { 2012 noDup[ip.(svcMapEntry).ip] = true 2013 ipLocal = append(ipLocal, net.ParseIP(ip.(svcMapEntry).ip)) 2014 } 2015 } 2016 return ipLocal, ok 2017 } 2018 2019 return nil, ipv6Miss 2020 } 2021 2022 func (n *network) HandleQueryResp(name string, ip net.IP) { 2023 networkID := n.ID() 2024 c := n.getController() 2025 c.Lock() 2026 defer c.Unlock() 2027 sr, ok := c.svcRecords[networkID] 2028 2029 if !ok { 2030 return 2031 } 2032 2033 ipStr := netutils.ReverseIP(ip.String()) 2034 // If an object with extResolver == true is already in the set this call will fail 2035 // but anyway it means that has already been inserted before 2036 if ok, _ := sr.ipMap.Contains(ipStr, ipInfo{name: name}); ok { 2037 sr.ipMap.Remove(ipStr, ipInfo{name: name}) 2038 sr.ipMap.Insert(ipStr, ipInfo{name: name, extResolver: true}) 2039 } 2040 } 2041 2042 func (n *network) ResolveIP(ip string) string { 2043 networkID := n.ID() 2044 c := n.getController() 2045 c.Lock() 2046 defer c.Unlock() 2047 sr, ok := c.svcRecords[networkID] 2048 2049 if !ok { 2050 return "" 2051 } 2052 2053 nwName := n.Name() 2054 2055 elemSet, ok := sr.ipMap.Get(ip) 2056 if !ok || len(elemSet) == 0 { 2057 return "" 2058 } 2059 // NOTE it is possible to have more than one element in the Set, this will happen 2060 // because of interleave of different events from different sources (local container create vs 2061 // network db notifications) 2062 // In such cases the resolution will be based on the first element of the set, and can vary 2063 // during the system stabilitation 2064 elem, ok := elemSet[0].(ipInfo) 2065 if !ok { 2066 setStr, b := sr.ipMap.String(ip) 2067 logrus.Errorf("expected set of ipInfo type for key %s set:%t %s", ip, b, setStr) 2068 return "" 2069 } 2070 2071 if elem.extResolver { 2072 return "" 2073 } 2074 2075 return elem.name + "." + nwName 2076 } 2077 2078 func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) { 2079 c := n.getController() 2080 2081 srv := []*net.SRV{} 2082 ip := []net.IP{} 2083 2084 logrus.Debugf("Service name To resolve: %v", name) 2085 2086 // There are DNS implementations that allow SRV queries for names not in 2087 // the format defined by RFC 2782. Hence specific validations checks are 2088 // not done 2089 parts := strings.Split(name, ".") 2090 if len(parts) < 3 { 2091 return nil, nil 2092 } 2093 2094 portName := parts[0] 2095 proto := parts[1] 2096 svcName := strings.Join(parts[2:], ".") 2097 2098 networkID := n.ID() 2099 c.Lock() 2100 defer c.Unlock() 2101 sr, ok := c.svcRecords[networkID] 2102 2103 if !ok { 2104 return nil, nil 2105 } 2106 2107 svcs, ok := sr.service[svcName] 2108 if !ok { 2109 return nil, nil 2110 } 2111 2112 for _, svc := range svcs { 2113 if svc.portName != portName { 2114 continue 2115 } 2116 if svc.proto != proto { 2117 continue 2118 } 2119 for _, t := range svc.target { 2120 srv = append(srv, 2121 &net.SRV{ 2122 Target: t.name, 2123 Port: t.port, 2124 }) 2125 2126 ip = append(ip, t.ip) 2127 } 2128 } 2129 2130 return srv, ip 2131 } 2132 2133 func (n *network) ExecFunc(f func()) error { 2134 return types.NotImplementedErrorf("ExecFunc not supported by network") 2135 } 2136 2137 func (n *network) NdotsSet() bool { 2138 return false 2139 } 2140 2141 // config-only network is looked up by name 2142 func (c *controller) getConfigNetwork(name string) (*network, error) { 2143 var n Network 2144 2145 s := func(current Network) bool { 2146 if current.Info().ConfigOnly() && current.Name() == name { 2147 n = current 2148 return true 2149 } 2150 return false 2151 } 2152 2153 c.WalkNetworks(s) 2154 2155 if n == nil { 2156 return nil, types.NotFoundErrorf("configuration network %q not found", name) 2157 } 2158 2159 return n.(*network), nil 2160 } 2161 2162 func (n *network) lbSandboxName() string { 2163 name := "lb-" + n.name 2164 if n.ingress { 2165 name = n.name + "-sbox" 2166 } 2167 return name 2168 } 2169 2170 func (n *network) lbEndpointName() string { 2171 return n.name + "-endpoint" 2172 } 2173 2174 func (n *network) createLoadBalancerSandbox() (retErr error) { 2175 sandboxName := n.lbSandboxName() 2176 // Mark the sandbox to be a load balancer 2177 sbOptions := []SandboxOption{OptionLoadBalancer(n.id)} 2178 if n.ingress { 2179 sbOptions = append(sbOptions, OptionIngress()) 2180 } 2181 sb, err := n.ctrlr.NewSandbox(sandboxName, sbOptions...) 2182 if err != nil { 2183 return err 2184 } 2185 defer func() { 2186 if retErr != nil { 2187 if e := n.ctrlr.SandboxDestroy(sandboxName); e != nil { 2188 logrus.Warnf("could not delete sandbox %s on failure on failure (%v): %v", sandboxName, retErr, e) 2189 } 2190 } 2191 }() 2192 2193 endpointName := n.lbEndpointName() 2194 epOptions := []EndpointOption{ 2195 CreateOptionIpam(n.loadBalancerIP, nil, nil, nil), 2196 CreateOptionLoadBalancer(), 2197 } 2198 if n.hasLoadBalancerEndpoint() && !n.ingress { 2199 // Mark LB endpoints as anonymous so they don't show up in DNS 2200 epOptions = append(epOptions, CreateOptionAnonymous()) 2201 } 2202 ep, err := n.createEndpoint(endpointName, epOptions...) 2203 if err != nil { 2204 return err 2205 } 2206 defer func() { 2207 if retErr != nil { 2208 if e := ep.Delete(true); e != nil { 2209 logrus.Warnf("could not delete endpoint %s on failure on failure (%v): %v", endpointName, retErr, e) 2210 } 2211 } 2212 }() 2213 2214 if err := ep.Join(sb, nil); err != nil { 2215 return err 2216 } 2217 2218 return sb.EnableService() 2219 } 2220 2221 func (n *network) deleteLoadBalancerSandbox() error { 2222 n.Lock() 2223 c := n.ctrlr 2224 name := n.name 2225 n.Unlock() 2226 2227 sandboxName := n.lbSandboxName() 2228 endpointName := n.lbEndpointName() 2229 2230 endpoint, err := n.EndpointByName(endpointName) 2231 if err != nil { 2232 logrus.Warnf("Failed to find load balancer endpoint %s on network %s: %v", endpointName, name, err) 2233 } else { 2234 info := endpoint.Info() 2235 if info != nil { 2236 sb := info.Sandbox() 2237 if sb != nil { 2238 if err := sb.DisableService(); err != nil { 2239 logrus.Warnf("Failed to disable service on sandbox %s: %v", sandboxName, err) 2240 // Ignore error and attempt to delete the load balancer endpoint 2241 } 2242 } 2243 } 2244 2245 if err := endpoint.Delete(true); err != nil { 2246 logrus.Warnf("Failed to delete endpoint %s (%s) in %s: %v", endpoint.Name(), endpoint.ID(), sandboxName, err) 2247 // Ignore error and attempt to delete the sandbox. 2248 } 2249 } 2250 2251 if err := c.SandboxDestroy(sandboxName); err != nil { 2252 return fmt.Errorf("Failed to delete %s sandbox: %v", sandboxName, err) 2253 } 2254 return nil 2255 }