moby--moby/libnetwork/store.go

158 lines
3.5 KiB
Go
Raw Normal View History

package libnetwork
import (
"encoding/json"
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/datastore"
)
func (c *controller) initDataStore() error {
if c.cfg == nil {
return fmt.Errorf("datastore initialization requires a valid configuration")
}
store, err := datastore.NewDataStore(&c.cfg.Datastore)
if err != nil {
return err
}
c.Lock()
c.store = store
c.Unlock()
return c.watchStore()
}
func (c *controller) newNetworkFromStore(n *network) {
c.Lock()
n.ctrlr = c
c.Unlock()
n.endpoints = endpointTable{}
c.addNetwork(n)
}
func (c *controller) addNetworkToStore(n *network) error {
if isReservedNetwork(n.Name()) {
return nil
}
c.Lock()
cs := c.store
c.Unlock()
if cs == nil {
log.Debugf("datastore not initialized. Network %s is not added to the store", n.Name())
return nil
}
// Commenting out AtomicPut due to https://github.com/docker/swarm/issues/875,
// Also Network object is Keyed with UUID & hence an Atomic put is not mandatory.
// return cs.PutObjectAtomic(n)
return cs.PutObject(n)
}
func (c *controller) newEndpointFromStore(ep *endpoint) {
c.Lock()
defer c.Unlock()
n, ok := c.networks[ep.network.id]
if !ok {
log.Warnf("Network (%s) unavailable for endpoint=%s. ignoring endpoint update", ep.network.id, ep.name)
// TODO : Get Network from Store and call newNetworkFromStore
return
}
ep.network = n
_, err := n.EndpointByID(string(ep.id))
if _, ok := err.(ErrNoSuchEndpoint); ok {
n.addEndpoint(ep)
}
}
func (c *controller) addEndpointToStore(ep *endpoint) error {
if isReservedNetwork(ep.network.name) {
return nil
}
c.Lock()
cs := c.store
c.Unlock()
if cs == nil {
log.Debugf("datastore not initialized. endpoint %s is not added to the store", ep.name)
return nil
}
// Commenting out AtomicPut due to https://github.com/docker/swarm/issues/875,
// Also Network object is Keyed with UUID & hence an Atomic put is not mandatory.
// return cs.PutObjectAtomic(ep)
return cs.PutObject(ep)
}
func (c *controller) watchStore() error {
c.Lock()
cs := c.store
c.Unlock()
nwPairs, err := cs.KVStore().WatchTree(datastore.Key(datastore.NetworkKeyPrefix), c.stopChan)
if err != nil {
return err
}
epPairs, err := cs.KVStore().WatchTree(datastore.Key(datastore.EndpointKeyPrefix), c.stopChan)
if err != nil {
return err
}
go func() {
for {
select {
case nws := <-nwPairs:
for _, kve := range nws {
var n network
err := json.Unmarshal(kve.Value, &n)
if err != nil {
log.Error(err)
continue
}
n.dbIndex = kve.LastIndex
c.Lock()
existing, ok := c.networks[n.id]
c.Unlock()
if ok {
// Skip existing network update
if existing.dbIndex != n.dbIndex {
log.Debugf("Skipping network update for %s (%s)", n.name, n.id)
}
continue
}
c.newNetworkFromStore(&n)
}
case eps := <-epPairs:
for _, epe := range eps {
var ep endpoint
err := json.Unmarshal(epe.Value, &ep)
if err != nil {
log.Error(err)
continue
}
ep.dbIndex = epe.LastIndex
c.Lock()
n, ok := c.networks[ep.network.id]
c.Unlock()
if ok {
existing, _ := n.EndpointByID(string(ep.id))
if existing != nil {
// Skip existing endpoint update
if existing.(*endpoint).dbIndex != ep.dbIndex {
log.Debugf("Skipping endpoint update for %s (%s)", ep.name, ep.id)
}
continue
}
}
c.newEndpointFromStore(&ep)
}
}
}
}()
return nil
}