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  }