github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/ipams/remote/remote.go (about) 1 package remote 2 3 import ( 4 "fmt" 5 "net" 6 7 log "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 // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins. 35 handleFunc := plugins.Handle 36 if pg := cb.GetPluginGetter(); pg != nil { 37 handleFunc = pg.Handle 38 } 39 handleFunc(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) { 40 a := newAllocator(name, client) 41 if cps, err := a.(*allocator).getCapabilities(); err == nil { 42 if err := cb.RegisterIpamDriverWithCapabilities(name, a, cps); err != nil { 43 log.Errorf("error registering remote ipam driver %s due to %v", name, err) 44 } 45 } else { 46 log.Infof("remote ipam driver %s does not support capabilities", name) 47 log.Debug(err) 48 if err := cb.RegisterIpamDriver(name, a); err != nil { 49 log.Errorf("error registering remote ipam driver %s due to %v", name, err) 50 } 51 } 52 }) 53 return nil 54 } 55 56 func (a *allocator) call(methodName string, arg interface{}, retVal PluginResponse) error { 57 method := ipamapi.PluginEndpointType + "." + methodName 58 err := a.endpoint.Call(method, arg, retVal) 59 if err != nil { 60 return err 61 } 62 if !retVal.IsSuccess() { 63 return fmt.Errorf("remote: %s", retVal.GetError()) 64 } 65 return nil 66 } 67 68 func (a *allocator) getCapabilities() (*ipamapi.Capability, error) { 69 var res api.GetCapabilityResponse 70 if err := a.call("GetCapabilities", nil, &res); err != nil { 71 return nil, err 72 } 73 return res.ToCapability(), nil 74 } 75 76 // GetDefaultAddressSpaces returns the local and global default address spaces 77 func (a *allocator) GetDefaultAddressSpaces() (string, string, error) { 78 res := &api.GetAddressSpacesResponse{} 79 if err := a.call("GetDefaultAddressSpaces", nil, res); err != nil { 80 return "", "", err 81 } 82 return res.LocalDefaultAddressSpace, res.GlobalDefaultAddressSpace, nil 83 } 84 85 // RequestPool requests an address pool in the specified address space 86 func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) { 87 req := &api.RequestPoolRequest{AddressSpace: addressSpace, Pool: pool, SubPool: subPool, Options: options, V6: v6} 88 res := &api.RequestPoolResponse{} 89 if err := a.call("RequestPool", req, res); err != nil { 90 return "", nil, nil, err 91 } 92 retPool, err := types.ParseCIDR(res.Pool) 93 return res.PoolID, retPool, res.Data, err 94 } 95 96 // ReleasePool removes an address pool from the specified address space 97 func (a *allocator) ReleasePool(poolID string) error { 98 req := &api.ReleasePoolRequest{PoolID: poolID} 99 res := &api.ReleasePoolResponse{} 100 return a.call("ReleasePool", req, res) 101 } 102 103 // RequestAddress requests an address from the address pool 104 func (a *allocator) RequestAddress(poolID string, address net.IP, options map[string]string) (*net.IPNet, map[string]string, error) { 105 var ( 106 prefAddress string 107 retAddress *net.IPNet 108 err error 109 ) 110 if address != nil { 111 prefAddress = address.String() 112 } 113 req := &api.RequestAddressRequest{PoolID: poolID, Address: prefAddress, Options: options} 114 res := &api.RequestAddressResponse{} 115 if err := a.call("RequestAddress", req, res); err != nil { 116 return nil, nil, err 117 } 118 if res.Address != "" { 119 retAddress, err = types.ParseCIDR(res.Address) 120 } else { 121 return nil, nil, ipamapi.ErrNoIPReturned 122 } 123 return retAddress, res.Data, err 124 } 125 126 // ReleaseAddress releases the address from the specified address pool 127 func (a *allocator) ReleaseAddress(poolID string, address net.IP) error { 128 var relAddress string 129 if address != nil { 130 relAddress = address.String() 131 } 132 req := &api.ReleaseAddressRequest{PoolID: poolID, Address: relAddress} 133 res := &api.ReleaseAddressResponse{} 134 return a.call("ReleaseAddress", req, res) 135 } 136 137 // DiscoverNew is a notification for a new discovery event, such as a new global datastore 138 func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { 139 return nil 140 } 141 142 // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster 143 func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { 144 return nil 145 }