| package drvregistry |
| |
| import ( |
| "fmt" |
| "strings" |
| "sync" |
| |
| "github.com/docker/libnetwork/driverapi" |
| "github.com/docker/libnetwork/ipamapi" |
| "github.com/docker/libnetwork/types" |
| ) |
| |
| type driverData struct { |
| driver driverapi.Driver |
| capability driverapi.Capability |
| } |
| |
| type ipamData struct { |
| driver ipamapi.Ipam |
| capability *ipamapi.Capability |
| // default address spaces are provided by ipam driver at registration time |
| defaultLocalAddressSpace, defaultGlobalAddressSpace string |
| } |
| |
| type driverTable map[string]*driverData |
| type ipamTable map[string]*ipamData |
| |
| // DrvRegistry holds the registry of all network drivers and IPAM drivers that it knows about. |
| type DrvRegistry struct { |
| sync.Mutex |
| drivers driverTable |
| ipamDrivers ipamTable |
| dfn DriverNotifyFunc |
| ifn IPAMNotifyFunc |
| } |
| |
| // Functors definition |
| |
| // InitFunc defines the driver initialization function signature. |
| type InitFunc func(driverapi.DriverCallback, map[string]interface{}) error |
| |
| // IPAMWalkFunc defines the IPAM driver table walker function signature. |
| type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool |
| |
| // DriverWalkFunc defines the network driver table walker function signature. |
| type DriverWalkFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) bool |
| |
| // IPAMNotifyFunc defines the notify function signature when a new IPAM driver gets registered. |
| type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) error |
| |
| // DriverNotifyFunc defines the notify function signature when a new network driver gets registered. |
| type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error |
| |
| // New retruns a new driver registry handle. |
| func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc) (*DrvRegistry, error) { |
| r := &DrvRegistry{ |
| drivers: make(driverTable), |
| ipamDrivers: make(ipamTable), |
| dfn: dfn, |
| ifn: ifn, |
| } |
| |
| return r, nil |
| } |
| |
| // AddDriver adds a network driver to the registry. |
| func (r *DrvRegistry) AddDriver(ntype string, fn InitFunc, config map[string]interface{}) error { |
| return fn(r, config) |
| } |
| |
| // WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them. |
| func (r *DrvRegistry) WalkIPAMs(ifn IPAMWalkFunc) { |
| type ipamVal struct { |
| name string |
| data *ipamData |
| } |
| |
| r.Lock() |
| ivl := make([]ipamVal, 0, len(r.ipamDrivers)) |
| for k, v := range r.ipamDrivers { |
| ivl = append(ivl, ipamVal{name: k, data: v}) |
| } |
| r.Unlock() |
| |
| for _, iv := range ivl { |
| if ifn(iv.name, iv.data.driver, iv.data.capability) { |
| break |
| } |
| } |
| } |
| |
| // WalkDrivers walks the network drivers registered in the registry and invokes the passed walk function and each one of them. |
| func (r *DrvRegistry) WalkDrivers(dfn DriverWalkFunc) { |
| type driverVal struct { |
| name string |
| data *driverData |
| } |
| |
| r.Lock() |
| dvl := make([]driverVal, 0, len(r.drivers)) |
| for k, v := range r.drivers { |
| dvl = append(dvl, driverVal{name: k, data: v}) |
| } |
| r.Unlock() |
| |
| for _, dv := range dvl { |
| if dfn(dv.name, dv.data.driver, dv.data.capability) { |
| break |
| } |
| } |
| } |
| |
| // Driver returns the actual network driver instance and its capability which registered with the passed name. |
| func (r *DrvRegistry) Driver(name string) (driverapi.Driver, *driverapi.Capability) { |
| r.Lock() |
| defer r.Unlock() |
| |
| d, ok := r.drivers[name] |
| if !ok { |
| return nil, nil |
| } |
| |
| return d.driver, &d.capability |
| } |
| |
| // IPAM returns the actual IPAM driver instance and its capability which registered with the passed name. |
| func (r *DrvRegistry) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) { |
| r.Lock() |
| defer r.Unlock() |
| |
| i, ok := r.ipamDrivers[name] |
| if !ok { |
| return nil, nil |
| } |
| |
| return i.driver, i.capability |
| } |
| |
| // IPAMDefaultAddressSpaces returns the default address space strings for the passed IPAM driver name. |
| func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, error) { |
| r.Lock() |
| defer r.Unlock() |
| |
| i, ok := r.ipamDrivers[name] |
| if !ok { |
| return "", "", fmt.Errorf("ipam %s not found", name) |
| } |
| |
| return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil |
| } |
| |
| // RegisterDriver registers the network driver when it gets discovered. |
| func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error { |
| if strings.TrimSpace(ntype) == "" { |
| return fmt.Errorf("network type string cannot be empty") |
| } |
| |
| r.Lock() |
| _, ok := r.drivers[ntype] |
| r.Unlock() |
| |
| if ok { |
| return driverapi.ErrActiveRegistration(ntype) |
| } |
| |
| if r.dfn != nil { |
| if err := r.dfn(ntype, driver, capability); err != nil { |
| return err |
| } |
| } |
| |
| dData := &driverData{driver, capability} |
| |
| r.Lock() |
| r.drivers[ntype] = dData |
| r.Unlock() |
| |
| return nil |
| } |
| |
| func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { |
| if strings.TrimSpace(name) == "" { |
| return fmt.Errorf("ipam driver name string cannot be empty") |
| } |
| |
| r.Lock() |
| _, ok := r.ipamDrivers[name] |
| r.Unlock() |
| if ok { |
| return types.ForbiddenErrorf("ipam driver %q already registered", name) |
| } |
| |
| locAS, glbAS, err := driver.GetDefaultAddressSpaces() |
| if err != nil { |
| return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err) |
| } |
| |
| if r.ifn != nil { |
| if err := r.ifn(name, driver, caps); err != nil { |
| return err |
| } |
| } |
| |
| r.Lock() |
| r.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps} |
| r.Unlock() |
| |
| return nil |
| } |
| |
| // RegisterIpamDriver registers the IPAM driver discovered with default capabilities. |
| func (r *DrvRegistry) RegisterIpamDriver(name string, driver ipamapi.Ipam) error { |
| return r.registerIpamDriver(name, driver, &ipamapi.Capability{}) |
| } |
| |
| // RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities. |
| func (r *DrvRegistry) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { |
| return r.registerIpamDriver(name, driver, caps) |
| } |