1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #687 from aboch/id

Adjust ipam errors
This commit is contained in:
Madhu Venugopal 2015-12-02 14:52:28 -08:00
commit 15a70d92dc
7 changed files with 60 additions and 55 deletions

View file

@ -24,7 +24,10 @@ const (
) )
var ( var (
errNoBitAvailable = fmt.Errorf("no bit available") // ErrNoBitAvailable is returned when no more bits are available to set
ErrNoBitAvailable = fmt.Errorf("no bit available")
// ErrBitAllocated is returned when the specific bit requested is already set
ErrBitAllocated = fmt.Errorf("requested bit is already allocated")
) )
// Handle contains the sequece representing the bitmask and its identifier // Handle contains the sequece representing the bitmask and its identifier
@ -94,7 +97,7 @@ func (s *sequence) toString() string {
// GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence
func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) { func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) {
if s.block == blockMAX || s.count == 0 { if s.block == blockMAX || s.count == 0 {
return invalidPos, invalidPos, errNoBitAvailable return invalidPos, invalidPos, ErrNoBitAvailable
} }
bits := from bits := from
bitSel := blockFirstBit >> from bitSel := blockFirstBit >> from
@ -197,7 +200,7 @@ func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) {
return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end) return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end)
} }
if h.Unselected() == 0 { if h.Unselected() == 0 {
return invalidPos, errNoBitAvailable return invalidPos, ErrNoBitAvailable
} }
return h.set(0, start, end, true, false) return h.set(0, start, end, true, false)
} }
@ -205,7 +208,7 @@ func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) {
// SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal // SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal
func (h *Handle) SetAny() (uint64, error) { func (h *Handle) SetAny() (uint64, error) {
if h.Unselected() == 0 { if h.Unselected() == 0 {
return invalidPos, errNoBitAvailable return invalidPos, ErrNoBitAvailable
} }
return h.set(0, 0, h.bits-1, true, false) return h.set(0, 0, h.bits-1, true, false)
} }
@ -269,7 +272,7 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64
bytePos, bitPos, err = getFirstAvailable(h.head, start) bytePos, bitPos, err = getFirstAvailable(h.head, start)
ret = posToOrdinal(bytePos, bitPos) ret = posToOrdinal(bytePos, bitPos)
if end < ret { if end < ret {
err = errNoBitAvailable err = ErrNoBitAvailable
} }
} else { } else {
bytePos, bitPos, err = checkIfAvailable(h.head, ordinal) bytePos, bitPos, err = checkIfAvailable(h.head, ordinal)
@ -449,7 +452,7 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {
byteOffset += current.count * blockBytes byteOffset += current.count * blockBytes
current = current.next current = current.next
} }
return invalidPos, invalidPos, errNoBitAvailable return invalidPos, invalidPos, ErrNoBitAvailable
} }
// checkIfAvailable checks if the bit correspondent to the specified ordinal is unset // checkIfAvailable checks if the bit correspondent to the specified ordinal is unset
@ -467,7 +470,7 @@ func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) {
} }
} }
return invalidPos, invalidPos, fmt.Errorf("requested bit is not available") return invalidPos, invalidPos, ErrBitAllocated
} }
// Given the byte position and the sequences list head, return the pointer to the // Given the byte position and the sequences list head, return the pointer to the

View file

