2015-06-16 14:46:51 -07:00
|
|
|
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 (a *Allocator) Key() []string {
|
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
2015-09-22 13:20:55 -07:00
|
|
|
return []string{dsConfigKey}
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// KeyPrefix returns the immediate parent key that can be used for tree walk
|
|
|
|
func (a *Allocator) KeyPrefix() []string {
|
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
2015-09-22 13:20:55 -07:00
|
|
|
return []string{dsConfigKey}
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Value marshals the data to be stored in the KV store
|
|
|
|
func (a *Allocator) Value() []byte {
|
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
|
|
|
|
|
|
|
if a.subnets == nil {
|
|
|
|
return []byte{}
|
|
|
|
}
|
2015-09-22 13:20:55 -07:00
|
|
|
m := map[string]interface{}{}
|
|
|
|
for k, v := range a.subnets {
|
|
|
|
m[k.String()] = v
|
|
|
|
}
|
2015-06-16 14:46:51 -07:00
|
|
|
|
2015-09-22 13:20:55 -07:00
|
|
|
b, err := json.Marshal(m)
|
2015-06-16 14:46:51 -07:00
|
|
|
if err != nil {
|
2015-09-22 13:20:55 -07:00
|
|
|
log.Warnf("Failed to marshal ipam configured subnets")
|
2015-06-16 14:46:51 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2015-06-18 15:13:38 -07:00
|
|
|
// SetValue unmarshalls the data from the KV store.
|
|
|
|
func (a *Allocator) SetValue(value []byte) error {
|
2015-09-22 13:20:55 -07:00
|
|
|
var m map[string]*PoolData
|
|
|
|
err := json.Unmarshal(value, &m)
|
2015-06-16 14:46:51 -07:00
|
|
|
if err != nil {
|
2015-09-22 13:20:55 -07:00
|
|
|
return err
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
2015-09-22 13:20:55 -07:00
|
|
|
for ks, d := range m {
|
|
|
|
k := SubnetKey{}
|
|
|
|
if err := k.FromString(ks); err != nil {
|
|
|
|
return err
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
2015-09-22 13:20:55 -07:00
|
|
|
a.subnets[k] = d
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
2015-09-22 13:20:55 -07:00
|
|
|
return nil
|
2015-06-16 14:46:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Index returns the latest DB Index as seen by this object
|
|
|
|
func (a *Allocator) Index() uint64 {
|
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
|
|
|
return a.dbIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetIndex method allows the datastore to store the latest DB Index into this object
|
|
|
|
func (a *Allocator) SetIndex(index uint64) {
|
|
|
|
a.Lock()
|
|
|
|
a.dbIndex = index
|
2015-06-18 15:13:38 -07:00
|
|
|
a.dbExists = true
|
2015-06-16 14:46:51 -07:00
|
|
|
a.Unlock()
|
|
|
|
}
|
|
|
|
|
2015-06-18 15:13:38 -07:00
|
|
|
// Exists method is true if this object has been stored in the DB.
|
|
|
|
func (a *Allocator) Exists() bool {
|
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
|
|
|
return a.dbExists
|
|
|
|
}
|
|
|
|
|
2015-09-22 07:09:39 -07:00
|
|
|
// Skip provides a way for a KV Object to avoid persisting it in the KV Store
|
|
|
|
func (a *Allocator) Skip() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-06-16 14:46:51 -07:00
|
|
|
func (a *Allocator) watchForChanges() error {
|
|
|
|
if a.store == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
kvpChan, err := a.store.KVStore().Watch(datastore.Key(a.Key()...), nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case kvPair := <-kvpChan:
|
|
|
|
if kvPair != nil {
|
|
|
|
a.subnetConfigFromStore(kvPair)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Allocator) readFromStore() error {
|
|
|
|
a.Lock()
|
|
|
|
store := a.store
|
|
|
|
a.Unlock()
|
|
|
|
|
|
|
|
if store == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
kvPair, err := a.store.KVStore().Get(datastore.Key(a.Key()...))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
a.subnetConfigFromStore(kvPair)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *Allocator) writeToStore() error {
|
|
|
|
a.Lock()
|
|
|
|
store := a.store
|
|
|
|
a.Unlock()
|
|
|
|
if store == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
err := store.PutObjectAtomic(a)
|
|
|
|
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() error {
|
|
|
|
a.Lock()
|
|
|
|
store := a.store
|
|
|
|
a.Unlock()
|
|
|
|
if store == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return store.DeleteObjectAtomic(a)
|
|
|
|
}
|
2015-09-16 19:39:46 +08:00
|
|
|
|
|
|
|
// DataScope method returns the storage scope of the datastore
|
|
|
|
func (a *Allocator) DataScope() datastore.DataScope {
|
|
|
|
return datastore.GlobalScope
|
|
|
|
}
|