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