@ -657,7 +657,7 @@ func TestSetInRange(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected failure. Got success with ordinal:%d", o) t.Fatalf("Expected failure. Got success with ordinal:%d", o)
} }
if err != errNoBitAvailable { if err != ErrNoBitAvailable {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -673,7 +673,7 @@ func TestSetInRange(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected failure. Got success with ordinal:%d", o) t.Fatalf("Expected failure. Got success with ordinal:%d", o)
} }
if err != errNoBitAvailable { if err != ErrNoBitAvailable {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
@ -687,7 +687,7 @@ func TestSetInRange(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected failure. Got success with ordinal:%d", o) t.Fatalf("Expected failure. Got success with ordinal:%d", o)
} }
if err != errNoBitAvailable { if err != ErrNoBitAvailable {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
} }

View file

@ -315,17 +315,17 @@ func (c *controller) RegisterIpamDriver(name string, driver ipamapi.Ipam) error
_, ok := c.ipamDrivers[name] _, ok := c.ipamDrivers[name]
c.Unlock() c.Unlock()
if ok { if ok {
return driverapi.ErrActiveRegistration(name) return types.ForbiddenErrorf("ipam driver %q already registered", name)
} }
locAS, glbAS, err := driver.GetDefaultAddressSpaces() locAS, glbAS, err := driver.GetDefaultAddressSpaces()
if err != nil { if err != nil {
return fmt.Errorf("ipam driver %s failed to return default address spaces: %v", name, err) return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err)
} }
c.Lock() c.Lock()
c.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS} c.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS}
c.Unlock() c.Unlock()
log.Debugf("Registering ipam provider: %s", name) log.Debugf("Registering ipam driver: %q", name)
return nil return nil
} }
@ -667,7 +667,7 @@ func (c *controller) loadIpamDriver(name string) (*ipamData, error) {
id, ok := c.ipamDrivers[name] id, ok := c.ipamDrivers[name]
c.Unlock() c.Unlock()
if !ok { if !ok {
return nil, ErrInvalidNetworkDriver(name) return nil, types.BadRequestErrorf("invalid ipam driver: %q", name)
} }
return id, nil return id, nil
} }

View file

@ -76,8 +76,7 @@ func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
func (a *Allocator) refresh(as string) error { func (a *Allocator) refresh(as string) error {
aSpace, err := a.getAddressSpaceFromStore(as) aSpace, err := a.getAddressSpaceFromStore(as)
if err != nil { if err != nil {
return fmt.Errorf("error getting pools config from store during init: %v", return types.InternalErrorf("error getting pools config from store: %v", err)
err)
} }
if aSpace == nil { if aSpace == nil {
@ -239,7 +238,7 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
store := a.getStore(key.AddressSpace) store := a.getStore(key.AddressSpace)
if store == nil { if store == nil {
return fmt.Errorf("could not find store for address space %s while inserting bit mask", key.AddressSpace) return types.InternalErrorf("could not find store for address space %s while inserting bit mask", key.AddressSpace)
} }
ipVer := getAddressVersion(pool.IP) ipVer := getAddressVersion(pool.IP)
@ -279,7 +278,7 @@ func (a *Allocator) retrieveBitmask(k SubnetKey, n *net.IPNet) (*bitseq.Handle,
if !ok { if !ok {
log.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String()) log.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String())
if err := a.insertBitMask(k, n); err != nil { if err := a.insertBitMask(k, n); err != nil {
return nil, fmt.Errorf("could not find bitmask in datastore for %s", k.String()) return nil, types.InternalErrorf("could not find bitmask in datastore for %s", k.String())
} }
a.Lock() a.Lock()
bm = a.addresses[k] bm = a.addresses[k]
@ -306,7 +305,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
} }
if as != localAddressSpace && as != globalAddressSpace { if as != localAddressSpace && as != globalAddressSpace {
return nil, fmt.Errorf("no default pool available for non-default address spaces") return nil, types.NotImplementedErrorf("no default pool availbale for non-default addresss spaces")
} }
aSpace, err := a.getAddrSpace(as) aSpace, err := a.getAddrSpace(as)
@ -378,7 +377,7 @@ func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s
bm, err := a.retrieveBitmask(k, c.Pool) bm, err := a.retrieveBitmask(k, c.Pool)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v", return nil, nil, types.InternalErrorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v",
k.String(), prefAddress, poolID, err) k.String(), prefAddress, poolID, err)
} }
ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range) ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range)
@ -410,12 +409,12 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
p, ok := aSpace.subnets[k] p, ok := aSpace.subnets[k]
if !ok { if !ok {
aSpace.Unlock() aSpace.Unlock()
return ipamapi.ErrBadPool return types.NotFoundErrorf("cannot find address pool for poolID:%s", poolID)
} }
if address == nil { if address == nil {
aSpace.Unlock() aSpace.Unlock()
return ipamapi.ErrInvalidRequest return types.BadRequestErrorf("invalid address: nil")
} }
if !p.Pool.Contains(address) { if !p.Pool.Contains(address) {
@ -434,12 +433,12 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
h, err := types.GetHostPartIP(address, mask) h, err := types.GetHostPartIP(address, mask)
if err != nil { if err != nil {
return fmt.Errorf("failed to release address %s: %v", address.String(), err) return types.InternalErrorf("failed to release address %s: %v", address.String(), err)
} }
bm, err := a.retrieveBitmask(k, c.Pool) bm, err := a.retrieveBitmask(k, c.Pool)
if err != nil { if err != nil {
return fmt.Errorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v", return types.InternalErrorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v",
k.String(), address, poolID, err) k.String(), address, poolID, err)
} }
@ -463,19 +462,25 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres
} else if prefAddress != nil { } else if prefAddress != nil {
hostPart, e := types.GetHostPartIP(prefAddress, base.Mask) hostPart, e := types.GetHostPartIP(prefAddress, base.Mask)
if e != nil { if e != nil {
return nil, fmt.Errorf("failed to allocate preferred address %s: %v", prefAddress.String(), e) return nil, types.InternalErrorf("failed to allocate preferred address %s: %v", prefAddress.String(), e)
} }
ordinal = ipToUint64(types.GetMinimalIP(hostPart)) ordinal = ipToUint64(types.GetMinimalIP(hostPart))
err = bitmask.Set(ordinal) err = bitmask.Set(ordinal)
} else { } else {
ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End) ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End)
} }
if err != nil {
return nil, ipamapi.ErrNoAvailableIPs
}
switch err {
case nil:
// Convert IP ordinal for this subnet into IP address // Convert IP ordinal for this subnet into IP address
return generateAddress(ordinal, base), nil return generateAddress(ordinal, base), nil
case bitseq.ErrBitAllocated:
return nil, ipamapi.ErrIPAlreadyAllocated
case bitseq.ErrNoBitAvailable:
return nil, ipamapi.ErrNoAvailableIPs
default:
return nil, err
}
} }
// DumpDatabase dumps the internal info // DumpDatabase dumps the internal info

