Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / docker / libnetwork / ipams / remote / remote.go
1 package remote
2
3 import (
4         "fmt"
5         "net"
6
7         "github.com/Sirupsen/logrus"
8         "github.com/docker/docker/pkg/plugins"
9         "github.com/docker/libnetwork/discoverapi"
10         "github.com/docker/libnetwork/ipamapi"
11         "github.com/docker/libnetwork/ipams/remote/api"
12         "github.com/docker/libnetwork/types"
13 )
14
15 type allocator struct {
16         endpoint *plugins.Client
17         name     string
18 }
19
20 // PluginResponse is the interface for the plugin request responses
21 type PluginResponse interface {
22         IsSuccess() bool
23         GetError() string
24 }
25
26 func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {
27         a := &allocator{name: name, endpoint: client}
28         return a
29 }
30
31 // Init registers a remote ipam when its plugin is activated
32 func Init(cb ipamapi.Callback, l, g interface{}) error {
33
34         newPluginHandler := func(name string, client *plugins.Client) {
35                 a := newAllocator(name, client)
36                 if cps, err := a.(*allocator).getCapabilities(); err == nil {
37                         if err := cb.RegisterIpamDriverWithCapabilities(name, a, cps); err != nil {
38                                 logrus.Errorf("error registering remote ipam driver %s due to %v", name, err)
39                         }
40                 } else {
41                         logrus.Infof("remote ipam driver %s does not support capabilities", name)
42                         logrus.Debug(err)
43                         if err := cb.RegisterIpamDriver(name, a); err != nil {
44                                 logrus.Errorf("error registering remote ipam driver %s due to %v", name, err)
45                         }
46                 }
47         }
48
49         // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
50         handleFunc := plugins.Handle
51         if pg := cb.GetPluginGetter(); pg != nil {
52                 handleFunc = pg.Handle
53                 activePlugins := pg.GetAllManagedPluginsByCap(ipamapi.PluginEndpointType)
54                 for _, ap := range activePlugins {
55                         newPluginHandler(ap.Name(), ap.Client())
56                 }
57         }
58         handleFunc(ipamapi.PluginEndpointType, newPluginHandler)
59         return nil
60 }
61
62 func (a *allocator) call(methodName string, arg interface{}, retVal PluginResponse) error {
63         method := ipamapi.PluginEndpointType + "." + methodName
64         err := a.endpoint.Call(method, arg, retVal)
65         if err != nil {
66                 return err
67         }
68         if !retVal.IsSuccess() {
69                 return fmt.Errorf("remote: %s", retVal.GetError())
70         }
71         return nil
72 }
73
74 func (a *allocator) getCapabilities() (*ipamapi.Capability, error) {
75         var res api.GetCapabilityResponse
76         if err := a.call("GetCapabilities", nil, &res); err != nil {
77                 return nil, err
78         }
79         return res.ToCapability(), nil
80 }
81
82 // GetDefaultAddressSpaces returns the local and global default address spaces
83 func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
84         res := &api.GetAddressSpacesResponse{}
85         if err := a.call("GetDefaultAddressSpaces", nil, res); err != nil {
86                 return "", "", err
87         }
88         return res.LocalDefaultAddressSpace, res.GlobalDefaultAddressSpace, nil
89 }
90
91 // RequestPool requests an address pool in the specified address space
92 func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
93         req := &api.RequestPoolRequest{AddressSpace: addressSpace, Pool: pool, SubPool: subPool, Options: options, V6: v6}
94         res := &api.RequestPoolResponse{}
95         if err := a.call("RequestPool", req, res); err != nil {
96                 return "", nil, nil, err
97         }
98         retPool, err := types.ParseCIDR(res.Pool)
99         return res.PoolID, retPool, res.Data, err
100 }
101
102 // ReleasePool removes an address pool from the specified address space
103 func (a *allocator) ReleasePool(poolID string) error {
104         req := &api.ReleasePoolRequest{PoolID: poolID}
105         res := &api.ReleasePoolResponse{}
106         return a.call("ReleasePool", req, res)
107 }
108
109 // RequestAddress requests an address from the address pool
110 func (a *allocator) RequestAddress(poolID string, address net.IP, options map[string]string) (*net.IPNet, map[string]string, error) {
111         var (
112                 prefAddress string
113                 retAddress  *net.IPNet
114                 err         error
115         )
116         if address != nil {
117                 prefAddress = address.String()
118         }
119         req := &api.RequestAddressRequest{PoolID: poolID, Address: prefAddress, Options: options}
120         res := &api.RequestAddressResponse{}
121         if err := a.call("RequestAddress", req, res); err != nil {
122                 return nil, nil, err
123         }
124         if res.Address != "" {
125                 retAddress, err = types.ParseCIDR(res.Address)
126         } else {
127                 return nil, nil, ipamapi.ErrNoIPReturned
128         }
129         return retAddress, res.Data, err
130 }
131
132 // ReleaseAddress releases the address from the specified address pool
133 func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
134         var relAddress string
135         if address != nil {
136                 relAddress = address.String()
137         }
138         req := &api.ReleaseAddressRequest{PoolID: poolID, Address: relAddress}
139         res := &api.ReleaseAddressResponse{}
140         return a.call("ReleaseAddress", req, res)
141 }
142
143 // DiscoverNew is a notification for a new discovery event, such as a new global datastore
144 func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
145         return nil
146 }
147
148 // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
149 func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
150         return nil
151 }
152
153 func (a *allocator) IsBuiltIn() bool {
154         return false
155 }