1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/libnetwork/ipam/store.go
Alessandro Boch dc4285b9a4 Adjust ipam errors
- Remove from contract predefined errors which are no longer
  valid (ex. ErrInvalidIpamService, ErrInvalidIpamConfigService)

- Do not use network driver error for ipam load failure in controller.go

- Bitseq to expose two well-known errors (no more bit available, bit is already set)

- Default ipam to report proper well-known error on RequestAddress()
  based on bitseq returned error

- Default ipam errors to comply with types error interface

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-12-02 13:38:04 -08:00

130 lines
3.2 KiB
Go

package ipam
import (
"encoding/json"
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/datastore"
"github.com/docker/libnetwork/types"
)
// Key provides the Key to be used in KV Store
func (aSpace *addrSpace) Key() []string {
aSpace.Lock()
defer aSpace.Unlock()
return []string{aSpace.id}
}
// KeyPrefix returns the immediate parent key that can be used for tree walk
func (aSpace *addrSpace) KeyPrefix() []string {
aSpace.Lock()
defer aSpace.Unlock()
return []string{dsConfigKey}
}
// Value marshals the data to be stored in the KV store
func (aSpace *addrSpace) Value() []byte {
b, err := json.Marshal(aSpace)
if err != nil {
log.Warnf("Failed to marshal ipam configured pools: %v", err)
return nil
}
return b
}
// SetValue unmarshalls the data from the KV store.
func (aSpace *addrSpace) SetValue(value []byte) error {
rc := &addrSpace{subnets: make(map[SubnetKey]*PoolData)}
if err := json.Unmarshal(value, rc); err != nil {
return err
}
aSpace.subnets = rc.subnets
return nil
}
// Index returns the latest DB Index as seen by this object
func (aSpace *addrSpace) Index() uint64 {
aSpace.Lock()
defer aSpace.Unlock()
return aSpace.dbIndex
}
// SetIndex method allows the datastore to store the latest DB Index into this object
func (aSpace *addrSpace) SetIndex(index uint64) {
aSpace.Lock()
aSpace.dbIndex = index
aSpace.dbExists = true
aSpace.Unlock()
}
// Exists method is true if this object has been stored in the DB.
func (aSpace *addrSpace) Exists() bool {
aSpace.Lock()
defer aSpace.Unlock()
return aSpace.dbExists
}
// Skip provides a way for a KV Object to avoid persisting it in the KV Store
func (aSpace *addrSpace) Skip() bool {
return false
}
func (a *Allocator) getStore(as string) datastore.DataStore {
a.Lock()
defer a.Unlock()
if aSpace, ok := a.addrSpaces[as]; ok {
return aSpace.ds
}
return nil
}
func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
store := a.getStore(as)
if store == nil {
return nil, types.InternalErrorf("store for address space %s not found", as)
}
pc := &addrSpace{id: dsConfigKey + "/" + as, ds: store, alloc: a}
if err := store.GetObject(datastore.Key(pc.Key()...), pc); err != nil {
if err == datastore.ErrKeyNotFound {
return nil, nil
}
return nil, types.InternalErrorf("could not get pools config from store: %v", err)
}
return pc, nil
}
func (a *Allocator) writeToStore(aSpace *addrSpace) error {
store := aSpace.store()
if store == nil {
return types.InternalErrorf("invalid store while trying to write %s address space", aSpace.DataScope())
}
err := store.PutObjectAtomic(aSpace)
if err == datastore.ErrKeyModified {
return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err)
}
return err
}
func (a *Allocator) deleteFromStore(aSpace *addrSpace) error {
store := aSpace.store()
if store == nil {
return types.InternalErrorf("invalid store while trying to delete %s address space", aSpace.DataScope())
}
return store.DeleteObjectAtomic(aSpace)
}
// DataScope method returns the storage scope of the datastore
func (aSpace *addrSpace) DataScope() string {
aSpace.Lock()
defer aSpace.Unlock()
return aSpace.scope
}