View file

@ -2,7 +2,6 @@ package ipam
import ( import (
"encoding/json" "encoding/json"
"fmt"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/datastore"
@ -84,7 +83,7 @@ func (a *Allocator) getStore(as string) datastore.DataStore {
func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) { func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
store := a.getStore(as) store := a.getStore(as)
if store == nil { if store == nil {
return nil, fmt.Errorf("store for address space %s not found", as) return nil, types.InternalErrorf("store for address space %s not found", as)
} }
pc := &addrSpace{id: dsConfigKey + "/" + as, ds: store, alloc: a} pc := &addrSpace{id: dsConfigKey + "/" + as, ds: store, alloc: a}
@ -93,7 +92,7 @@ func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
return nil, nil return nil, nil
} }
return nil, fmt.Errorf("could not get pools config from store: %v", err) return nil, types.InternalErrorf("could not get pools config from store: %v", err)
} }
return pc, nil return pc, nil
@ -102,7 +101,7 @@ func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
func (a *Allocator) writeToStore(aSpace *addrSpace) error { func (a *Allocator) writeToStore(aSpace *addrSpace) error {
store := aSpace.store() store := aSpace.store()
if store == nil { if store == nil {
return fmt.Errorf("invalid store while trying to write %s address space", aSpace.DataScope()) return types.InternalErrorf("invalid store while trying to write %s address space", aSpace.DataScope())
} }
err := store.PutObjectAtomic(aSpace) err := store.PutObjectAtomic(aSpace)
@ -116,7 +115,7 @@ func (a *Allocator) writeToStore(aSpace *addrSpace) error {
func (a *Allocator) deleteFromStore(aSpace *addrSpace) error { func (a *Allocator) deleteFromStore(aSpace *addrSpace) error {
store := aSpace.store() store := aSpace.store()
if store == nil { if store == nil {
return fmt.Errorf("invalid store while trying to delete %s address space", aSpace.DataScope()) return types.InternalErrorf("invalid store while trying to delete %s address space", aSpace.DataScope())
} }
return store.DeleteObjectAtomic(aSpace) return store.DeleteObjectAtomic(aSpace)

View file

@ -88,12 +88,12 @@ func (s *SubnetKey) String() string {
// FromString populate the SubnetKey object reading it from string // FromString populate the SubnetKey object reading it from string
func (s *SubnetKey) FromString(str string) error { func (s *SubnetKey) FromString(str string) error {
if str == "" || !strings.Contains(str, "/") { if str == "" || !strings.Contains(str, "/") {
return fmt.Errorf("invalid string form for subnetkey: %s", str) return types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
} }
p := strings.Split(str, "/") p := strings.Split(str, "/")
if len(p) != 3 && len(p) != 5 { if len(p) != 3 && len(p) != 5 {
return fmt.Errorf("invalid string form for subnetkey: %s", str) return types.BadRequestErrorf("invalid string form for subnetkey: %s", str)
} }
s.AddressSpace = p[0] s.AddressSpace = p[0]
s.Subnet = fmt.Sprintf("%s/%s", p[1], p[2]) s.Subnet = fmt.Sprintf("%s/%s", p[1], p[2])
@ -317,7 +317,7 @@ func (aSpace *addrSpace) updatePoolDBOnRemoval(k SubnetKey) (func() error, error
return func() error { return func() error {
bm, err := aSpace.alloc.retrieveBitmask(k, c.Pool) bm, err := aSpace.alloc.retrieveBitmask(k, c.Pool)
if err != nil { if err != nil {
return fmt.Errorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err) return types.InternalErrorf("could not find bitmask in datastore for pool %s removal: %v", k.String(), err)
} }
return bm.Destroy() return bm.Destroy()
}, nil }, nil

View file

@ -2,8 +2,9 @@
package ipamapi package ipamapi
import ( import (
"errors"
"net" "net"
"github.com/docker/libnetwork/types"
) )
/******************** /********************
@ -29,22 +30,19 @@ type Callback interface {
// Weel-known errors returned by IPAM // Weel-known errors returned by IPAM
var ( var (
ErrInvalidIpamService = errors.New("Invalid IPAM Service") ErrIpamInternalError = types.InternalErrorf("IPAM Internal Error")
ErrInvalidIpamConfigService = errors.New("Invalid IPAM Config Service") ErrInvalidAddressSpace = types.BadRequestErrorf("Invalid Address Space")
ErrIpamNotAvailable = errors.New("IPAM Service not available") ErrInvalidPool = types.BadRequestErrorf("Invalid Address Pool")
ErrIpamInternalError = errors.New("IPAM Internal Error") ErrInvalidSubPool = types.BadRequestErrorf("Invalid Address SubPool")
ErrInvalidAddressSpace = errors.New("Invalid Address Space") ErrInvalidRequest = types.BadRequestErrorf("Invalid Request")
ErrInvalidPool = errors.New("Invalid Address Pool") ErrPoolNotFound = types.BadRequestErrorf("Address Pool not found")
ErrInvalidSubPool = errors.New("Invalid Address SubPool") ErrOverlapPool = types.ForbiddenErrorf("Address pool overlaps with existing pool on this address space")
ErrInvalidRequest = errors.New("Invalid Request") ErrNoAvailablePool = types.NoServiceErrorf("No available pool")
ErrPoolNotFound = errors.New("Address Pool not found") ErrNoAvailableIPs = types.NoServiceErrorf("No available addresses on this pool")
ErrOverlapPool = errors.New("Address pool overlaps with existing pool on this address space") ErrIPAlreadyAllocated = types.ForbiddenErrorf("Address already in use")
ErrNoAvailablePool = errors.New("No available pool") ErrIPOutOfRange = types.BadRequestErrorf("Requested address is out of range")
ErrNoAvailableIPs = errors.New("No available addresses on this pool") ErrPoolOverlap = types.ForbiddenErrorf("Pool overlaps with other one on this address space")
ErrIPAlreadyAllocated = errors.New("Address already in use") ErrBadPool = types.BadRequestErrorf("Address space does not contain specified address pool")
ErrIPOutOfRange = errors.New("Requested address is out of range")
ErrPoolOverlap = errors.New("Pool overlaps with other one on this address space")
ErrBadPool = errors.New("Address space does not contain specified address pool")
) )
/******************************* /*******************************