github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/daemon/network.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"runtime"
     7  	"sort"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/docker/docker/api/types"
    12  	"github.com/docker/docker/api/types/network"
    13  	clustertypes "github.com/docker/docker/daemon/cluster/provider"
    14  	"github.com/docker/docker/pkg/plugingetter"
    15  	"github.com/docker/docker/runconfig"
    16  	"github.com/docker/libnetwork"
    17  	lncluster "github.com/docker/libnetwork/cluster"
    18  	"github.com/docker/libnetwork/driverapi"
    19  	"github.com/docker/libnetwork/ipamapi"
    20  	networktypes "github.com/docker/libnetwork/types"
    21  	"github.com/pkg/errors"
    22  	"github.com/sirupsen/logrus"
    23  	"golang.org/x/net/context"
    24  )
    25  
    26  // NetworkControllerEnabled checks if the networking stack is enabled.
    27  // This feature depends on OS primitives and it's disabled in systems like Windows.
    28  func (daemon *Daemon) NetworkControllerEnabled() bool {
    29  	return daemon.netController != nil
    30  }
    31  
    32  // FindNetwork function finds a network for a given string that can represent network name or id
    33  func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
    34  	// 1. match by full ID.
    35  	n, err := daemon.GetNetworkByID(idName)
    36  	if err == nil || !isNoSuchNetworkError(err) {
    37  		return n, err
    38  	}
    39  
    40  	// 2. match by full name
    41  	n, err = daemon.GetNetworkByName(idName)
    42  	if err == nil || !isNoSuchNetworkError(err) {
    43  		return n, err
    44  	}
    45  
    46  	// 3. match by ID prefix
    47  	list := daemon.GetNetworksByIDPrefix(idName)
    48  	if len(list) == 0 {
    49  		// Be very careful to change the error type here, the libnetwork.ErrNoSuchNetwork error is used by the controller
    50  		// to retry the creation of the network as managed through the swarm manager
    51  		return nil, errors.WithStack(notFound(libnetwork.ErrNoSuchNetwork(idName)))
    52  	}
    53  	if len(list) > 1 {
    54  		return nil, errors.WithStack(invalidIdentifier(idName))
    55  	}
    56  	return list[0], nil
    57  }
    58  
    59  func isNoSuchNetworkError(err error) bool {
    60  	_, ok := err.(libnetwork.ErrNoSuchNetwork)
    61  	return ok
    62  }
    63  
    64  // GetNetworkByID function returns a network whose ID matches the given ID.
    65  // It fails with an error if no matching network is found.
    66  func (daemon *Daemon) GetNetworkByID(id string) (libnetwork.Network, error) {
    67  	c := daemon.netController
    68  	if c == nil {
    69  		return nil, libnetwork.ErrNoSuchNetwork(id)
    70  	}
    71  	return c.NetworkByID(id)
    72  }
    73  
    74  // GetNetworkByName function returns a network for a given network name.
    75  // If no network name is given, the default network is returned.
    76  func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
    77  	c := daemon.netController
    78  	if c == nil {
    79  		return nil, libnetwork.ErrNoSuchNetwork(name)
    80  	}
    81  	if name == "" {
    82  		name = c.Config().Daemon.DefaultNetwork
    83  	}
    84  	return c.NetworkByName(name)
    85  }
    86  
    87  // GetNetworksByIDPrefix returns a list of networks whose ID partially matches zero or more networks
    88  func (daemon *Daemon) GetNetworksByIDPrefix(partialID string) []libnetwork.Network {
    89  	c := daemon.netController
    90  	if c == nil {
    91  		return nil
    92  	}
    93  	list := []libnetwork.Network{}
    94  	l := func(nw libnetwork.Network) bool {
    95  		if strings.HasPrefix(nw.ID(), partialID) {
    96  			list = append(list, nw)
    97  		}
    98  		return false
    99  	}
   100  	c.WalkNetworks(l)
   101  
   102  	return list
   103  }
   104  
   105  // getAllNetworks returns a list containing all networks
   106  func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
   107  	return daemon.netController.Networks()
   108  }
   109  
   110  type ingressJob struct {
   111  	create  *clustertypes.NetworkCreateRequest
   112  	ip      net.IP
   113  	jobDone chan struct{}
   114  }
   115  
   116  var (
   117  	ingressWorkerOnce  sync.Once
   118  	ingressJobsChannel chan *ingressJob
   119  	ingressID          string
   120  )
   121  
   122  func (daemon *Daemon) startIngressWorker() {
   123  	ingressJobsChannel = make(chan *ingressJob, 100)
   124  	go func() {
   125  		// nolint: gosimple
   126  		for {
   127  			select {
   128  			case r := <-ingressJobsChannel:
   129  				if r.create != nil {
   130  					daemon.setupIngress(r.create, r.ip, ingressID)
   131  					ingressID = r.create.ID
   132  				} else {
   133  					daemon.releaseIngress(ingressID)
   134  					ingressID = ""
   135  				}
   136  				close(r.jobDone)
   137  			}
   138  		}
   139  	}()
   140  }
   141  
   142  // enqueueIngressJob adds a ingress add/rm request to the worker queue.
   143  // It guarantees the worker is started.
   144  func (daemon *Daemon) enqueueIngressJob(job *ingressJob) {
   145  	ingressWorkerOnce.Do(daemon.startIngressWorker)
   146  	ingressJobsChannel <- job
   147  }
   148  
   149  // SetupIngress setups ingress networking.
   150  // The function returns a channel which will signal the caller when the programming is completed.
   151  func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) (<-chan struct{}, error) {
   152  	ip, _, err := net.ParseCIDR(nodeIP)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	done := make(chan struct{})
   157  	daemon.enqueueIngressJob(&ingressJob{&create, ip, done})
   158  	return done, nil
   159  }
   160  
   161  // ReleaseIngress releases the ingress networking.
   162  // The function returns a channel which will signal the caller when the programming is completed.
   163  func (daemon *Daemon) ReleaseIngress() (<-chan struct{}, error) {
   164  	done := make(chan struct{})
   165  	daemon.enqueueIngressJob(&ingressJob{nil, nil, done})
   166  	return done, nil
   167  }
   168  
   169  func (daemon *Daemon) setupIngress(create *clustertypes.NetworkCreateRequest, ip net.IP, staleID string) {
   170  	controller := daemon.netController
   171  	controller.AgentInitWait()
   172  
   173  	if staleID != "" && staleID != create.ID {
   174  		daemon.releaseIngress(staleID)
   175  	}
   176  
   177  	if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
   178  		// If it is any other error other than already
   179  		// exists error log error and return.
   180  		if _, ok := err.(libnetwork.NetworkNameError); !ok {
   181  			logrus.Errorf("Failed creating ingress network: %v", err)
   182  			return
   183  		}
   184  		// Otherwise continue down the call to create or recreate sandbox.
   185  	}
   186  
   187  	_, err := daemon.GetNetworkByID(create.ID)
   188  	if err != nil {
   189  		logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
   190  	}
   191  }
   192  
   193  func (daemon *Daemon) releaseIngress(id string) {
   194  	controller := daemon.netController
   195  
   196  	if id == "" {
   197  		return
   198  	}
   199  
   200  	n, err := controller.NetworkByID(id)
   201  	if err != nil {
   202  		logrus.Errorf("failed to retrieve ingress network %s: %v", id, err)
   203  		return
   204  	}
   205  
   206  	if err := n.Delete(); err != nil {
   207  		logrus.Errorf("Failed to delete ingress network %s: %v", n.ID(), err)
   208  		return
   209  	}
   210  }
   211  
   212  // SetNetworkBootstrapKeys sets the bootstrap keys.
   213  func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
   214  	err := daemon.netController.SetKeys(keys)
   215  	if err == nil {
   216  		// Upon successful key setting dispatch the keys available event
   217  		daemon.cluster.SendClusterEvent(lncluster.EventNetworkKeysAvailable)
   218  	}
   219  	return err
   220  }
   221  
   222  // UpdateAttachment notifies the attacher about the attachment config.
   223  func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
   224  	if daemon.clusterProvider == nil {
   225  		return fmt.Errorf("cluster provider is not initialized")
   226  	}
   227  
   228  	if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
   229  		return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
   230  	}
   231  
   232  	return nil
   233  }
   234  
   235  // WaitForDetachment makes the cluster manager wait for detachment of
   236  // the container from the network.
   237  func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
   238  	if daemon.clusterProvider == nil {
   239  		return fmt.Errorf("cluster provider is not initialized")
   240  	}
   241  
   242  	return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
   243  }
   244  
   245  // CreateManagedNetwork creates an agent network.
   246  func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
   247  	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
   248  	return err
   249  }
   250  
   251  // CreateNetwork creates a network with the given name, driver and other optional parameters
   252  func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
   253  	resp, err := daemon.createNetwork(create, "", false)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	return resp, err
   258  }
   259  
   260  func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
   261  	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
   262  		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
   263  		return nil, notAllowedError{err}
   264  	}
   265  
   266  	var warning string
   267  	nw, err := daemon.GetNetworkByName(create.Name)
   268  	if err != nil {
   269  		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
   270  			return nil, err
   271  		}
   272  	}
   273  	if nw != nil {
   274  		// check if user defined CheckDuplicate, if set true, return err
   275  		// otherwise prepare a warning message
   276  		if create.CheckDuplicate {
   277  			return nil, libnetwork.NetworkNameError(create.Name)
   278  		}
   279  		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
   280  	}
   281  
   282  	c := daemon.netController
   283  	driver := create.Driver
   284  	if driver == "" {
   285  		driver = c.Config().Daemon.DefaultDriver
   286  	}
   287  
   288  	nwOptions := []libnetwork.NetworkOption{
   289  		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
   290  		libnetwork.NetworkOptionDriverOpts(create.Options),
   291  		libnetwork.NetworkOptionLabels(create.Labels),
   292  		libnetwork.NetworkOptionAttachable(create.Attachable),
   293  		libnetwork.NetworkOptionIngress(create.Ingress),
   294  		libnetwork.NetworkOptionScope(create.Scope),
   295  	}
   296  
   297  	if create.ConfigOnly {
   298  		nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly())
   299  	}
   300  
   301  	if create.IPAM != nil {
   302  		ipam := create.IPAM
   303  		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
   304  		if err != nil {
   305  			return nil, err
   306  		}
   307  		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
   308  	}
   309  
   310  	if create.Internal {
   311  		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
   312  	}
   313  	if agent {
   314  		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
   315  		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
   316  	}
   317  
   318  	if create.ConfigFrom != nil {
   319  		nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network))
   320  	}
   321  
   322  	if agent && driver == "overlay" && (create.Ingress || runtime.GOOS == "windows") {
   323  		nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id)
   324  		if !exists {
   325  			return nil, fmt.Errorf("Failed to find a load balancer IP to use for network: %v", id)
   326  		}
   327  
   328  		nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP))
   329  	}
   330  
   331  	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
   332  	if err != nil {
   333  		if _, ok := err.(libnetwork.ErrDataStoreNotInitialized); ok {
   334  			// nolint: golint
   335  			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.")
   336  		}
   337  		return nil, err
   338  	}
   339  
   340  	daemon.pluginRefCount(driver, driverapi.NetworkPluginEndpointType, plugingetter.Acquire)
   341  	if create.IPAM != nil {
   342  		daemon.pluginRefCount(create.IPAM.Driver, ipamapi.PluginEndpointType, plugingetter.Acquire)
   343  	}
   344  	daemon.LogNetworkEvent(n, "create")
   345  
   346  	return &types.NetworkCreateResponse{
   347  		ID:      n.ID(),
   348  		Warning: warning,
   349  	}, nil
   350  }
   351  
   352  func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) {
   353  	var builtinDrivers []string
   354  
   355  	if capability == driverapi.NetworkPluginEndpointType {
   356  		builtinDrivers = daemon.netController.BuiltinDrivers()
   357  	} else if capability == ipamapi.PluginEndpointType {
   358  		builtinDrivers = daemon.netController.BuiltinIPAMDrivers()
   359  	}
   360  
   361  	for _, d := range builtinDrivers {
   362  		if d == driver {
   363  			return
   364  		}
   365  	}
   366  
   367  	if daemon.PluginStore != nil {
   368  		_, err := daemon.PluginStore.Get(driver, capability, mode)
   369  		if err != nil {
   370  			logrus.WithError(err).WithFields(logrus.Fields{"mode": mode, "driver": driver}).Error("Error handling plugin refcount operation")
   371  		}
   372  	}
   373  }
   374  
   375  func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
   376  	ipamV4Cfg := []*libnetwork.IpamConf{}
   377  	ipamV6Cfg := []*libnetwork.IpamConf{}
   378  	for _, d := range data {
   379  		iCfg := libnetwork.IpamConf{}
   380  		iCfg.PreferredPool = d.Subnet
   381  		iCfg.SubPool = d.IPRange
   382  		iCfg.Gateway = d.Gateway
   383  		iCfg.AuxAddresses = d.AuxAddress
   384  		ip, _, err := net.ParseCIDR(d.Subnet)
   385  		if err != nil {
   386  			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
   387  		}
   388  		if ip.To4() != nil {
   389  			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
   390  		} else {
   391  			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
   392  		}
   393  	}
   394  	return ipamV4Cfg, ipamV6Cfg, nil
   395  }
   396  
   397  // UpdateContainerServiceConfig updates a service configuration.
   398  func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
   399  	container, err := daemon.GetContainer(containerName)
   400  	if err != nil {
   401  		return err
   402  	}
   403  
   404  	container.NetworkSettings.Service = serviceConfig
   405  	return nil
   406  }
   407  
   408  // ConnectContainerToNetwork connects the given container to the given
   409  // network. If either cannot be found, an err is returned. If the
   410  // network cannot be set up, an err is returned.
   411  func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
   412  	container, err := daemon.GetContainer(containerName)
   413  	if err != nil {
   414  		return err
   415  	}
   416  	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
   417  }
   418  
   419  // DisconnectContainerFromNetwork disconnects the given container from
   420  // the given network. If either cannot be found, an err is returned.
   421  func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
   422  	container, err := daemon.GetContainer(containerName)
   423  	if err != nil {
   424  		if force {
   425  			return daemon.ForceEndpointDelete(containerName, networkName)
   426  		}
   427  		return err
   428  	}
   429  	return daemon.DisconnectFromNetwork(container, networkName, force)
   430  }
   431  
   432  // GetNetworkDriverList returns the list of plugins drivers
   433  // registered for network.
   434  func (daemon *Daemon) GetNetworkDriverList() []string {
   435  	if !daemon.NetworkControllerEnabled() {
   436  		return nil
   437  	}
   438  
   439  	pluginList := daemon.netController.BuiltinDrivers()
   440  
   441  	managedPlugins := daemon.PluginStore.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
   442  
   443  	for _, plugin := range managedPlugins {
   444  		pluginList = append(pluginList, plugin.Name())
   445  	}
   446  
   447  	pluginMap := make(map[string]bool)
   448  	for _, plugin := range pluginList {
   449  		pluginMap[plugin] = true
   450  	}
   451  
   452  	networks := daemon.netController.Networks()
   453  
   454  	for _, network := range networks {
   455  		if !pluginMap[network.Type()] {
   456  			pluginList = append(pluginList, network.Type())
   457  			pluginMap[network.Type()] = true
   458  		}
   459  	}
   460  
   461  	sort.Strings(pluginList)
   462  
   463  	return pluginList
   464  }
   465  
   466  // DeleteManagedNetwork deletes an agent network.
   467  func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
   468  	return daemon.deleteNetwork(networkID, true)
   469  }
   470  
   471  // DeleteNetwork destroys a network unless it's one of docker's predefined networks.
   472  func (daemon *Daemon) DeleteNetwork(networkID string) error {
   473  	return daemon.deleteNetwork(networkID, false)
   474  }
   475  
   476  func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
   477  	nw, err := daemon.FindNetwork(networkID)
   478  	if err != nil {
   479  		return err
   480  	}
   481  
   482  	if nw.Info().Ingress() {
   483  		return nil
   484  	}
   485  
   486  	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
   487  		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
   488  		return notAllowedError{err}
   489  	}
   490  
   491  	if dynamic && !nw.Info().Dynamic() {
   492  		if runconfig.IsPreDefinedNetwork(nw.Name()) {
   493  			// Predefined networks now support swarm services. Make this
   494  			// a no-op when cluster requests to remove the predefined network.
   495  			return nil
   496  		}
   497  		err := fmt.Errorf("%s is not a dynamic network", nw.Name())
   498  		return notAllowedError{err}
   499  	}
   500  
   501  	if err := nw.Delete(); err != nil {
   502  		return err
   503  	}
   504  
   505  	// If this is not a configuration only network, we need to
   506  	// update the corresponding remote drivers' reference counts
   507  	if !nw.Info().ConfigOnly() {
   508  		daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release)
   509  		ipamType, _, _, _ := nw.Info().IpamConfig()
   510  		daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release)
   511  		daemon.LogNetworkEvent(nw, "destroy")
   512  	}
   513  
   514  	return nil
   515  }
   516  
   517  // GetNetworks returns a list of all networks
   518  func (daemon *Daemon) GetNetworks() []libnetwork.Network {
   519  	return daemon.getAllNetworks()
   520  }
   521  
   522  // clearAttachableNetworks removes the attachable networks
   523  // after disconnecting any connected container
   524  func (daemon *Daemon) clearAttachableNetworks() {
   525  	for _, n := range daemon.GetNetworks() {
   526  		if !n.Info().Attachable() {
   527  			continue
   528  		}
   529  		for _, ep := range n.Endpoints() {
   530  			epInfo := ep.Info()
   531  			if epInfo == nil {
   532  				continue
   533  			}
   534  			sb := epInfo.Sandbox()
   535  			if sb == nil {
   536  				continue
   537  			}
   538  			containerID := sb.ContainerID()
   539  			if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil {
   540  				logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v",
   541  					containerID, n.Name(), err)
   542  			}
   543  		}
   544  		if err := daemon.DeleteManagedNetwork(n.ID()); err != nil {
   545  			logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err)
   546  		}
   547  	}
   548  }