github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/network.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "sort" 8 "strconv" 9 "strings" 10 "sync" 11 12 "github.com/docker/docker/api/types" 13 containertypes "github.com/docker/docker/api/types/container" 14 "github.com/docker/docker/api/types/filters" 15 "github.com/docker/docker/api/types/network" 16 "github.com/docker/docker/container" 17 clustertypes "github.com/docker/docker/daemon/cluster/provider" 18 internalnetwork "github.com/docker/docker/daemon/network" 19 "github.com/docker/docker/errdefs" 20 "github.com/docker/docker/opts" 21 "github.com/docker/docker/pkg/plugingetter" 22 "github.com/docker/docker/runconfig" 23 "github.com/docker/go-connections/nat" 24 "github.com/docker/libnetwork" 25 lncluster "github.com/docker/libnetwork/cluster" 26 "github.com/docker/libnetwork/driverapi" 27 "github.com/docker/libnetwork/ipamapi" 28 "github.com/docker/libnetwork/netlabel" 29 "github.com/docker/libnetwork/networkdb" 30 "github.com/docker/libnetwork/options" 31 networktypes "github.com/docker/libnetwork/types" 32 "github.com/pkg/errors" 33 "github.com/sirupsen/logrus" 34 ) 35 36 // PredefinedNetworkError is returned when user tries to create predefined network that already exists. 37 type PredefinedNetworkError string 38 39 func (pnr PredefinedNetworkError) Error() string { 40 return fmt.Sprintf("operation is not permitted on predefined %s network ", string(pnr)) 41 } 42 43 // Forbidden denotes the type of this error 44 func (pnr PredefinedNetworkError) Forbidden() {} 45 46 // NetworkControllerEnabled checks if the networking stack is enabled. 47 // This feature depends on OS primitives and it's disabled in systems like Windows. 48 func (daemon *Daemon) NetworkControllerEnabled() bool { 49 return daemon.netController != nil 50 } 51 52 // NetworkController returns the network controller created by the daemon. 53 func (daemon *Daemon) NetworkController() libnetwork.NetworkController { 54 return daemon.netController 55 } 56 57 // FindNetwork returns a network based on: 58 // 1. Full ID 59 // 2. Full Name 60 // 3. Partial ID 61 // as long as there is no ambiguity 62 func (daemon *Daemon) FindNetwork(term string) (libnetwork.Network, error) { 63 listByFullName := []libnetwork.Network{} 64 listByPartialID := []libnetwork.Network{} 65 for _, nw := range daemon.getAllNetworks() { 66 if nw.ID() == term { 67 return nw, nil 68 } 69 if nw.Name() == term { 70 listByFullName = append(listByFullName, nw) 71 } 72 if strings.HasPrefix(nw.ID(), term) { 73 listByPartialID = append(listByPartialID, nw) 74 } 75 } 76 switch { 77 case len(listByFullName) == 1: 78 return listByFullName[0], nil 79 case len(listByFullName) > 1: 80 return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found on name)", term, len(listByFullName))) 81 case len(listByPartialID) == 1: 82 return listByPartialID[0], nil 83 case len(listByPartialID) > 1: 84 return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID))) 85 } 86 87 // Be very careful to change the error type here, the 88 // libnetwork.ErrNoSuchNetwork error is used by the controller 89 // to retry the creation of the network as managed through the swarm manager 90 return nil, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term)) 91 } 92 93 // GetNetworkByID function returns a network whose ID matches the given ID. 94 // It fails with an error if no matching network is found. 95 func (daemon *Daemon) GetNetworkByID(id string) (libnetwork.Network, error) { 96 c := daemon.netController 97 if c == nil { 98 return nil, errors.Wrap(libnetwork.ErrNoSuchNetwork(id), "netcontroller is nil") 99 } 100 return c.NetworkByID(id) 101 } 102 103 // GetNetworkByName function returns a network for a given network name. 104 // If no network name is given, the default network is returned. 105 func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) { 106 c := daemon.netController 107 if c == nil { 108 return nil, libnetwork.ErrNoSuchNetwork(name) 109 } 110 if name == "" { 111 name = c.Config().Daemon.DefaultNetwork 112 } 113 return c.NetworkByName(name) 114 } 115 116 // GetNetworksByIDPrefix returns a list of networks whose ID partially matches zero or more networks 117 func (daemon *Daemon) GetNetworksByIDPrefix(partialID string) []libnetwork.Network { 118 c := daemon.netController 119 if c == nil { 120 return nil 121 } 122 list := []libnetwork.Network{} 123 l := func(nw libnetwork.Network) bool { 124 if strings.HasPrefix(nw.ID(), partialID) { 125 list = append(list, nw) 126 } 127 return false 128 } 129 c.WalkNetworks(l) 130 131 return list 132 } 133 134 // getAllNetworks returns a list containing all networks 135 func (daemon *Daemon) getAllNetworks() []libnetwork.Network { 136 c := daemon.netController 137 if c == nil { 138 return nil 139 } 140 return c.Networks() 141 } 142 143 type ingressJob struct { 144 create *clustertypes.NetworkCreateRequest 145 ip net.IP 146 jobDone chan struct{} 147 } 148 149 var ( 150 ingressWorkerOnce sync.Once 151 ingressJobsChannel chan *ingressJob 152 ingressID string 153 ) 154 155 func (daemon *Daemon) startIngressWorker() { 156 ingressJobsChannel = make(chan *ingressJob, 100) 157 go func() { 158 // nolint: gosimple 159 for { 160 select { 161 case r := <-ingressJobsChannel: 162 if r.create != nil { 163 daemon.setupIngress(r.create, r.ip, ingressID) 164 ingressID = r.create.ID 165 } else { 166 daemon.releaseIngress(ingressID) 167 ingressID = "" 168 } 169 close(r.jobDone) 170 } 171 } 172 }() 173 } 174 175 // enqueueIngressJob adds a ingress add/rm request to the worker queue. 176 // It guarantees the worker is started. 177 func (daemon *Daemon) enqueueIngressJob(job *ingressJob) { 178 ingressWorkerOnce.Do(daemon.startIngressWorker) 179 ingressJobsChannel <- job 180 } 181 182 // SetupIngress setups ingress networking. 183 // The function returns a channel which will signal the caller when the programming is completed. 184 func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) (<-chan struct{}, error) { 185 ip, _, err := net.ParseCIDR(nodeIP) 186 if err != nil { 187 return nil, err 188 } 189 done := make(chan struct{}) 190 daemon.enqueueIngressJob(&ingressJob{&create, ip, done}) 191 return done, nil 192 } 193 194 // ReleaseIngress releases the ingress networking. 195 // The function returns a channel which will signal the caller when the programming is completed. 196 func (daemon *Daemon) ReleaseIngress() (<-chan struct{}, error) { 197 done := make(chan struct{}) 198 daemon.enqueueIngressJob(&ingressJob{nil, nil, done}) 199 return done, nil 200 } 201 202 func (daemon *Daemon) setupIngress(create *clustertypes.NetworkCreateRequest, ip net.IP, staleID string) { 203 controller := daemon.netController 204 controller.AgentInitWait() 205 206 if staleID != "" && staleID != create.ID { 207 daemon.releaseIngress(staleID) 208 } 209 210 if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil { 211 // If it is any other error other than already 212 // exists error log error and return. 213 if _, ok := err.(libnetwork.NetworkNameError); !ok { 214 logrus.Errorf("Failed creating ingress network: %v", err) 215 return 216 } 217 // Otherwise continue down the call to create or recreate sandbox. 218 } 219 220 _, err := daemon.GetNetworkByID(create.ID) 221 if err != nil { 222 logrus.Errorf("Failed getting ingress network by id after creating: %v", err) 223 } 224 } 225 226 func (daemon *Daemon) releaseIngress(id string) { 227 controller := daemon.netController 228 229 if id == "" { 230 return 231 } 232 233 n, err := controller.NetworkByID(id) 234 if err != nil { 235 logrus.Errorf("failed to retrieve ingress network %s: %v", id, err) 236 return 237 } 238 239 if err := n.Delete(libnetwork.NetworkDeleteOptionRemoveLB); err != nil { 240 logrus.Errorf("Failed to delete ingress network %s: %v", n.ID(), err) 241 return 242 } 243 } 244 245 // SetNetworkBootstrapKeys sets the bootstrap keys. 246 func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error { 247 err := daemon.netController.SetKeys(keys) 248 if err == nil { 249 // Upon successful key setting dispatch the keys available event 250 daemon.cluster.SendClusterEvent(lncluster.EventNetworkKeysAvailable) 251 } 252 return err 253 } 254 255 // UpdateAttachment notifies the attacher about the attachment config. 256 func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error { 257 if daemon.clusterProvider == nil { 258 return fmt.Errorf("cluster provider is not initialized") 259 } 260 261 if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil { 262 return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config) 263 } 264 265 return nil 266 } 267 268 // WaitForDetachment makes the cluster manager wait for detachment of 269 // the container from the network. 270 func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error { 271 if daemon.clusterProvider == nil { 272 return fmt.Errorf("cluster provider is not initialized") 273 } 274 275 return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID) 276 } 277 278 // CreateManagedNetwork creates an agent network. 279 func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error { 280 _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true) 281 return err 282 } 283 284 // CreateNetwork creates a network with the given name, driver and other optional parameters 285 func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) { 286 resp, err := daemon.createNetwork(create, "", false) 287 if err != nil { 288 return nil, err 289 } 290 return resp, err 291 } 292 293 func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) { 294 if runconfig.IsPreDefinedNetwork(create.Name) { 295 return nil, PredefinedNetworkError(create.Name) 296 } 297 298 var warning string 299 nw, err := daemon.GetNetworkByName(create.Name) 300 if err != nil { 301 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 302 return nil, err 303 } 304 } 305 if nw != nil { 306 // check if user defined CheckDuplicate, if set true, return err 307 // otherwise prepare a warning message 308 if create.CheckDuplicate { 309 if !agent || nw.Info().Dynamic() { 310 return nil, libnetwork.NetworkNameError(create.Name) 311 } 312 } 313 warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) 314 } 315 316 c := daemon.netController 317 driver := create.Driver 318 if driver == "" { 319 driver = c.Config().Daemon.DefaultDriver 320 } 321 322 nwOptions := []libnetwork.NetworkOption{ 323 libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6), 324 libnetwork.NetworkOptionDriverOpts(create.Options), 325 libnetwork.NetworkOptionLabels(create.Labels), 326 libnetwork.NetworkOptionAttachable(create.Attachable), 327 libnetwork.NetworkOptionIngress(create.Ingress), 328 libnetwork.NetworkOptionScope(create.Scope), 329 } 330 331 if create.ConfigOnly { 332 nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly()) 333 } 334 335 if create.IPAM != nil { 336 ipam := create.IPAM 337 v4Conf, v6Conf, err := getIpamConfig(ipam.Config) 338 if err != nil { 339 return nil, err 340 } 341 nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options)) 342 } 343 344 if create.Internal { 345 nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork()) 346 } 347 if agent { 348 nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic()) 349 nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false)) 350 } 351 352 if create.ConfigFrom != nil { 353 nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network)) 354 } 355 356 if agent && driver == "overlay" { 357 nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id) 358 if !exists { 359 return nil, fmt.Errorf("Failed to find a load balancer IP to use for network: %v", id) 360 } 361 362 nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP)) 363 } 364 365 n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) 366 if err != nil { 367 if _, ok := err.(libnetwork.ErrDataStoreNotInitialized); ok { 368 // nolint: golint 369 return nil, errors.New("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.") 370 } 371 return nil, err 372 } 373 374 daemon.pluginRefCount(driver, driverapi.NetworkPluginEndpointType, plugingetter.Acquire) 375 if create.IPAM != nil { 376 daemon.pluginRefCount(create.IPAM.Driver, ipamapi.PluginEndpointType, plugingetter.Acquire) 377 } 378 daemon.LogNetworkEvent(n, "create") 379 380 return &types.NetworkCreateResponse{ 381 ID: n.ID(), 382 Warning: warning, 383 }, nil 384 } 385 386 func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) { 387 var builtinDrivers []string 388 389 if capability == driverapi.NetworkPluginEndpointType { 390 builtinDrivers = daemon.netController.BuiltinDrivers() 391 } else if capability == ipamapi.PluginEndpointType { 392 builtinDrivers = daemon.netController.BuiltinIPAMDrivers() 393 } 394 395 for _, d := range builtinDrivers { 396 if d == driver { 397 return 398 } 399 } 400 401 if daemon.PluginStore != nil { 402 _, err := daemon.PluginStore.Get(driver, capability, mode) 403 if err != nil { 404 logrus.WithError(err).WithFields(logrus.Fields{"mode": mode, "driver": driver}).Error("Error handling plugin refcount operation") 405 } 406 } 407 } 408 409 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) { 410 ipamV4Cfg := []*libnetwork.IpamConf{} 411 ipamV6Cfg := []*libnetwork.IpamConf{} 412 for _, d := range data { 413 iCfg := libnetwork.IpamConf{} 414 iCfg.PreferredPool = d.Subnet 415 iCfg.SubPool = d.IPRange 416 iCfg.Gateway = d.Gateway 417 iCfg.AuxAddresses = d.AuxAddress 418 ip, _, err := net.ParseCIDR(d.Subnet) 419 if err != nil { 420 return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err) 421 } 422 if ip.To4() != nil { 423 ipamV4Cfg = append(ipamV4Cfg, &iCfg) 424 } else { 425 ipamV6Cfg = append(ipamV6Cfg, &iCfg) 426 } 427 } 428 return ipamV4Cfg, ipamV6Cfg, nil 429 } 430 431 // UpdateContainerServiceConfig updates a service configuration. 432 func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error { 433 ctr, err := daemon.GetContainer(containerName) 434 if err != nil { 435 return err 436 } 437 438 ctr.NetworkSettings.Service = serviceConfig 439 return nil 440 } 441 442 // ConnectContainerToNetwork connects the given container to the given 443 // network. If either cannot be found, an err is returned. If the 444 // network cannot be set up, an err is returned. 445 func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error { 446 ctr, err := daemon.GetContainer(containerName) 447 if err != nil { 448 return err 449 } 450 return daemon.ConnectToNetwork(ctr, networkName, endpointConfig) 451 } 452 453 // DisconnectContainerFromNetwork disconnects the given container from 454 // the given network. If either cannot be found, an err is returned. 455 func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error { 456 ctr, err := daemon.GetContainer(containerName) 457 if err != nil { 458 if force { 459 return daemon.ForceEndpointDelete(containerName, networkName) 460 } 461 return err 462 } 463 return daemon.DisconnectFromNetwork(ctr, networkName, force) 464 } 465 466 // GetNetworkDriverList returns the list of plugins drivers 467 // registered for network. 468 func (daemon *Daemon) GetNetworkDriverList() []string { 469 if !daemon.NetworkControllerEnabled() { 470 return nil 471 } 472 473 pluginList := daemon.netController.BuiltinDrivers() 474 475 managedPlugins := daemon.PluginStore.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType) 476 477 for _, plugin := range managedPlugins { 478 pluginList = append(pluginList, plugin.Name()) 479 } 480 481 pluginMap := make(map[string]bool) 482 for _, plugin := range pluginList { 483 pluginMap[plugin] = true 484 } 485 486 networks := daemon.netController.Networks() 487 488 for _, nw := range networks { 489 if !pluginMap[nw.Type()] { 490 pluginList = append(pluginList, nw.Type()) 491 pluginMap[nw.Type()] = true 492 } 493 } 494 495 sort.Strings(pluginList) 496 497 return pluginList 498 } 499 500 // DeleteManagedNetwork deletes an agent network. 501 // The requirement of networkID is enforced. 502 func (daemon *Daemon) DeleteManagedNetwork(networkID string) error { 503 n, err := daemon.GetNetworkByID(networkID) 504 if err != nil { 505 return err 506 } 507 return daemon.deleteNetwork(n, true) 508 } 509 510 // DeleteNetwork destroys a network unless it's one of docker's predefined networks. 511 func (daemon *Daemon) DeleteNetwork(networkID string) error { 512 n, err := daemon.GetNetworkByID(networkID) 513 if err != nil { 514 return errors.Wrap(err, "could not find network by ID") 515 } 516 return daemon.deleteNetwork(n, false) 517 } 518 519 func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error { 520 if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic { 521 err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name()) 522 return errdefs.Forbidden(err) 523 } 524 525 if dynamic && !nw.Info().Dynamic() { 526 if runconfig.IsPreDefinedNetwork(nw.Name()) { 527 // Predefined networks now support swarm services. Make this 528 // a no-op when cluster requests to remove the predefined network. 529 return nil 530 } 531 err := fmt.Errorf("%s is not a dynamic network", nw.Name()) 532 return errdefs.Forbidden(err) 533 } 534 535 if err := nw.Delete(); err != nil { 536 return errors.Wrap(err, "error while removing network") 537 } 538 539 // If this is not a configuration only network, we need to 540 // update the corresponding remote drivers' reference counts 541 if !nw.Info().ConfigOnly() { 542 daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release) 543 ipamType, _, _, _ := nw.Info().IpamConfig() 544 daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release) 545 daemon.LogNetworkEvent(nw, "destroy") 546 } 547 548 return nil 549 } 550 551 // GetNetworks returns a list of all networks 552 func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) ([]types.NetworkResource, error) { 553 networks := daemon.getAllNetworks() 554 555 list := make([]types.NetworkResource, 0, len(networks)) 556 var idx map[string]libnetwork.Network 557 if config.Detailed { 558 idx = make(map[string]libnetwork.Network) 559 } 560 561 for _, n := range networks { 562 nr := buildNetworkResource(n) 563 list = append(list, nr) 564 if config.Detailed { 565 idx[nr.ID] = n 566 } 567 } 568 569 var err error 570 list, err = internalnetwork.FilterNetworks(list, filter) 571 if err != nil { 572 return nil, err 573 } 574 575 if config.Detailed { 576 for i, n := range list { 577 np := &n 578 buildDetailedNetworkResources(np, idx[n.ID], config.Verbose) 579 list[i] = *np 580 } 581 } 582 583 return list, nil 584 } 585 586 func buildNetworkResource(nw libnetwork.Network) types.NetworkResource { 587 r := types.NetworkResource{} 588 if nw == nil { 589 return r 590 } 591 592 info := nw.Info() 593 r.Name = nw.Name() 594 r.ID = nw.ID() 595 r.Created = info.Created() 596 r.Scope = info.Scope() 597 r.Driver = nw.Type() 598 r.EnableIPv6 = info.IPv6Enabled() 599 r.Internal = info.Internal() 600 r.Attachable = info.Attachable() 601 r.Ingress = info.Ingress() 602 r.Options = info.DriverOptions() 603 r.Containers = make(map[string]types.EndpointResource) 604 buildIpamResources(&r, info) 605 r.Labels = info.Labels() 606 r.ConfigOnly = info.ConfigOnly() 607 608 if cn := info.ConfigFrom(); cn != "" { 609 r.ConfigFrom = network.ConfigReference{Network: cn} 610 } 611 612 peers := info.Peers() 613 if len(peers) != 0 { 614 r.Peers = buildPeerInfoResources(peers) 615 } 616 617 return r 618 } 619 620 func buildDetailedNetworkResources(r *types.NetworkResource, nw libnetwork.Network, verbose bool) { 621 if nw == nil { 622 return 623 } 624 625 epl := nw.Endpoints() 626 for _, e := range epl { 627 ei := e.Info() 628 if ei == nil { 629 continue 630 } 631 sb := ei.Sandbox() 632 tmpID := e.ID() 633 key := "ep-" + tmpID 634 if sb != nil { 635 key = sb.ContainerID() 636 } 637 638 r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei) 639 } 640 if !verbose { 641 return 642 } 643 services := nw.Info().Services() 644 r.Services = make(map[string]network.ServiceInfo) 645 for name, service := range services { 646 tasks := []network.Task{} 647 for _, t := range service.Tasks { 648 tasks = append(tasks, network.Task{ 649 Name: t.Name, 650 EndpointID: t.EndpointID, 651 EndpointIP: t.EndpointIP, 652 Info: t.Info, 653 }) 654 } 655 r.Services[name] = network.ServiceInfo{ 656 VIP: service.VIP, 657 Ports: service.Ports, 658 Tasks: tasks, 659 LocalLBIndex: service.LocalLBIndex, 660 } 661 } 662 } 663 664 func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo { 665 peerInfo := make([]network.PeerInfo, 0, len(peers)) 666 for _, peer := range peers { 667 peerInfo = append(peerInfo, network.PeerInfo{ 668 Name: peer.Name, 669 IP: peer.IP, 670 }) 671 } 672 return peerInfo 673 } 674 675 func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo) { 676 id, opts, ipv4conf, ipv6conf := nwInfo.IpamConfig() 677 678 ipv4Info, ipv6Info := nwInfo.IpamInfo() 679 680 r.IPAM.Driver = id 681 682 r.IPAM.Options = opts 683 684 r.IPAM.Config = []network.IPAMConfig{} 685 for _, ip4 := range ipv4conf { 686 if ip4.PreferredPool == "" { 687 continue 688 } 689 iData := network.IPAMConfig{} 690 iData.Subnet = ip4.PreferredPool 691 iData.IPRange = ip4.SubPool 692 iData.Gateway = ip4.Gateway 693 iData.AuxAddress = ip4.AuxAddresses 694 r.IPAM.Config = append(r.IPAM.Config, iData) 695 } 696 697 if len(r.IPAM.Config) == 0 { 698 for _, ip4Info := range ipv4Info { 699 iData := network.IPAMConfig{} 700 iData.Subnet = ip4Info.IPAMData.Pool.String() 701 if ip4Info.IPAMData.Gateway != nil { 702 iData.Gateway = ip4Info.IPAMData.Gateway.IP.String() 703 } 704 r.IPAM.Config = append(r.IPAM.Config, iData) 705 } 706 } 707 708 hasIpv6Conf := false 709 for _, ip6 := range ipv6conf { 710 if ip6.PreferredPool == "" { 711 continue 712 } 713 hasIpv6Conf = true 714 iData := network.IPAMConfig{} 715 iData.Subnet = ip6.PreferredPool 716 iData.IPRange = ip6.SubPool 717 iData.Gateway = ip6.Gateway 718 iData.AuxAddress = ip6.AuxAddresses 719 r.IPAM.Config = append(r.IPAM.Config, iData) 720 } 721 722 if !hasIpv6Conf { 723 for _, ip6Info := range ipv6Info { 724 if ip6Info.IPAMData.Pool == nil { 725 continue 726 } 727 iData := network.IPAMConfig{} 728 iData.Subnet = ip6Info.IPAMData.Pool.String() 729 iData.Gateway = ip6Info.IPAMData.Gateway.String() 730 r.IPAM.Config = append(r.IPAM.Config, iData) 731 } 732 } 733 } 734 735 func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo) types.EndpointResource { 736 er := types.EndpointResource{} 737 738 er.EndpointID = id 739 er.Name = name 740 ei := info 741 if ei == nil { 742 return er 743 } 744 745 if iface := ei.Iface(); iface != nil { 746 if mac := iface.MacAddress(); mac != nil { 747 er.MacAddress = mac.String() 748 } 749 if ip := iface.Address(); ip != nil && len(ip.IP) > 0 { 750 er.IPv4Address = ip.String() 751 } 752 753 if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 { 754 er.IPv6Address = ipv6.String() 755 } 756 } 757 return er 758 } 759 760 // clearAttachableNetworks removes the attachable networks 761 // after disconnecting any connected container 762 func (daemon *Daemon) clearAttachableNetworks() { 763 for _, n := range daemon.getAllNetworks() { 764 if !n.Info().Attachable() { 765 continue 766 } 767 for _, ep := range n.Endpoints() { 768 epInfo := ep.Info() 769 if epInfo == nil { 770 continue 771 } 772 sb := epInfo.Sandbox() 773 if sb == nil { 774 continue 775 } 776 containerID := sb.ContainerID() 777 if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil { 778 logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v", 779 containerID, n.Name(), err) 780 } 781 } 782 if err := daemon.DeleteManagedNetwork(n.ID()); err != nil { 783 logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err) 784 } 785 } 786 } 787 788 // buildCreateEndpointOptions builds endpoint options from a given network. 789 func buildCreateEndpointOptions(c *container.Container, n libnetwork.Network, epConfig *network.EndpointSettings, sb libnetwork.Sandbox, daemonDNS []string) ([]libnetwork.EndpointOption, error) { 790 var ( 791 bindings = make(nat.PortMap) 792 pbList []networktypes.PortBinding 793 exposeList []networktypes.TransportPort 794 createOptions []libnetwork.EndpointOption 795 ) 796 797 defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() 798 799 if (!serviceDiscoveryOnDefaultNetwork() && n.Name() == defaultNetName) || 800 c.NetworkSettings.IsAnonymousEndpoint { 801 createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) 802 } 803 804 if epConfig != nil { 805 ipam := epConfig.IPAMConfig 806 807 if ipam != nil { 808 var ( 809 ipList []net.IP 810 ip, ip6, linkip net.IP 811 ) 812 813 for _, ips := range ipam.LinkLocalIPs { 814 if linkip = net.ParseIP(ips); linkip == nil && ips != "" { 815 return nil, errors.Errorf("Invalid link-local IP address: %s", ipam.LinkLocalIPs) 816 } 817 ipList = append(ipList, linkip) 818 819 } 820 821 if ip = net.ParseIP(ipam.IPv4Address); ip == nil && ipam.IPv4Address != "" { 822 return nil, errors.Errorf("Invalid IPv4 address: %s)", ipam.IPv4Address) 823 } 824 825 if ip6 = net.ParseIP(ipam.IPv6Address); ip6 == nil && ipam.IPv6Address != "" { 826 return nil, errors.Errorf("Invalid IPv6 address: %s)", ipam.IPv6Address) 827 } 828 829 createOptions = append(createOptions, 830 libnetwork.CreateOptionIpam(ip, ip6, ipList, nil)) 831 832 } 833 834 for _, alias := range epConfig.Aliases { 835 createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) 836 } 837 for k, v := range epConfig.DriverOpts { 838 createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v})) 839 } 840 } 841 842 if c.NetworkSettings.Service != nil { 843 svcCfg := c.NetworkSettings.Service 844 845 var vip string 846 if svcCfg.VirtualAddresses[n.ID()] != nil { 847 vip = svcCfg.VirtualAddresses[n.ID()].IPv4 848 } 849 850 var portConfigs []*libnetwork.PortConfig 851 for _, portConfig := range svcCfg.ExposedPorts { 852 portConfigs = append(portConfigs, &libnetwork.PortConfig{ 853 Name: portConfig.Name, 854 Protocol: libnetwork.PortConfig_Protocol(portConfig.Protocol), 855 TargetPort: portConfig.TargetPort, 856 PublishedPort: portConfig.PublishedPort, 857 }) 858 } 859 860 createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs, svcCfg.Aliases[n.ID()])) 861 } 862 863 if !containertypes.NetworkMode(n.Name()).IsUserDefined() { 864 createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution()) 865 } 866 867 // configs that are applicable only for the endpoint in the network 868 // to which container was connected to on docker run. 869 // Ideally all these network-specific endpoint configurations must be moved under 870 // container.NetworkSettings.Networks[n.Name()] 871 if n.Name() == c.HostConfig.NetworkMode.NetworkName() || 872 (n.Name() == defaultNetName && c.HostConfig.NetworkMode.IsDefault()) { 873 if c.Config.MacAddress != "" { 874 mac, err := net.ParseMAC(c.Config.MacAddress) 875 if err != nil { 876 return nil, err 877 } 878 879 genericOption := options.Generic{ 880 netlabel.MacAddress: mac, 881 } 882 883 createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) 884 } 885 886 } 887 888 // Port-mapping rules belong to the container & applicable only to non-internal networks 889 portmaps := getSandboxPortMapInfo(sb) 890 if n.Info().Internal() || len(portmaps) > 0 { 891 return createOptions, nil 892 } 893 894 if c.HostConfig.PortBindings != nil { 895 for p, b := range c.HostConfig.PortBindings { 896 bindings[p] = []nat.PortBinding{} 897 for _, bb := range b { 898 bindings[p] = append(bindings[p], nat.PortBinding{ 899 HostIP: bb.HostIP, 900 HostPort: bb.HostPort, 901 }) 902 } 903 } 904 } 905 906 portSpecs := c.Config.ExposedPorts 907 ports := make([]nat.Port, len(portSpecs)) 908 var i int 909 for p := range portSpecs { 910 ports[i] = p 911 i++ 912 } 913 nat.SortPortMap(ports, bindings) 914 for _, port := range ports { 915 expose := networktypes.TransportPort{} 916 expose.Proto = networktypes.ParseProtocol(port.Proto()) 917 expose.Port = uint16(port.Int()) 918 exposeList = append(exposeList, expose) 919 920 pb := networktypes.PortBinding{Port: expose.Port, Proto: expose.Proto} 921 binding := bindings[port] 922 for i := 0; i < len(binding); i++ { 923 pbCopy := pb.GetCopy() 924 newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) 925 var portStart, portEnd int 926 if err == nil { 927 portStart, portEnd, err = newP.Range() 928 } 929 if err != nil { 930 return nil, errors.Wrapf(err, "Error parsing HostPort value (%s)", binding[i].HostPort) 931 } 932 pbCopy.HostPort = uint16(portStart) 933 pbCopy.HostPortEnd = uint16(portEnd) 934 pbCopy.HostIP = net.ParseIP(binding[i].HostIP) 935 pbList = append(pbList, pbCopy) 936 } 937 938 if c.HostConfig.PublishAllPorts && len(binding) == 0 { 939 pbList = append(pbList, pb) 940 } 941 } 942 943 var dns []string 944 945 if len(c.HostConfig.DNS) > 0 { 946 dns = c.HostConfig.DNS 947 } else if len(daemonDNS) > 0 { 948 dns = daemonDNS 949 } 950 951 if len(dns) > 0 { 952 createOptions = append(createOptions, 953 libnetwork.CreateOptionDNS(dns)) 954 } 955 956 createOptions = append(createOptions, 957 libnetwork.CreateOptionPortMapping(pbList), 958 libnetwork.CreateOptionExposedPorts(exposeList)) 959 960 return createOptions, nil 961 } 962 963 // getSandboxPortMapInfo retrieves the current port-mapping programmed for the given sandbox 964 func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap { 965 pm := nat.PortMap{} 966 if sb == nil { 967 return pm 968 } 969 970 for _, ep := range sb.Endpoints() { 971 pm, _ = getEndpointPortMapInfo(ep) 972 if len(pm) > 0 { 973 break 974 } 975 } 976 return pm 977 } 978 979 func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) { 980 pm := nat.PortMap{} 981 driverInfo, err := ep.DriverInfo() 982 if err != nil { 983 return pm, err 984 } 985 986 if driverInfo == nil { 987 // It is not an error for epInfo to be nil 988 return pm, nil 989 } 990 991 if expData, ok := driverInfo[netlabel.ExposedPorts]; ok { 992 if exposedPorts, ok := expData.([]networktypes.TransportPort); ok { 993 for _, tp := range exposedPorts { 994 natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port))) 995 if err != nil { 996 return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err) 997 } 998 pm[natPort] = nil 999 } 1000 } 1001 } 1002 1003 mapData, ok := driverInfo[netlabel.PortMap] 1004 if !ok { 1005 return pm, nil 1006 } 1007 1008 if portMapping, ok := mapData.([]networktypes.PortBinding); ok { 1009 for _, pp := range portMapping { 1010 natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port))) 1011 if err != nil { 1012 return pm, err 1013 } 1014 natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))} 1015 pm[natPort] = append(pm[natPort], natBndg) 1016 } 1017 } 1018 1019 return pm, nil 1020 } 1021 1022 // buildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint. 1023 func buildEndpointInfo(networkSettings *internalnetwork.Settings, n libnetwork.Network, ep libnetwork.Endpoint) error { 1024 if ep == nil { 1025 return errors.New("endpoint cannot be nil") 1026 } 1027 1028 if networkSettings == nil { 1029 return errors.New("network cannot be nil") 1030 } 1031 1032 epInfo := ep.Info() 1033 if epInfo == nil { 1034 // It is not an error to get an empty endpoint info 1035 return nil 1036 } 1037 1038 if _, ok := networkSettings.Networks[n.Name()]; !ok { 1039 networkSettings.Networks[n.Name()] = &internalnetwork.EndpointSettings{ 1040 EndpointSettings: &network.EndpointSettings{}, 1041 } 1042 } 1043 networkSettings.Networks[n.Name()].NetworkID = n.ID() 1044 networkSettings.Networks[n.Name()].EndpointID = ep.ID() 1045 1046 iface := epInfo.Iface() 1047 if iface == nil { 1048 return nil 1049 } 1050 1051 if iface.MacAddress() != nil { 1052 networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() 1053 } 1054 1055 if iface.Address() != nil { 1056 ones, _ := iface.Address().Mask.Size() 1057 networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() 1058 networkSettings.Networks[n.Name()].IPPrefixLen = ones 1059 } 1060 1061 if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil { 1062 onesv6, _ := iface.AddressIPv6().Mask.Size() 1063 networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String() 1064 networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 1065 } 1066 1067 return nil 1068 } 1069 1070 // buildJoinOptions builds endpoint Join options from a given network. 1071 func buildJoinOptions(networkSettings *internalnetwork.Settings, n interface { 1072 Name() string 1073 }) ([]libnetwork.EndpointOption, error) { 1074 var joinOptions []libnetwork.EndpointOption 1075 if epConfig, ok := networkSettings.Networks[n.Name()]; ok { 1076 for _, str := range epConfig.Links { 1077 name, alias, err := opts.ParseLink(str) 1078 if err != nil { 1079 return nil, err 1080 } 1081 joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias)) 1082 } 1083 for k, v := range epConfig.DriverOpts { 1084 joinOptions = append(joinOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v})) 1085 } 1086 } 1087 1088 return joinOptions, nil 1089 }