github.com/rawahars/moby@v24.0.4+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/libnetwork" 21 lncluster "github.com/docker/docker/libnetwork/cluster" 22 "github.com/docker/docker/libnetwork/driverapi" 23 "github.com/docker/docker/libnetwork/ipamapi" 24 "github.com/docker/docker/libnetwork/netlabel" 25 "github.com/docker/docker/libnetwork/networkdb" 26 "github.com/docker/docker/libnetwork/options" 27 networktypes "github.com/docker/docker/libnetwork/types" 28 "github.com/docker/docker/opts" 29 "github.com/docker/docker/pkg/plugingetter" 30 "github.com/docker/docker/runconfig" 31 "github.com/docker/go-connections/nat" 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.Controller { 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().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 return daemon.createNetwork(create, "", false) 287 } 288 289 func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) { 290 if runconfig.IsPreDefinedNetwork(create.Name) { 291 return nil, PredefinedNetworkError(create.Name) 292 } 293 294 var warning string 295 nw, err := daemon.GetNetworkByName(create.Name) 296 if err != nil { 297 if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok { 298 return nil, err 299 } 300 } 301 if nw != nil { 302 // check if user defined CheckDuplicate, if set true, return err 303 // otherwise prepare a warning message 304 if create.CheckDuplicate { 305 if !agent || nw.Info().Dynamic() { 306 return nil, libnetwork.NetworkNameError(create.Name) 307 } 308 } 309 warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) 310 } 311 312 c := daemon.netController 313 driver := create.Driver 314 if driver == "" { 315 driver = c.Config().DefaultDriver 316 } 317 318 networkOptions := make(map[string]string) 319 for k, v := range create.Options { 320 networkOptions[k] = v 321 } 322 if defaultOpts, ok := daemon.configStore.DefaultNetworkOpts[driver]; create.ConfigFrom == nil && ok { 323 for k, v := range defaultOpts { 324 if _, ok := networkOptions[k]; !ok { 325 logrus.WithFields(logrus.Fields{"driver": driver, "network": id, k: v}).Debug("Applying network default option") 326 networkOptions[k] = v 327 } 328 } 329 } 330 331 nwOptions := []libnetwork.NetworkOption{ 332 libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6), 333 libnetwork.NetworkOptionDriverOpts(networkOptions), 334 libnetwork.NetworkOptionLabels(create.Labels), 335 libnetwork.NetworkOptionAttachable(create.Attachable), 336 libnetwork.NetworkOptionIngress(create.Ingress), 337 libnetwork.NetworkOptionScope(create.Scope), 338 } 339 340 if create.ConfigOnly { 341 nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly()) 342 } 343 344 if create.IPAM != nil { 345 ipam := create.IPAM 346 v4Conf, v6Conf, err := getIpamConfig(ipam.Config) 347 if err != nil { 348 return nil, err 349 } 350 nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options)) 351 } 352 353 if create.Internal { 354 nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork()) 355 } 356 if agent { 357 nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic()) 358 nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false)) 359 } 360 361 if create.ConfigFrom != nil { 362 nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network)) 363 } 364 365 if agent && driver == "overlay" { 366 nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id) 367 if !exists { 368 return nil, fmt.Errorf("failed to find a load balancer IP to use for network: %v", id) 369 } 370 371 nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP)) 372 } 373 374 n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) 375 if err != nil { 376 if errors.Is(err, libnetwork.ErrDataStoreNotInitialized) { 377 //nolint: revive 378 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.") 379 } 380 return nil, err 381 } 382 383 daemon.pluginRefCount(driver, driverapi.NetworkPluginEndpointType, plugingetter.Acquire) 384 if create.IPAM != nil { 385 daemon.pluginRefCount(create.IPAM.Driver, ipamapi.PluginEndpointType, plugingetter.Acquire) 386 } 387 daemon.LogNetworkEvent(n, "create") 388 389 return &types.NetworkCreateResponse{ 390 ID: n.ID(), 391 Warning: warning, 392 }, nil 393 } 394 395 func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) { 396 var builtinDrivers []string 397 398 if capability == driverapi.NetworkPluginEndpointType { 399 builtinDrivers = daemon.netController.BuiltinDrivers() 400 } else if capability == ipamapi.PluginEndpointType { 401 builtinDrivers = daemon.netController.BuiltinIPAMDrivers() 402 } 403 404 for _, d := range builtinDrivers { 405 if d == driver { 406 return 407 } 408 } 409 410 if daemon.PluginStore != nil { 411 _, err := daemon.PluginStore.Get(driver, capability, mode) 412 if err != nil { 413 logrus.WithError(err).WithFields(logrus.Fields{"mode": mode, "driver": driver}).Error("Error handling plugin refcount operation") 414 } 415 } 416 } 417 418 func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) { 419 ipamV4Cfg := []*libnetwork.IpamConf{} 420 ipamV6Cfg := []*libnetwork.IpamConf{} 421 for _, d := range data { 422 iCfg := libnetwork.IpamConf{} 423 iCfg.PreferredPool = d.Subnet 424 iCfg.SubPool = d.IPRange 425 iCfg.Gateway = d.Gateway 426 iCfg.AuxAddresses = d.AuxAddress 427 ip, _, err := net.ParseCIDR(d.Subnet) 428 if err != nil { 429 return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err) 430 } 431 if ip.To4() != nil { 432 ipamV4Cfg = append(ipamV4Cfg, &iCfg) 433 } else { 434 ipamV6Cfg = append(ipamV6Cfg, &iCfg) 435 } 436 } 437 return ipamV4Cfg, ipamV6Cfg, nil 438 } 439 440 // UpdateContainerServiceConfig updates a service configuration. 441 func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error { 442 ctr, err := daemon.GetContainer(containerName) 443 if err != nil { 444 return err 445 } 446 447 ctr.NetworkSettings.Service = serviceConfig 448 return nil 449 } 450 451 // ConnectContainerToNetwork connects the given container to the given 452 // network. If either cannot be found, an err is returned. If the 453 // network cannot be set up, an err is returned. 454 func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error { 455 ctr, err := daemon.GetContainer(containerName) 456 if err != nil { 457 return err 458 } 459 return daemon.ConnectToNetwork(ctr, networkName, endpointConfig) 460 } 461 462 // DisconnectContainerFromNetwork disconnects the given container from 463 // the given network. If either cannot be found, an err is returned. 464 func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error { 465 ctr, err := daemon.GetContainer(containerName) 466 if err != nil { 467 if force { 468 return daemon.ForceEndpointDelete(containerName, networkName) 469 } 470 return err 471 } 472 return daemon.DisconnectFromNetwork(ctr, networkName, force) 473 } 474 475 // GetNetworkDriverList returns the list of plugins drivers 476 // registered for network. 477 func (daemon *Daemon) GetNetworkDriverList() []string { 478 if !daemon.NetworkControllerEnabled() { 479 return nil 480 } 481 482 pluginList := daemon.netController.BuiltinDrivers() 483 484 managedPlugins := daemon.PluginStore.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType) 485 486 for _, plugin := range managedPlugins { 487 pluginList = append(pluginList, plugin.Name()) 488 } 489 490 pluginMap := make(map[string]bool) 491 for _, plugin := range pluginList { 492 pluginMap[plugin] = true 493 } 494 495 networks := daemon.netController.Networks() 496 497 for _, nw := range networks { 498 if !pluginMap[nw.Type()] { 499 pluginList = append(pluginList, nw.Type()) 500 pluginMap[nw.Type()] = true 501 } 502 } 503 504 sort.Strings(pluginList) 505 506 return pluginList 507 } 508 509 // DeleteManagedNetwork deletes an agent network. 510 // The requirement of networkID is enforced. 511 func (daemon *Daemon) DeleteManagedNetwork(networkID string) error { 512 n, err := daemon.GetNetworkByID(networkID) 513 if err != nil { 514 return err 515 } 516 return daemon.deleteNetwork(n, true) 517 } 518 519 // DeleteNetwork destroys a network unless it's one of docker's predefined networks. 520 func (daemon *Daemon) DeleteNetwork(networkID string) error { 521 n, err := daemon.GetNetworkByID(networkID) 522 if err != nil { 523 return errors.Wrap(err, "could not find network by ID") 524 } 525 return daemon.deleteNetwork(n, false) 526 } 527 528 func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error { 529 if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic { 530 err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name()) 531 return errdefs.Forbidden(err) 532 } 533 534 if dynamic && !nw.Info().Dynamic() { 535 if runconfig.IsPreDefinedNetwork(nw.Name()) { 536 // Predefined networks now support swarm services. Make this 537 // a no-op when cluster requests to remove the predefined network. 538 return nil 539 } 540 err := fmt.Errorf("%s is not a dynamic network", nw.Name()) 541 return errdefs.Forbidden(err) 542 } 543 544 if err := nw.Delete(); err != nil { 545 return errors.Wrap(err, "error while removing network") 546 } 547 548 // If this is not a configuration only network, we need to 549 // update the corresponding remote drivers' reference counts 550 if !nw.Info().ConfigOnly() { 551 daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release) 552 ipamType, _, _, _ := nw.Info().IpamConfig() 553 daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release) 554 daemon.LogNetworkEvent(nw, "destroy") 555 } 556 557 return nil 558 } 559 560 // GetNetworks returns a list of all networks 561 func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) ([]types.NetworkResource, error) { 562 networks := daemon.getAllNetworks() 563 564 list := make([]types.NetworkResource, 0, len(networks)) 565 var idx map[string]libnetwork.Network 566 if config.Detailed { 567 idx = make(map[string]libnetwork.Network) 568 } 569 570 for _, n := range networks { 571 nr := buildNetworkResource(n) 572 list = append(list, nr) 573 if config.Detailed { 574 idx[nr.ID] = n 575 } 576 } 577 578 var err error 579 list, err = internalnetwork.FilterNetworks(list, filter) 580 if err != nil { 581 return nil, err 582 } 583 584 if config.Detailed { 585 for i := range list { 586 np := &list[i] 587 buildDetailedNetworkResources(np, idx[np.ID], config.Verbose) 588 list[i] = *np 589 } 590 } 591 592 return list, nil 593 } 594 595 func buildNetworkResource(nw libnetwork.Network) types.NetworkResource { 596 r := types.NetworkResource{} 597 if nw == nil { 598 return r 599 } 600 601 info := nw.Info() 602 r.Name = nw.Name() 603 r.ID = nw.ID() 604 r.Created = info.Created() 605 r.Scope = info.Scope() 606 r.Driver = nw.Type() 607 r.EnableIPv6 = info.IPv6Enabled() 608 r.Internal = info.Internal() 609 r.Attachable = info.Attachable() 610 r.Ingress = info.Ingress() 611 r.Options = info.DriverOptions() 612 r.Containers = make(map[string]types.EndpointResource) 613 buildIpamResources(&r, info) 614 r.Labels = info.Labels() 615 r.ConfigOnly = info.ConfigOnly() 616 617 if cn := info.ConfigFrom(); cn != "" { 618 r.ConfigFrom = network.ConfigReference{Network: cn} 619 } 620 621 peers := info.Peers() 622 if len(peers) != 0 { 623 r.Peers = buildPeerInfoResources(peers) 624 } 625 626 return r 627 } 628 629 func buildDetailedNetworkResources(r *types.NetworkResource, nw libnetwork.Network, verbose bool) { 630 if nw == nil { 631 return 632 } 633 634 epl := nw.Endpoints() 635 for _, e := range epl { 636 ei := e.Info() 637 if ei == nil { 638 continue 639 } 640 sb := ei.Sandbox() 641 tmpID := e.ID() 642 key := "ep-" + tmpID 643 if sb != nil { 644 key = sb.ContainerID() 645 } 646 647 r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei) 648 } 649 if !verbose { 650 return 651 } 652 services := nw.Info().Services() 653 r.Services = make(map[string]network.ServiceInfo) 654 for name, service := range services { 655 tasks := []network.Task{} 656 for _, t := range service.Tasks { 657 tasks = append(tasks, network.Task{ 658 Name: t.Name, 659 EndpointID: t.EndpointID, 660 EndpointIP: t.EndpointIP, 661 Info: t.Info, 662 }) 663 } 664 r.Services[name] = network.ServiceInfo{ 665 VIP: service.VIP, 666 Ports: service.Ports, 667 Tasks: tasks, 668 LocalLBIndex: service.LocalLBIndex, 669 } 670 } 671 } 672 673 func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo { 674 peerInfo := make([]network.PeerInfo, 0, len(peers)) 675 for _, peer := range peers { 676 peerInfo = append(peerInfo, network.PeerInfo{ 677 Name: peer.Name, 678 IP: peer.IP, 679 }) 680 } 681 return peerInfo 682 } 683 684 func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo) { 685 id, opts, ipv4conf, ipv6conf := nwInfo.IpamConfig() 686 687 ipv4Info, ipv6Info := nwInfo.IpamInfo() 688 689 r.IPAM.Driver = id 690 691 r.IPAM.Options = opts 692 693 r.IPAM.Config = []network.IPAMConfig{} 694 for _, ip4 := range ipv4conf { 695 if ip4.PreferredPool == "" { 696 continue 697 } 698 iData := network.IPAMConfig{} 699 iData.Subnet = ip4.PreferredPool 700 iData.IPRange = ip4.SubPool 701 iData.Gateway = ip4.Gateway 702 iData.AuxAddress = ip4.AuxAddresses 703 r.IPAM.Config = append(r.IPAM.Config, iData) 704 } 705 706 if len(r.IPAM.Config) == 0 { 707 for _, ip4Info := range ipv4Info { 708 iData := network.IPAMConfig{} 709 iData.Subnet = ip4Info.IPAMData.Pool.String() 710 if ip4Info.IPAMData.Gateway != nil { 711 iData.Gateway = ip4Info.IPAMData.Gateway.IP.String() 712 } 713 r.IPAM.Config = append(r.IPAM.Config, iData) 714 } 715 } 716 717 hasIpv6Conf := false 718 for _, ip6 := range ipv6conf { 719 if ip6.PreferredPool == "" { 720 continue 721 } 722 hasIpv6Conf = true 723 iData := network.IPAMConfig{} 724 iData.Subnet = ip6.PreferredPool 725 iData.IPRange = ip6.SubPool 726 iData.Gateway = ip6.Gateway 727 iData.AuxAddress = ip6.AuxAddresses 728 r.IPAM.Config = append(r.IPAM.Config, iData) 729 } 730 731 if !hasIpv6Conf { 732 for _, ip6Info := range ipv6Info { 733 if ip6Info.IPAMData.Pool == nil { 734 continue 735 } 736 iData := network.IPAMConfig{} 737 iData.Subnet = ip6Info.IPAMData.Pool.String() 738 iData.Gateway = ip6Info.IPAMData.Gateway.String() 739 r.IPAM.Config = append(r.IPAM.Config, iData) 740 } 741 } 742 } 743 744 func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo) types.EndpointResource { 745 er := types.EndpointResource{} 746 747 er.EndpointID = id 748 er.Name = name 749 ei := info 750 if ei == nil { 751 return er 752 } 753 754 if iface := ei.Iface(); iface != nil { 755 if mac := iface.MacAddress(); mac != nil { 756 er.MacAddress = mac.String() 757 } 758 if ip := iface.Address(); ip != nil && len(ip.IP) > 0 { 759 er.IPv4Address = ip.String() 760 } 761 762 if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 { 763 er.IPv6Address = ipv6.String() 764 } 765 } 766 return er 767 } 768 769 // clearAttachableNetworks removes the attachable networks 770 // after disconnecting any connected container 771 func (daemon *Daemon) clearAttachableNetworks() { 772 for _, n := range daemon.getAllNetworks() { 773 if !n.Info().Attachable() { 774 continue 775 } 776 for _, ep := range n.Endpoints() { 777 epInfo := ep.Info() 778 if epInfo == nil { 779 continue 780 } 781 sb := epInfo.Sandbox() 782 if sb == nil { 783 continue 784 } 785 containerID := sb.ContainerID() 786 if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil { 787 logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v", 788 containerID, n.Name(), err) 789 } 790 } 791 if err := daemon.DeleteManagedNetwork(n.ID()); err != nil { 792 logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err) 793 } 794 } 795 } 796 797 // buildCreateEndpointOptions builds endpoint options from a given network. 798 func buildCreateEndpointOptions(c *container.Container, n libnetwork.Network, epConfig *network.EndpointSettings, sb *libnetwork.Sandbox, daemonDNS []string) ([]libnetwork.EndpointOption, error) { 799 var ( 800 bindings = make(nat.PortMap) 801 pbList []networktypes.PortBinding 802 exposeList []networktypes.TransportPort 803 createOptions []libnetwork.EndpointOption 804 ) 805 806 defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() 807 808 if (!serviceDiscoveryOnDefaultNetwork() && n.Name() == defaultNetName) || 809 c.NetworkSettings.IsAnonymousEndpoint { 810 createOptions = append(createOptions, libnetwork.CreateOptionAnonymous()) 811 } 812 813 if epConfig != nil { 814 ipam := epConfig.IPAMConfig 815 816 if ipam != nil { 817 var ( 818 ipList []net.IP 819 ip, ip6, linkip net.IP 820 ) 821 822 for _, ips := range ipam.LinkLocalIPs { 823 if linkip = net.ParseIP(ips); linkip == nil && ips != "" { 824 return nil, errors.Errorf("Invalid link-local IP address: %s", ipam.LinkLocalIPs) 825 } 826 ipList = append(ipList, linkip) 827 } 828 829 if ip = net.ParseIP(ipam.IPv4Address); ip == nil && ipam.IPv4Address != "" { 830 return nil, errors.Errorf("Invalid IPv4 address: %s)", ipam.IPv4Address) 831 } 832 833 if ip6 = net.ParseIP(ipam.IPv6Address); ip6 == nil && ipam.IPv6Address != "" { 834 return nil, errors.Errorf("Invalid IPv6 address: %s)", ipam.IPv6Address) 835 } 836 837 createOptions = append(createOptions, 838 libnetwork.CreateOptionIpam(ip, ip6, ipList, nil)) 839 } 840 841 for _, alias := range epConfig.Aliases { 842 createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias)) 843 } 844 for k, v := range epConfig.DriverOpts { 845 createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v})) 846 } 847 } 848 849 if c.NetworkSettings.Service != nil { 850 svcCfg := c.NetworkSettings.Service 851 852 var vip string 853 if svcCfg.VirtualAddresses[n.ID()] != nil { 854 vip = svcCfg.VirtualAddresses[n.ID()].IPv4 855 } 856 857 var portConfigs []*libnetwork.PortConfig 858 for _, portConfig := range svcCfg.ExposedPorts { 859 portConfigs = append(portConfigs, &libnetwork.PortConfig{ 860 Name: portConfig.Name, 861 Protocol: libnetwork.PortConfig_Protocol(portConfig.Protocol), 862 TargetPort: portConfig.TargetPort, 863 PublishedPort: portConfig.PublishedPort, 864 }) 865 } 866 867 createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs, svcCfg.Aliases[n.ID()])) 868 } 869 870 if !containertypes.NetworkMode(n.Name()).IsUserDefined() { 871 createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution()) 872 } 873 874 // configs that are applicable only for the endpoint in the network 875 // to which container was connected to on docker run. 876 // Ideally all these network-specific endpoint configurations must be moved under 877 // container.NetworkSettings.Networks[n.Name()] 878 if n.Name() == c.HostConfig.NetworkMode.NetworkName() || 879 (n.Name() == defaultNetName && c.HostConfig.NetworkMode.IsDefault()) { 880 if c.Config.MacAddress != "" { 881 mac, err := net.ParseMAC(c.Config.MacAddress) 882 if err != nil { 883 return nil, err 884 } 885 886 genericOption := options.Generic{ 887 netlabel.MacAddress: mac, 888 } 889 890 createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) 891 } 892 } 893 894 // Port-mapping rules belong to the container & applicable only to non-internal networks 895 portmaps := getPortMapInfo(sb) 896 if n.Info().Internal() || len(portmaps) > 0 { 897 return createOptions, nil 898 } 899 900 if c.HostConfig.PortBindings != nil { 901 for p, b := range c.HostConfig.PortBindings { 902 bindings[p] = []nat.PortBinding{} 903 for _, bb := range b { 904 bindings[p] = append(bindings[p], nat.PortBinding{ 905 HostIP: bb.HostIP, 906 HostPort: bb.HostPort, 907 }) 908 } 909 } 910 } 911 912 portSpecs := c.Config.ExposedPorts 913 ports := make([]nat.Port, len(portSpecs)) 914 var i int 915 for p := range portSpecs { 916 ports[i] = p 917 i++ 918 } 919 nat.SortPortMap(ports, bindings) 920 for _, port := range ports { 921 expose := networktypes.TransportPort{} 922 expose.Proto = networktypes.ParseProtocol(port.Proto()) 923 expose.Port = uint16(port.Int()) 924 exposeList = append(exposeList, expose) 925 926 pb := networktypes.PortBinding{Port: expose.Port, Proto: expose.Proto} 927 binding := bindings[port] 928 for i := 0; i < len(binding); i++ { 929 pbCopy := pb.GetCopy() 930 newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) 931 var portStart, portEnd int 932 if err == nil { 933 portStart, portEnd, err = newP.Range() 934 } 935 if err != nil { 936 return nil, errors.Wrapf(err, "Error parsing HostPort value (%s)", binding[i].HostPort) 937 } 938 pbCopy.HostPort = uint16(portStart) 939 pbCopy.HostPortEnd = uint16(portEnd) 940 pbCopy.HostIP = net.ParseIP(binding[i].HostIP) 941 pbList = append(pbList, pbCopy) 942 } 943 944 if c.HostConfig.PublishAllPorts && len(binding) == 0 { 945 pbList = append(pbList, pb) 946 } 947 } 948 949 var dns []string 950 951 if len(c.HostConfig.DNS) > 0 { 952 dns = c.HostConfig.DNS 953 } else if len(daemonDNS) > 0 { 954 dns = daemonDNS 955 } 956 957 if len(dns) > 0 { 958 createOptions = append(createOptions, 959 libnetwork.CreateOptionDNS(dns)) 960 } 961 962 createOptions = append(createOptions, 963 libnetwork.CreateOptionPortMapping(pbList), 964 libnetwork.CreateOptionExposedPorts(exposeList)) 965 966 return createOptions, nil 967 } 968 969 // getPortMapInfo retrieves the current port-mapping programmed for the given sandbox 970 func getPortMapInfo(sb *libnetwork.Sandbox) nat.PortMap { 971 pm := nat.PortMap{} 972 if sb == nil { 973 return pm 974 } 975 976 for _, ep := range sb.Endpoints() { 977 pm, _ = getEndpointPortMapInfo(ep) 978 if len(pm) > 0 { 979 break 980 } 981 } 982 return pm 983 } 984 985 func getEndpointPortMapInfo(ep *libnetwork.Endpoint) (nat.PortMap, error) { 986 pm := nat.PortMap{} 987 driverInfo, err := ep.DriverInfo() 988 if err != nil { 989 return pm, err 990 } 991 992 if driverInfo == nil { 993 // It is not an error for epInfo to be nil 994 return pm, nil 995 } 996 997 if expData, ok := driverInfo[netlabel.ExposedPorts]; ok { 998 if exposedPorts, ok := expData.([]networktypes.TransportPort); ok { 999 for _, tp := range exposedPorts { 1000 natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port))) 1001 if err != nil { 1002 return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err) 1003 } 1004 pm[natPort] = nil 1005 } 1006 } 1007 } 1008 1009 mapData, ok := driverInfo[netlabel.PortMap] 1010 if !ok { 1011 return pm, nil 1012 } 1013 1014 if portMapping, ok := mapData.([]networktypes.PortBinding); ok { 1015 for _, pp := range portMapping { 1016 natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port))) 1017 if err != nil { 1018 return pm, err 1019 } 1020 natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))} 1021 pm[natPort] = append(pm[natPort], natBndg) 1022 } 1023 } 1024 1025 return pm, nil 1026 } 1027 1028 // buildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint. 1029 func buildEndpointInfo(networkSettings *internalnetwork.Settings, n libnetwork.Network, ep *libnetwork.Endpoint) error { 1030 if ep == nil { 1031 return errors.New("endpoint cannot be nil") 1032 } 1033 1034 if networkSettings == nil { 1035 return errors.New("network cannot be nil") 1036 } 1037 1038 epInfo := ep.Info() 1039 if epInfo == nil { 1040 // It is not an error to get an empty endpoint info 1041 return nil 1042 } 1043 1044 if _, ok := networkSettings.Networks[n.Name()]; !ok { 1045 networkSettings.Networks[n.Name()] = &internalnetwork.EndpointSettings{ 1046 EndpointSettings: &network.EndpointSettings{}, 1047 } 1048 } 1049 networkSettings.Networks[n.Name()].NetworkID = n.ID() 1050 networkSettings.Networks[n.Name()].EndpointID = ep.ID() 1051 1052 iface := epInfo.Iface() 1053 if iface == nil { 1054 return nil 1055 } 1056 1057 if iface.MacAddress() != nil { 1058 networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String() 1059 } 1060 1061 if iface.Address() != nil { 1062 ones, _ := iface.Address().Mask.Size() 1063 networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String() 1064 networkSettings.Networks[n.Name()].IPPrefixLen = ones 1065 } 1066 1067 if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil { 1068 onesv6, _ := iface.AddressIPv6().Mask.Size() 1069 networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String() 1070 networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6 1071 } 1072 1073 return nil 1074 } 1075 1076 // buildJoinOptions builds endpoint Join options from a given network. 1077 func buildJoinOptions(networkSettings *internalnetwork.Settings, n interface { 1078 Name() string 1079 }) ([]libnetwork.EndpointOption, error) { 1080 var joinOptions []libnetwork.EndpointOption 1081 if epConfig, ok := networkSettings.Networks[n.Name()]; ok { 1082 for _, str := range epConfig.Links { 1083 name, alias, err := opts.ParseLink(str) 1084 if err != nil { 1085 return nil, err 1086 } 1087 joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias)) 1088 } 1089 for k, v := range epConfig.DriverOpts { 1090 joinOptions = append(joinOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v})) 1091 } 1092 } 1093 1094 return joinOptions, nil 1095 }