github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/allocator/cnmallocator/networkallocator.go (about)

     1  package cnmallocator
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/pkg/plugingetter"
    10  	"github.com/docker/libnetwork/datastore"
    11  	"github.com/docker/libnetwork/driverapi"
    12  	"github.com/docker/libnetwork/drvregistry"
    13  	"github.com/docker/libnetwork/ipamapi"
    14  	"github.com/docker/libnetwork/netlabel"
    15  	"github.com/docker/swarmkit/api"
    16  	"github.com/docker/swarmkit/log"
    17  	"github.com/docker/swarmkit/manager/allocator/networkallocator"
    18  	"github.com/pkg/errors"
    19  	"github.com/sirupsen/logrus"
    20  )
    21  
    22  const (
    23  	// DefaultDriver defines the name of the driver to be used by
    24  	// default if a network without any driver name specified is
    25  	// created.
    26  	DefaultDriver = "overlay"
    27  )
    28  
    29  // cnmNetworkAllocator acts as the controller for all network related operations
    30  // like managing network and IPAM drivers and also creating and
    31  // deleting networks and the associated resources.
    32  type cnmNetworkAllocator struct {
    33  	// The driver register which manages all internal and external
    34  	// IPAM and network drivers.
    35  	drvRegistry *drvregistry.DrvRegistry
    36  
    37  	// The port allocator instance for allocating node ports
    38  	portAllocator *portAllocator
    39  
    40  	// Local network state used by cnmNetworkAllocator to do network management.
    41  	networks map[string]*network
    42  
    43  	// Allocator state to indicate if allocation has been
    44  	// successfully completed for this service.
    45  	services map[string]struct{}
    46  
    47  	// Allocator state to indicate if allocation has been
    48  	// successfully completed for this task.
    49  	tasks map[string]struct{}
    50  
    51  	// Allocator state to indicate if allocation has been
    52  	// successfully completed for this node on this network.
    53  	// outer map key: node id
    54  	// inner map key: network id
    55  	nodes map[string]map[string]struct{}
    56  }
    57  
    58  // Local in-memory state related to network that need to be tracked by cnmNetworkAllocator
    59  type network struct {
    60  	// A local cache of the store object.
    61  	nw *api.Network
    62  
    63  	// pools is used to save the internal poolIDs needed when
    64  	// releasing the pool.
    65  	pools map[string]string
    66  
    67  	// endpoints is a map of endpoint IP to the poolID from which it
    68  	// was allocated.
    69  	endpoints map[string]string
    70  
    71  	// isNodeLocal indicates whether the scope of the network's resources
    72  	// is local to the node. If true, it means the resources can only be
    73  	// allocated locally by the node where the network will be deployed.
    74  	// In this the swarm manager will skip the allocations.
    75  	isNodeLocal bool
    76  }
    77  
    78  type networkDriver struct {
    79  	driver     driverapi.Driver
    80  	name       string
    81  	capability *driverapi.Capability
    82  }
    83  
    84  type initializer struct {
    85  	fn    drvregistry.InitFunc
    86  	ntype string
    87  }
    88  
    89  // NetworkConfig is used to store network related cluster config in the Manager.
    90  type NetworkConfig struct {
    91  	// DefaultAddrPool specifies default subnet pool for global scope networks
    92  	DefaultAddrPool []string
    93  
    94  	// SubnetSize specifies the subnet size of the networks created from
    95  	// the default subnet pool
    96  	SubnetSize uint32
    97  
    98  	// VXLANUDPPort specifies the UDP port number for VXLAN traffic
    99  	VXLANUDPPort uint32
   100  }
   101  
   102  // New returns a new NetworkAllocator handle
   103  func New(pg plugingetter.PluginGetter, netConfig *NetworkConfig) (networkallocator.NetworkAllocator, error) {
   104  	na := &cnmNetworkAllocator{
   105  		networks: make(map[string]*network),
   106  		services: make(map[string]struct{}),
   107  		tasks:    make(map[string]struct{}),
   108  		nodes:    make(map[string]map[string]struct{}),
   109  	}
   110  
   111  	// There are no driver configurations and notification
   112  	// functions as of now.
   113  	reg, err := drvregistry.New(nil, nil, nil, nil, pg)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	if err := initializeDrivers(reg); err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	if err = initIPAMDrivers(reg, netConfig); err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	pa, err := newPortAllocator()
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  
   131  	na.portAllocator = pa
   132  	na.drvRegistry = reg
   133  	return na, nil
   134  }
   135  
   136  // Allocate allocates all the necessary resources both general
   137  // and driver-specific which may be specified in the NetworkSpec
   138  func (na *cnmNetworkAllocator) Allocate(n *api.Network) error {
   139  	if _, ok := na.networks[n.ID]; ok {
   140  		return fmt.Errorf("network %s already allocated", n.ID)
   141  	}
   142  
   143  	d, err := na.resolveDriver(n)
   144  	if err != nil {
   145  		return err
   146  	}
   147  
   148  	nw := &network{
   149  		nw:          n,
   150  		endpoints:   make(map[string]string),
   151  		isNodeLocal: d.capability.DataScope == datastore.LocalScope,
   152  	}
   153  
   154  	// No swarm-level allocation can be provided by the network driver for
   155  	// node-local networks. Only thing needed is populating the driver's name
   156  	// in the driver's state.
   157  	if nw.isNodeLocal {
   158  		n.DriverState = &api.Driver{
   159  			Name: d.name,
   160  		}
   161  		// In order to support backward compatibility with older daemon
   162  		// versions which assumes the network attachment to contains
   163  		// non nil IPAM attribute, passing an empty object
   164  		n.IPAM = &api.IPAMOptions{Driver: &api.Driver{}}
   165  	} else {
   166  		nw.pools, err = na.allocatePools(n)
   167  		if err != nil {
   168  			return errors.Wrapf(err, "failed allocating pools and gateway IP for network %s", n.ID)
   169  		}
   170  
   171  		if err := na.allocateDriverState(n); err != nil {
   172  			na.freePools(n, nw.pools)
   173  			return errors.Wrapf(err, "failed while allocating driver state for network %s", n.ID)
   174  		}
   175  	}
   176  
   177  	na.networks[n.ID] = nw
   178  
   179  	return nil
   180  }
   181  
   182  func (na *cnmNetworkAllocator) getNetwork(id string) *network {
   183  	return na.networks[id]
   184  }
   185  
   186  // Deallocate frees all the general and driver specific resources
   187  // which were assigned to the passed network.
   188  func (na *cnmNetworkAllocator) Deallocate(n *api.Network) error {
   189  	localNet := na.getNetwork(n.ID)
   190  	if localNet == nil {
   191  		return fmt.Errorf("could not get networker state for network %s", n.ID)
   192  	}
   193  
   194  	// No swarm-level resource deallocation needed for node-local networks
   195  	if localNet.isNodeLocal {
   196  		delete(na.networks, n.ID)
   197  		return nil
   198  	}
   199  
   200  	if err := na.freeDriverState(n); err != nil {
   201  		return errors.Wrapf(err, "failed to free driver state for network %s", n.ID)
   202  	}
   203  
   204  	delete(na.networks, n.ID)
   205  
   206  	return na.freePools(n, localNet.pools)
   207  }
   208  
   209  // AllocateService allocates all the network resources such as virtual
   210  // IP and ports needed by the service.
   211  func (na *cnmNetworkAllocator) AllocateService(s *api.Service) (err error) {
   212  	if err = na.portAllocator.serviceAllocatePorts(s); err != nil {
   213  		return err
   214  	}
   215  	defer func() {
   216  		if err != nil {
   217  			na.DeallocateService(s)
   218  		}
   219  	}()
   220  
   221  	if s.Endpoint == nil {
   222  		s.Endpoint = &api.Endpoint{}
   223  	}
   224  	s.Endpoint.Spec = s.Spec.Endpoint.Copy()
   225  
   226  	// If ResolutionMode is DNSRR do not try allocating VIPs, but
   227  	// free any VIP from previous state.
   228  	if s.Spec.Endpoint != nil && s.Spec.Endpoint.Mode == api.ResolutionModeDNSRoundRobin {
   229  		for _, vip := range s.Endpoint.VirtualIPs {
   230  			if err := na.deallocateVIP(vip); err != nil {
   231  				// don't bail here, deallocate as many as possible.
   232  				log.L.WithError(err).
   233  					WithField("vip.network", vip.NetworkID).
   234  					WithField("vip.addr", vip.Addr).Error("error deallocating vip")
   235  			}
   236  		}
   237  
   238  		s.Endpoint.VirtualIPs = nil
   239  
   240  		delete(na.services, s.ID)
   241  		return nil
   242  	}
   243  
   244  	specNetworks := serviceNetworks(s)
   245  
   246  	// Allocate VIPs for all the pre-populated endpoint attachments
   247  	eVIPs := s.Endpoint.VirtualIPs[:0]
   248  
   249  vipLoop:
   250  	for _, eAttach := range s.Endpoint.VirtualIPs {
   251  		if na.IsVIPOnIngressNetwork(eAttach) && networkallocator.IsIngressNetworkNeeded(s) {
   252  			if err = na.allocateVIP(eAttach); err != nil {
   253  				return err
   254  			}
   255  			eVIPs = append(eVIPs, eAttach)
   256  			continue vipLoop
   257  
   258  		}
   259  		for _, nAttach := range specNetworks {
   260  			if nAttach.Target == eAttach.NetworkID {
   261  				log.L.WithFields(logrus.Fields{"service_id": s.ID, "vip": eAttach.Addr}).Debug("allocate vip")
   262  				if err = na.allocateVIP(eAttach); err != nil {
   263  					return err
   264  				}
   265  				eVIPs = append(eVIPs, eAttach)
   266  				continue vipLoop
   267  			}
   268  		}
   269  		// If the network of the VIP is not part of the service spec,
   270  		// deallocate the vip
   271  		na.deallocateVIP(eAttach)
   272  	}
   273  
   274  networkLoop:
   275  	for _, nAttach := range specNetworks {
   276  		for _, vip := range s.Endpoint.VirtualIPs {
   277  			if vip.NetworkID == nAttach.Target {
   278  				continue networkLoop
   279  			}
   280  		}
   281  
   282  		vip := &api.Endpoint_VirtualIP{NetworkID: nAttach.Target}
   283  		if err = na.allocateVIP(vip); err != nil {
   284  			return err
   285  		}
   286  
   287  		eVIPs = append(eVIPs, vip)
   288  	}
   289  
   290  	if len(eVIPs) > 0 {
   291  		na.services[s.ID] = struct{}{}
   292  	} else {
   293  		delete(na.services, s.ID)
   294  	}
   295  
   296  	s.Endpoint.VirtualIPs = eVIPs
   297  	return nil
   298  }
   299  
   300  // DeallocateService de-allocates all the network resources such as
   301  // virtual IP and ports associated with the service.
   302  func (na *cnmNetworkAllocator) DeallocateService(s *api.Service) error {
   303  	if s.Endpoint == nil {
   304  		return nil
   305  	}
   306  
   307  	for _, vip := range s.Endpoint.VirtualIPs {
   308  		if err := na.deallocateVIP(vip); err != nil {
   309  			// don't bail here, deallocate as many as possible.
   310  			log.L.WithError(err).
   311  				WithField("vip.network", vip.NetworkID).
   312  				WithField("vip.addr", vip.Addr).Error("error deallocating vip")
   313  		}
   314  	}
   315  	s.Endpoint.VirtualIPs = nil
   316  
   317  	na.portAllocator.serviceDeallocatePorts(s)
   318  	delete(na.services, s.ID)
   319  
   320  	return nil
   321  }
   322  
   323  // IsAllocated returns if the passed network has been allocated or not.
   324  func (na *cnmNetworkAllocator) IsAllocated(n *api.Network) bool {
   325  	_, ok := na.networks[n.ID]
   326  	return ok
   327  }
   328  
   329  // IsTaskAllocated returns if the passed task has its network resources allocated or not.
   330  func (na *cnmNetworkAllocator) IsTaskAllocated(t *api.Task) bool {
   331  	// If the task is not found in the allocated set, then it is
   332  	// not allocated.
   333  	if _, ok := na.tasks[t.ID]; !ok {
   334  		return false
   335  	}
   336  
   337  	// If Networks is empty there is no way this Task is allocated.
   338  	if len(t.Networks) == 0 {
   339  		return false
   340  	}
   341  
   342  	// To determine whether the task has its resources allocated,
   343  	// we just need to look at one global scope network (in case of
   344  	// multi-network attachment).  This is because we make sure we
   345  	// allocate for every network or we allocate for none.
   346  
   347  	// Find the first global scope network
   348  	for _, nAttach := range t.Networks {
   349  		// If the network is not allocated, the task cannot be allocated.
   350  		localNet, ok := na.networks[nAttach.Network.ID]
   351  		if !ok {
   352  			return false
   353  		}
   354  
   355  		// Nothing else to check for local scope network
   356  		if localNet.isNodeLocal {
   357  			continue
   358  		}
   359  
   360  		// Addresses empty. Task is not allocated.
   361  		if len(nAttach.Addresses) == 0 {
   362  			return false
   363  		}
   364  
   365  		// The allocated IP address not found in local endpoint state. Not allocated.
   366  		if _, ok := localNet.endpoints[nAttach.Addresses[0]]; !ok {
   367  			return false
   368  		}
   369  	}
   370  
   371  	return true
   372  }
   373  
   374  // HostPublishPortsNeedUpdate returns true if the passed service needs
   375  // allocations for its published ports in host (non ingress) mode
   376  func (na *cnmNetworkAllocator) HostPublishPortsNeedUpdate(s *api.Service) bool {
   377  	return na.portAllocator.hostPublishPortsNeedUpdate(s)
   378  }
   379  
   380  // IsServiceAllocated returns false if the passed service needs to have network resources allocated/updated.
   381  func (na *cnmNetworkAllocator) IsServiceAllocated(s *api.Service, flags ...func(*networkallocator.ServiceAllocationOpts)) bool {
   382  	var options networkallocator.ServiceAllocationOpts
   383  	for _, flag := range flags {
   384  		flag(&options)
   385  	}
   386  
   387  	specNetworks := serviceNetworks(s)
   388  
   389  	// If endpoint mode is VIP and allocator does not have the
   390  	// service in VIP allocated set then it needs to be allocated.
   391  	if len(specNetworks) != 0 &&
   392  		(s.Spec.Endpoint == nil ||
   393  			s.Spec.Endpoint.Mode == api.ResolutionModeVirtualIP) {
   394  
   395  		if _, ok := na.services[s.ID]; !ok {
   396  			return false
   397  		}
   398  
   399  		if s.Endpoint == nil || len(s.Endpoint.VirtualIPs) == 0 {
   400  			return false
   401  		}
   402  
   403  		// If the spec has networks which don't have a corresponding VIP,
   404  		// the service needs to be allocated.
   405  	networkLoop:
   406  		for _, net := range specNetworks {
   407  			for _, vip := range s.Endpoint.VirtualIPs {
   408  				if vip.NetworkID == net.Target {
   409  					continue networkLoop
   410  				}
   411  			}
   412  			return false
   413  		}
   414  	}
   415  
   416  	// If the spec no longer has networks attached and has a vip allocated
   417  	// from previous spec the service needs to allocated.
   418  	if s.Endpoint != nil {
   419  	vipLoop:
   420  		for _, vip := range s.Endpoint.VirtualIPs {
   421  			if na.IsVIPOnIngressNetwork(vip) && networkallocator.IsIngressNetworkNeeded(s) {
   422  				// This checks the condition when ingress network is needed
   423  				// but allocation has not been done.
   424  				if _, ok := na.services[s.ID]; !ok {
   425  					return false
   426  				}
   427  				continue vipLoop
   428  			}
   429  			for _, net := range specNetworks {
   430  				if vip.NetworkID == net.Target {
   431  					continue vipLoop
   432  				}
   433  			}
   434  			return false
   435  		}
   436  	}
   437  
   438  	// If the endpoint mode is DNSRR and allocator has the service
   439  	// in VIP allocated set then we return to be allocated to make
   440  	// sure the allocator triggers networkallocator to free up the
   441  	// resources if any.
   442  	if s.Spec.Endpoint != nil && s.Spec.Endpoint.Mode == api.ResolutionModeDNSRoundRobin {
   443  		if _, ok := na.services[s.ID]; ok {
   444  			return false
   445  		}
   446  	}
   447  
   448  	if (s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0) ||
   449  		(s.Endpoint != nil && len(s.Endpoint.Ports) != 0) {
   450  		return na.portAllocator.isPortsAllocatedOnInit(s, options.OnInit)
   451  	}
   452  	return true
   453  }
   454  
   455  // AllocateTask allocates all the endpoint resources for all the
   456  // networks that a task is attached to.
   457  func (na *cnmNetworkAllocator) AllocateTask(t *api.Task) error {
   458  	for i, nAttach := range t.Networks {
   459  		if localNet := na.getNetwork(nAttach.Network.ID); localNet != nil && localNet.isNodeLocal {
   460  			continue
   461  		}
   462  		if err := na.allocateNetworkIPs(nAttach); err != nil {
   463  			if err := na.releaseEndpoints(t.Networks[:i]); err != nil {
   464  				log.G(context.TODO()).WithError(err).Errorf("failed to release IP addresses while rolling back allocation for task %s network %s", t.ID, nAttach.Network.ID)
   465  			}
   466  			return errors.Wrapf(err, "failed to allocate network IP for task %s network %s", t.ID, nAttach.Network.ID)
   467  		}
   468  	}
   469  
   470  	na.tasks[t.ID] = struct{}{}
   471  
   472  	return nil
   473  }
   474  
   475  // DeallocateTask releases all the endpoint resources for all the
   476  // networks that a task is attached to.
   477  func (na *cnmNetworkAllocator) DeallocateTask(t *api.Task) error {
   478  	delete(na.tasks, t.ID)
   479  	return na.releaseEndpoints(t.Networks)
   480  }
   481  
   482  // IsAttachmentAllocated returns if the passed node and network has resources allocated or not.
   483  func (na *cnmNetworkAllocator) IsAttachmentAllocated(node *api.Node, networkAttachment *api.NetworkAttachment) bool {
   484  	if node == nil {
   485  		return false
   486  	}
   487  
   488  	if networkAttachment == nil || networkAttachment.Network == nil {
   489  		return false
   490  	}
   491  
   492  	// If the node is not found in the allocated set, then it is
   493  	// not allocated.
   494  	if _, ok := na.nodes[node.ID]; !ok {
   495  		return false
   496  	}
   497  
   498  	// If the nework is not found in the allocated set, then it is
   499  	// not allocated.
   500  	if _, ok := na.nodes[node.ID][networkAttachment.Network.ID]; !ok {
   501  		return false
   502  	}
   503  
   504  	// If the network is not allocated, the node cannot be allocated.
   505  	localNet, ok := na.networks[networkAttachment.Network.ID]
   506  	if !ok {
   507  		return false
   508  	}
   509  
   510  	// Addresses empty, not allocated.
   511  	if len(networkAttachment.Addresses) == 0 {
   512  		return false
   513  	}
   514  
   515  	// The allocated IP address not found in local endpoint state. Not allocated.
   516  	if _, ok := localNet.endpoints[networkAttachment.Addresses[0]]; !ok {
   517  		return false
   518  	}
   519  
   520  	return true
   521  }
   522  
   523  // AllocateAttachment allocates the IP addresses for a LB in a network
   524  // on a given node
   525  func (na *cnmNetworkAllocator) AllocateAttachment(node *api.Node, networkAttachment *api.NetworkAttachment) error {
   526  
   527  	if err := na.allocateNetworkIPs(networkAttachment); err != nil {
   528  		return err
   529  	}
   530  
   531  	if na.nodes[node.ID] == nil {
   532  		na.nodes[node.ID] = make(map[string]struct{})
   533  	}
   534  	na.nodes[node.ID][networkAttachment.Network.ID] = struct{}{}
   535  
   536  	return nil
   537  }
   538  
   539  // DeallocateAttachment deallocates the IP addresses for a LB in a network to
   540  // which the node is attached.
   541  func (na *cnmNetworkAllocator) DeallocateAttachment(node *api.Node, networkAttachment *api.NetworkAttachment) error {
   542  
   543  	delete(na.nodes[node.ID], networkAttachment.Network.ID)
   544  	if len(na.nodes[node.ID]) == 0 {
   545  		delete(na.nodes, node.ID)
   546  	}
   547  
   548  	return na.releaseEndpoints([]*api.NetworkAttachment{networkAttachment})
   549  }
   550  
   551  func (na *cnmNetworkAllocator) releaseEndpoints(networks []*api.NetworkAttachment) error {
   552  	for _, nAttach := range networks {
   553  		localNet := na.getNetwork(nAttach.Network.ID)
   554  		if localNet == nil {
   555  			return fmt.Errorf("could not find network allocator state for network %s", nAttach.Network.ID)
   556  		}
   557  
   558  		if localNet.isNodeLocal {
   559  			continue
   560  		}
   561  
   562  		ipam, _, _, err := na.resolveIPAM(nAttach.Network)
   563  		if err != nil {
   564  			return errors.Wrap(err, "failed to resolve IPAM while releasing")
   565  		}
   566  
   567  		// Do not fail and bail out if we fail to release IP
   568  		// address here. Keep going and try releasing as many
   569  		// addresses as possible.
   570  		for _, addr := range nAttach.Addresses {
   571  			// Retrieve the poolID and immediately nuke
   572  			// out the mapping.
   573  			poolID := localNet.endpoints[addr]
   574  			delete(localNet.endpoints, addr)
   575  
   576  			ip, _, err := net.ParseCIDR(addr)
   577  			if err != nil {
   578  				log.G(context.TODO()).Errorf("Could not parse IP address %s while releasing", addr)
   579  				continue
   580  			}
   581  
   582  			if err := ipam.ReleaseAddress(poolID, ip); err != nil {
   583  				log.G(context.TODO()).WithError(err).Errorf("IPAM failure while releasing IP address %s", addr)
   584  			}
   585  		}
   586  
   587  		// Clear out the address list when we are done with
   588  		// this network.
   589  		nAttach.Addresses = nil
   590  	}
   591  
   592  	return nil
   593  }
   594  
   595  // allocate virtual IP for a single endpoint attachment of the service.
   596  func (na *cnmNetworkAllocator) allocateVIP(vip *api.Endpoint_VirtualIP) error {
   597  	var opts map[string]string
   598  	localNet := na.getNetwork(vip.NetworkID)
   599  	if localNet == nil {
   600  		return errors.New("networkallocator: could not find local network state")
   601  	}
   602  
   603  	if localNet.isNodeLocal {
   604  		return nil
   605  	}
   606  
   607  	// If this IP is already allocated in memory we don't need to
   608  	// do anything.
   609  	if _, ok := localNet.endpoints[vip.Addr]; ok {
   610  		return nil
   611  	}
   612  
   613  	ipam, _, _, err := na.resolveIPAM(localNet.nw)
   614  	if err != nil {
   615  		return errors.Wrap(err, "failed to resolve IPAM while allocating")
   616  	}
   617  
   618  	var addr net.IP
   619  	if vip.Addr != "" {
   620  		var err error
   621  
   622  		addr, _, err = net.ParseCIDR(vip.Addr)
   623  		if err != nil {
   624  			return err
   625  		}
   626  	}
   627  	if localNet.nw.IPAM != nil && localNet.nw.IPAM.Driver != nil {
   628  		// set ipam allocation method to serial
   629  		opts = setIPAMSerialAlloc(localNet.nw.IPAM.Driver.Options)
   630  	}
   631  
   632  	for _, poolID := range localNet.pools {
   633  		ip, _, err := ipam.RequestAddress(poolID, addr, opts)
   634  		if err != nil && err != ipamapi.ErrNoAvailableIPs && err != ipamapi.ErrIPOutOfRange {
   635  			return errors.Wrap(err, "could not allocate VIP from IPAM")
   636  		}
   637  
   638  		// If we got an address then we are done.
   639  		if err == nil {
   640  			ipStr := ip.String()
   641  			localNet.endpoints[ipStr] = poolID
   642  			vip.Addr = ipStr
   643  			return nil
   644  		}
   645  	}
   646  
   647  	return errors.New("could not find an available IP while allocating VIP")
   648  }
   649  
   650  func (na *cnmNetworkAllocator) deallocateVIP(vip *api.Endpoint_VirtualIP) error {
   651  	localNet := na.getNetwork(vip.NetworkID)
   652  	if localNet == nil {
   653  		return errors.New("networkallocator: could not find local network state")
   654  	}
   655  	if localNet.isNodeLocal {
   656  		return nil
   657  	}
   658  	ipam, _, _, err := na.resolveIPAM(localNet.nw)
   659  	if err != nil {
   660  		return errors.Wrap(err, "failed to resolve IPAM while allocating")
   661  	}
   662  
   663  	// Retrieve the poolID and immediately nuke
   664  	// out the mapping.
   665  	poolID := localNet.endpoints[vip.Addr]
   666  	delete(localNet.endpoints, vip.Addr)
   667  
   668  	ip, _, err := net.ParseCIDR(vip.Addr)
   669  	if err != nil {
   670  		log.G(context.TODO()).Errorf("Could not parse VIP address %s while releasing", vip.Addr)
   671  		return err
   672  	}
   673  
   674  	if err := ipam.ReleaseAddress(poolID, ip); err != nil {
   675  		log.G(context.TODO()).WithError(err).Errorf("IPAM failure while releasing VIP address %s", vip.Addr)
   676  		return err
   677  	}
   678  
   679  	return nil
   680  }
   681  
   682  // allocate the IP addresses for a single network attachment of the task.
   683  func (na *cnmNetworkAllocator) allocateNetworkIPs(nAttach *api.NetworkAttachment) error {
   684  	var ip *net.IPNet
   685  	var opts map[string]string
   686  
   687  	ipam, _, _, err := na.resolveIPAM(nAttach.Network)
   688  	if err != nil {
   689  		return errors.Wrap(err, "failed to resolve IPAM while allocating")
   690  	}
   691  
   692  	localNet := na.getNetwork(nAttach.Network.ID)
   693  	if localNet == nil {
   694  		return fmt.Errorf("could not find network allocator state for network %s", nAttach.Network.ID)
   695  	}
   696  
   697  	addresses := nAttach.Addresses
   698  	if len(addresses) == 0 {
   699  		addresses = []string{""}
   700  	}
   701  
   702  	for i, rawAddr := range addresses {
   703  		var addr net.IP
   704  		if rawAddr != "" {
   705  			var err error
   706  			addr, _, err = net.ParseCIDR(rawAddr)
   707  			if err != nil {
   708  				addr = net.ParseIP(rawAddr)
   709  
   710  				if addr == nil {
   711  					return errors.Wrapf(err, "could not parse address string %s", rawAddr)
   712  				}
   713  			}
   714  		}
   715  		// Set the ipam options if the network has an ipam driver.
   716  		if localNet.nw.IPAM != nil && localNet.nw.IPAM.Driver != nil {
   717  			// set ipam allocation method to serial
   718  			opts = setIPAMSerialAlloc(localNet.nw.IPAM.Driver.Options)
   719  		}
   720  
   721  		for _, poolID := range localNet.pools {
   722  			var err error
   723  
   724  			ip, _, err = ipam.RequestAddress(poolID, addr, opts)
   725  			if err != nil && err != ipamapi.ErrNoAvailableIPs && err != ipamapi.ErrIPOutOfRange {
   726  				return errors.Wrap(err, "could not allocate IP from IPAM")
   727  			}
   728  
   729  			// If we got an address then we are done.
   730  			if err == nil {
   731  				ipStr := ip.String()
   732  				localNet.endpoints[ipStr] = poolID
   733  				addresses[i] = ipStr
   734  				nAttach.Addresses = addresses
   735  				return nil
   736  			}
   737  		}
   738  	}
   739  
   740  	return errors.New("could not find an available IP")
   741  }
   742  
   743  func (na *cnmNetworkAllocator) freeDriverState(n *api.Network) error {
   744  	d, err := na.resolveDriver(n)
   745  	if err != nil {
   746  		return err
   747  	}
   748  
   749  	return d.driver.NetworkFree(n.ID)
   750  }
   751  
   752  func (na *cnmNetworkAllocator) allocateDriverState(n *api.Network) error {
   753  	d, err := na.resolveDriver(n)
   754  	if err != nil {
   755  		return err
   756  	}
   757  
   758  	options := make(map[string]string)
   759  	// reconcile the driver specific options from the network spec
   760  	// and from the operational state retrieved from the store
   761  	if n.Spec.DriverConfig != nil {
   762  		for k, v := range n.Spec.DriverConfig.Options {
   763  			options[k] = v
   764  		}
   765  	}
   766  	if n.DriverState != nil {
   767  		for k, v := range n.DriverState.Options {
   768  			options[k] = v
   769  		}
   770  	}
   771  
   772  	// Construct IPAM data for driver consumption.
   773  	ipv4Data := make([]driverapi.IPAMData, 0, len(n.IPAM.Configs))
   774  	for _, ic := range n.IPAM.Configs {
   775  		if ic.Family == api.IPAMConfig_IPV6 {
   776  			continue
   777  		}
   778  
   779  		_, subnet, err := net.ParseCIDR(ic.Subnet)
   780  		if err != nil {
   781  			return errors.Wrapf(err, "error parsing subnet %s while allocating driver state", ic.Subnet)
   782  		}
   783  
   784  		gwIP := net.ParseIP(ic.Gateway)
   785  		gwNet := &net.IPNet{
   786  			IP:   gwIP,
   787  			Mask: subnet.Mask,
   788  		}
   789  
   790  		data := driverapi.IPAMData{
   791  			Pool:    subnet,
   792  			Gateway: gwNet,
   793  		}
   794  
   795  		ipv4Data = append(ipv4Data, data)
   796  	}
   797  
   798  	ds, err := d.driver.NetworkAllocate(n.ID, options, ipv4Data, nil)
   799  	if err != nil {
   800  		return err
   801  	}
   802  
   803  	// Update network object with the obtained driver state.
   804  	n.DriverState = &api.Driver{
   805  		Name:    d.name,
   806  		Options: ds,
   807  	}
   808  
   809  	return nil
   810  }
   811  
   812  // Resolve network driver
   813  func (na *cnmNetworkAllocator) resolveDriver(n *api.Network) (*networkDriver, error) {
   814  	dName := DefaultDriver
   815  	if n.Spec.DriverConfig != nil && n.Spec.DriverConfig.Name != "" {
   816  		dName = n.Spec.DriverConfig.Name
   817  	}
   818  
   819  	d, drvcap := na.drvRegistry.Driver(dName)
   820  	if d == nil {
   821  		err := na.loadDriver(dName)
   822  		if err != nil {
   823  			return nil, err
   824  		}
   825  
   826  		d, drvcap = na.drvRegistry.Driver(dName)
   827  		if d == nil {
   828  			return nil, fmt.Errorf("could not resolve network driver %s", dName)
   829  		}
   830  	}
   831  
   832  	return &networkDriver{driver: d, capability: drvcap, name: dName}, nil
   833  }
   834  
   835  func (na *cnmNetworkAllocator) loadDriver(name string) error {
   836  	pg := na.drvRegistry.GetPluginGetter()
   837  	if pg == nil {
   838  		return errors.New("plugin store is uninitialized")
   839  	}
   840  	_, err := pg.Get(name, driverapi.NetworkPluginEndpointType, plugingetter.Lookup)
   841  	return err
   842  }
   843  
   844  // Resolve the IPAM driver
   845  func (na *cnmNetworkAllocator) resolveIPAM(n *api.Network) (ipamapi.Ipam, string, map[string]string, error) {
   846  	dName := ipamapi.DefaultIPAM
   847  	if n.Spec.IPAM != nil && n.Spec.IPAM.Driver != nil && n.Spec.IPAM.Driver.Name != "" {
   848  		dName = n.Spec.IPAM.Driver.Name
   849  	}
   850  
   851  	var dOptions map[string]string
   852  	if n.Spec.IPAM != nil && n.Spec.IPAM.Driver != nil && len(n.Spec.IPAM.Driver.Options) != 0 {
   853  		dOptions = n.Spec.IPAM.Driver.Options
   854  	}
   855  
   856  	ipam, _ := na.drvRegistry.IPAM(dName)
   857  	if ipam == nil {
   858  		return nil, "", nil, fmt.Errorf("could not resolve IPAM driver %s", dName)
   859  	}
   860  
   861  	return ipam, dName, dOptions, nil
   862  }
   863  
   864  func (na *cnmNetworkAllocator) freePools(n *api.Network, pools map[string]string) error {
   865  	ipam, _, _, err := na.resolveIPAM(n)
   866  	if err != nil {
   867  		return errors.Wrapf(err, "failed to resolve IPAM while freeing pools for network %s", n.ID)
   868  	}
   869  
   870  	releasePools(ipam, n.IPAM.Configs, pools)
   871  	return nil
   872  }
   873  
   874  func releasePools(ipam ipamapi.Ipam, icList []*api.IPAMConfig, pools map[string]string) {
   875  	for _, ic := range icList {
   876  		if err := ipam.ReleaseAddress(pools[ic.Subnet], net.ParseIP(ic.Gateway)); err != nil {
   877  			log.G(context.TODO()).WithError(err).Errorf("Failed to release address %s", ic.Subnet)
   878  		}
   879  	}
   880  
   881  	for k, p := range pools {
   882  		if err := ipam.ReleasePool(p); err != nil {
   883  			log.G(context.TODO()).WithError(err).Errorf("Failed to release pool %s", k)
   884  		}
   885  	}
   886  }
   887  
   888  func (na *cnmNetworkAllocator) allocatePools(n *api.Network) (map[string]string, error) {
   889  	ipam, dName, dOptions, err := na.resolveIPAM(n)
   890  	if err != nil {
   891  		return nil, err
   892  	}
   893  
   894  	// We don't support user defined address spaces yet so just
   895  	// retrieve default address space names for the driver.
   896  	_, asName, err := na.drvRegistry.IPAMDefaultAddressSpaces(dName)
   897  	if err != nil {
   898  		return nil, err
   899  	}
   900  
   901  	pools := make(map[string]string)
   902  
   903  	var ipamConfigs []*api.IPAMConfig
   904  
   905  	// If there is non-nil IPAM state always prefer those subnet
   906  	// configs over Spec configs.
   907  	if n.IPAM != nil {
   908  		ipamConfigs = n.IPAM.Configs
   909  	} else if n.Spec.IPAM != nil {
   910  		ipamConfigs = make([]*api.IPAMConfig, len(n.Spec.IPAM.Configs))
   911  		copy(ipamConfigs, n.Spec.IPAM.Configs)
   912  	}
   913  
   914  	// Append an empty slot for subnet allocation if there are no
   915  	// IPAM configs from either spec or state.
   916  	if len(ipamConfigs) == 0 {
   917  		ipamConfigs = append(ipamConfigs, &api.IPAMConfig{Family: api.IPAMConfig_IPV4})
   918  	}
   919  
   920  	// Update the runtime IPAM configurations with initial state
   921  	n.IPAM = &api.IPAMOptions{
   922  		Driver:  &api.Driver{Name: dName, Options: dOptions},
   923  		Configs: ipamConfigs,
   924  	}
   925  
   926  	for i, ic := range ipamConfigs {
   927  		poolID, poolIP, meta, err := ipam.RequestPool(asName, ic.Subnet, ic.Range, dOptions, false)
   928  		if err != nil {
   929  			// Rollback by releasing all the resources allocated so far.
   930  			releasePools(ipam, ipamConfigs[:i], pools)
   931  			return nil, err
   932  		}
   933  		pools[poolIP.String()] = poolID
   934  
   935  		// The IPAM contract allows the IPAM driver to autonomously
   936  		// provide a network gateway in response to the pool request.
   937  		// But if the network spec contains a gateway, we will allocate
   938  		// it irrespective of whether the ipam driver returned one already.
   939  		// If none of the above is true, we need to allocate one now, and
   940  		// let the driver know this request is for the network gateway.
   941  		var (
   942  			gwIP *net.IPNet
   943  			ip   net.IP
   944  		)
   945  		if gws, ok := meta[netlabel.Gateway]; ok {
   946  			if ip, gwIP, err = net.ParseCIDR(gws); err != nil {
   947  				return nil, fmt.Errorf("failed to parse gateway address (%v) returned by ipam driver: %v", gws, err)
   948  			}
   949  			gwIP.IP = ip
   950  		}
   951  		if dOptions == nil {
   952  			dOptions = make(map[string]string)
   953  		}
   954  		dOptions[ipamapi.RequestAddressType] = netlabel.Gateway
   955  		// set ipam allocation method to serial
   956  		dOptions = setIPAMSerialAlloc(dOptions)
   957  		defer delete(dOptions, ipamapi.RequestAddressType)
   958  
   959  		if ic.Gateway != "" || gwIP == nil {
   960  			gwIP, _, err = ipam.RequestAddress(poolID, net.ParseIP(ic.Gateway), dOptions)
   961  			if err != nil {
   962  				// Rollback by releasing all the resources allocated so far.
   963  				releasePools(ipam, ipamConfigs[:i], pools)
   964  				return nil, err
   965  			}
   966  		}
   967  
   968  		if ic.Subnet == "" {
   969  			ic.Subnet = poolIP.String()
   970  		}
   971  
   972  		if ic.Gateway == "" {
   973  			ic.Gateway = gwIP.IP.String()
   974  		}
   975  
   976  	}
   977  
   978  	return pools, nil
   979  }
   980  
   981  func initializeDrivers(reg *drvregistry.DrvRegistry) error {
   982  	for _, i := range initializers {
   983  		if err := reg.AddDriver(i.ntype, i.fn, nil); err != nil {
   984  			return err
   985  		}
   986  	}
   987  	return nil
   988  }
   989  
   990  func serviceNetworks(s *api.Service) []*api.NetworkAttachmentConfig {
   991  	// Always prefer NetworkAttachmentConfig in the TaskSpec
   992  	if len(s.Spec.Task.Networks) == 0 && len(s.Spec.Networks) != 0 {
   993  		return s.Spec.Networks
   994  	}
   995  	return s.Spec.Task.Networks
   996  }
   997  
   998  // IsVIPOnIngressNetwork check if the vip is in ingress network
   999  func (na *cnmNetworkAllocator) IsVIPOnIngressNetwork(vip *api.Endpoint_VirtualIP) bool {
  1000  	if vip == nil {
  1001  		return false
  1002  	}
  1003  
  1004  	localNet := na.getNetwork(vip.NetworkID)
  1005  	if localNet != nil && localNet.nw != nil {
  1006  		return networkallocator.IsIngressNetwork(localNet.nw)
  1007  	}
  1008  	return false
  1009  }
  1010  
  1011  // IsBuiltInDriver returns whether the passed driver is an internal network driver
  1012  func IsBuiltInDriver(name string) bool {
  1013  	n := strings.ToLower(name)
  1014  	for _, d := range initializers {
  1015  		if n == d.ntype {
  1016  			return true
  1017  		}
  1018  	}
  1019  	return false
  1020  }
  1021  
  1022  // setIPAMSerialAlloc sets the ipam allocation method to serial
  1023  func setIPAMSerialAlloc(opts map[string]string) map[string]string {
  1024  	if opts == nil {
  1025  		opts = make(map[string]string)
  1026  	}
  1027  	if _, ok := opts[ipamapi.AllocSerialPrefix]; !ok {
  1028  		opts[ipamapi.AllocSerialPrefix] = "true"
  1029  	}
  1030  	return opts
  1031  }