github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/daemon/network.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/Sirupsen/logrus"
    10  	"github.com/docker/docker/api/errors"
    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/runconfig"
    15  	"github.com/docker/libnetwork"
    16  	networktypes "github.com/docker/libnetwork/types"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  // NetworkControllerEnabled checks if the networking stack is enabled.
    21  // This feature depends on OS primitives and it's disabled in systems like Windows.
    22  func (daemon *Daemon) NetworkControllerEnabled() bool {
    23  	return daemon.netController != nil
    24  }
    25  
    26  // FindNetwork function finds a network for a given string that can represent network name or id
    27  func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
    28  	// Find by Name
    29  	n, err := daemon.GetNetworkByName(idName)
    30  	if err != nil && !isNoSuchNetworkError(err) {
    31  		return nil, err
    32  	}
    33  
    34  	if n != nil {
    35  		return n, nil
    36  	}
    37  
    38  	// Find by id
    39  	return daemon.GetNetworkByID(idName)
    40  }
    41  
    42  func isNoSuchNetworkError(err error) bool {
    43  	_, ok := err.(libnetwork.ErrNoSuchNetwork)
    44  	return ok
    45  }
    46  
    47  // GetNetworkByID function returns a network whose ID begins with the given prefix.
    48  // It fails with an error if no matching, or more than one matching, networks are found.
    49  func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) {
    50  	list := daemon.GetNetworksByID(partialID)
    51  
    52  	if len(list) == 0 {
    53  		return nil, libnetwork.ErrNoSuchNetwork(partialID)
    54  	}
    55  	if len(list) > 1 {
    56  		return nil, libnetwork.ErrInvalidID(partialID)
    57  	}
    58  	return list[0], nil
    59  }
    60  
    61  // GetNetworkByName function returns a network for a given network name.
    62  // If no network name is given, the default network is returned.
    63  func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
    64  	c := daemon.netController
    65  	if c == nil {
    66  		return nil, libnetwork.ErrNoSuchNetwork(name)
    67  	}
    68  	if name == "" {
    69  		name = c.Config().Daemon.DefaultNetwork
    70  	}
    71  	return c.NetworkByName(name)
    72  }
    73  
    74  // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
    75  func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
    76  	c := daemon.netController
    77  	if c == nil {
    78  		return nil
    79  	}
    80  	list := []libnetwork.Network{}
    81  	l := func(nw libnetwork.Network) bool {
    82  		if strings.HasPrefix(nw.ID(), partialID) {
    83  			list = append(list, nw)
    84  		}
    85  		return false
    86  	}
    87  	c.WalkNetworks(l)
    88  
    89  	return list
    90  }
    91  
    92  // getAllNetworks returns a list containing all networks
    93  func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
    94  	c := daemon.netController
    95  	list := []libnetwork.Network{}
    96  	l := func(nw libnetwork.Network) bool {
    97  		list = append(list, nw)
    98  		return false
    99  	}
   100  	c.WalkNetworks(l)
   101  
   102  	return list
   103  }
   104  
   105  func isIngressNetwork(name string) bool {
   106  	return name == "ingress"
   107  }
   108  
   109  var ingressChan = make(chan struct{}, 1)
   110  
   111  func ingressWait() func() {
   112  	ingressChan <- struct{}{}
   113  	return func() { <-ingressChan }
   114  }
   115  
   116  // SetupIngress setups ingress networking.
   117  func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error {
   118  	ip, _, err := net.ParseCIDR(nodeIP)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	go func() {
   124  		controller := daemon.netController
   125  		controller.AgentInitWait()
   126  
   127  		if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID {
   128  			if err := controller.SandboxDestroy("ingress-sbox"); err != nil {
   129  				logrus.Errorf("Failed to delete stale ingress sandbox: %v", err)
   130  				return
   131  			}
   132  
   133  			// Cleanup any stale endpoints that might be left over during previous iterations
   134  			epList := n.Endpoints()
   135  			for _, ep := range epList {
   136  				if err := ep.Delete(true); err != nil {
   137  					logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
   138  				}
   139  			}
   140  
   141  			if err := n.Delete(); err != nil {
   142  				logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err)
   143  				return
   144  			}
   145  		}
   146  
   147  		if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
   148  			// If it is any other error other than already
   149  			// exists error log error and return.
   150  			if _, ok := err.(libnetwork.NetworkNameError); !ok {
   151  				logrus.Errorf("Failed creating ingress network: %v", err)
   152  				return
   153  			}
   154  
   155  			// Otherwise continue down the call to create or recreate sandbox.
   156  		}
   157  
   158  		n, err := daemon.GetNetworkByID(create.ID)
   159  		if err != nil {
   160  			logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
   161  			return
   162  		}
   163  
   164  		sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress())
   165  		if err != nil {
   166  			if _, ok := err.(networktypes.ForbiddenError); !ok {
   167  				logrus.Errorf("Failed creating ingress sandbox: %v", err)
   168  			}
   169  			return
   170  		}
   171  
   172  		ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil))
   173  		if err != nil {
   174  			logrus.Errorf("Failed creating ingress endpoint: %v", err)
   175  			return
   176  		}
   177  
   178  		if err := ep.Join(sb, nil); err != nil {
   179  			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
   180  		}
   181  	}()
   182  
   183  	return nil
   184  }
   185  
   186  // SetNetworkBootstrapKeys sets the bootstrap keys.
   187  func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
   188  	return daemon.netController.SetKeys(keys)
   189  }
   190  
   191  // UpdateAttachment notifies the attacher about the attachment config.
   192  func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
   193  	if daemon.clusterProvider == nil {
   194  		return fmt.Errorf("cluster provider is not initialized")
   195  	}
   196  
   197  	if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
   198  		return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
   199  	}
   200  
   201  	return nil
   202  }
   203  
   204  // WaitForDetachment makes the cluster manager wait for detachment of
   205  // the container from the network.
   206  func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
   207  	if daemon.clusterProvider == nil {
   208  		return fmt.Errorf("cluster provider is not initialized")
   209  	}
   210  
   211  	return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
   212  }
   213  
   214  // CreateManagedNetwork creates an agent network.
   215  func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
   216  	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
   217  	return err
   218  }
   219  
   220  // CreateNetwork creates a network with the given name, driver and other optional parameters
   221  func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
   222  	resp, err := daemon.createNetwork(create, "", false)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	return resp, err
   227  }
   228  
   229  func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
   230  	// If there is a pending ingress network creation wait here
   231  	// since ingress network creation can happen via node download
   232  	// from manager or task download.
   233  	if isIngressNetwork(create.Name) {
   234  		defer ingressWait()()
   235  	}
   236  
   237  	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
   238  		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
   239  		return nil, errors.NewRequestForbiddenError(err)
   240  	}
   241  
   242  	var warning string
   243  	nw, err := daemon.GetNetworkByName(create.Name)
   244  	if err != nil {
   245  		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
   246  			return nil, err
   247  		}
   248  	}
   249  	if nw != nil {
   250  		if create.CheckDuplicate {
   251  			return nil, libnetwork.NetworkNameError(create.Name)
   252  		}
   253  		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
   254  	}
   255  
   256  	c := daemon.netController
   257  	driver := create.Driver
   258  	if driver == "" {
   259  		driver = c.Config().Daemon.DefaultDriver
   260  	}
   261  
   262  	nwOptions := []libnetwork.NetworkOption{
   263  		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
   264  		libnetwork.NetworkOptionDriverOpts(create.Options),
   265  		libnetwork.NetworkOptionLabels(create.Labels),
   266  	}
   267  
   268  	if create.IPAM != nil {
   269  		ipam := create.IPAM
   270  		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
   271  		if err != nil {
   272  			return nil, err
   273  		}
   274  		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
   275  	}
   276  
   277  	if create.Internal {
   278  		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
   279  	}
   280  	if agent {
   281  		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
   282  		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
   283  	}
   284  
   285  	if isIngressNetwork(create.Name) {
   286  		nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress())
   287  	}
   288  
   289  	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
   290  	if err != nil {
   291  		return nil, err
   292  	}
   293  
   294  	daemon.LogNetworkEvent(n, "create")
   295  
   296  	return &types.NetworkCreateResponse{
   297  		ID:      n.ID(),
   298  		Warning: warning,
   299  	}, nil
   300  }
   301  
   302  func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
   303  	ipamV4Cfg := []*libnetwork.IpamConf{}
   304  	ipamV6Cfg := []*libnetwork.IpamConf{}
   305  	for _, d := range data {
   306  		iCfg := libnetwork.IpamConf{}
   307  		iCfg.PreferredPool = d.Subnet
   308  		iCfg.SubPool = d.IPRange
   309  		iCfg.Gateway = d.Gateway
   310  		iCfg.AuxAddresses = d.AuxAddress
   311  		ip, _, err := net.ParseCIDR(d.Subnet)
   312  		if err != nil {
   313  			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
   314  		}
   315  		if ip.To4() != nil {
   316  			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
   317  		} else {
   318  			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
   319  		}
   320  	}
   321  	return ipamV4Cfg, ipamV6Cfg, nil
   322  }
   323  
   324  // UpdateContainerServiceConfig updates a service configuration.
   325  func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
   326  	container, err := daemon.GetContainer(containerName)
   327  	if err != nil {
   328  		return err
   329  	}
   330  
   331  	container.NetworkSettings.Service = serviceConfig
   332  	return nil
   333  }
   334  
   335  // ConnectContainerToNetwork connects the given container to the given
   336  // network. If either cannot be found, an err is returned. If the
   337  // network cannot be set up, an err is returned.
   338  func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
   339  	container, err := daemon.GetContainer(containerName)
   340  	if err != nil {
   341  		return err
   342  	}
   343  	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
   344  }
   345  
   346  // DisconnectContainerFromNetwork disconnects the given container from
   347  // the given network. If either cannot be found, an err is returned.
   348  func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
   349  	container, err := daemon.GetContainer(containerName)
   350  	if err != nil {
   351  		if force {
   352  			return daemon.ForceEndpointDelete(containerName, networkName)
   353  		}
   354  		return err
   355  	}
   356  	return daemon.DisconnectFromNetwork(container, networkName, force)
   357  }
   358  
   359  // GetNetworkDriverList returns the list of plugins drivers
   360  // registered for network.
   361  func (daemon *Daemon) GetNetworkDriverList() []string {
   362  	if !daemon.NetworkControllerEnabled() {
   363  		return nil
   364  	}
   365  
   366  	pluginList := daemon.netController.BuiltinDrivers()
   367  	pluginMap := make(map[string]bool)
   368  	for _, plugin := range pluginList {
   369  		pluginMap[plugin] = true
   370  	}
   371  
   372  	networks := daemon.netController.Networks()
   373  
   374  	for _, network := range networks {
   375  		if !pluginMap[network.Type()] {
   376  			pluginList = append(pluginList, network.Type())
   377  			pluginMap[network.Type()] = true
   378  		}
   379  	}
   380  
   381  	sort.Strings(pluginList)
   382  
   383  	return pluginList
   384  }
   385  
   386  // DeleteManagedNetwork deletes an agent network.
   387  func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
   388  	return daemon.deleteNetwork(networkID, true)
   389  }
   390  
   391  // DeleteNetwork destroys a network unless it's one of docker's predefined networks.
   392  func (daemon *Daemon) DeleteNetwork(networkID string) error {
   393  	return daemon.deleteNetwork(networkID, false)
   394  }
   395  
   396  func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
   397  	nw, err := daemon.FindNetwork(networkID)
   398  	if err != nil {
   399  		return err
   400  	}
   401  
   402  	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
   403  		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
   404  		return errors.NewRequestForbiddenError(err)
   405  	}
   406  
   407  	if err := nw.Delete(); err != nil {
   408  		return err
   409  	}
   410  	daemon.LogNetworkEvent(nw, "destroy")
   411  	return nil
   412  }
   413  
   414  // GetNetworks returns a list of all networks
   415  func (daemon *Daemon) GetNetworks() []libnetwork.Network {
   416  	return daemon.getAllNetworks()
   417  }