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  }