Browse Source

Providing KVObject option to skip persisting object in kvstore

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 9 years ago
parent
commit
725280d03f

+ 5 - 0
libnetwork/bitseq/store.go

@@ -70,6 +70,11 @@ func (h *Handle) Exists() bool {
 	return h.dbExists
 }
 
+// Skip provides a way for a KV Object to avoid persisting it in the KV Store
+func (h *Handle) Skip() bool {
+	return false
+}
+
 // DataScope method returns the storage scope of the datastore
 func (h *Handle) DataScope() datastore.DataScope {
 	return datastore.GlobalScope

+ 1 - 0
libnetwork/controller.go

@@ -248,6 +248,7 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti
 		id:          stringid.GenerateRandomID(),
 		ctrlr:       c,
 		endpoints:   endpointTable{},
+		persist:     true,
 	}
 
 	network.processOptions(options...)

+ 2 - 0
libnetwork/datastore/datastore.go

@@ -61,6 +61,8 @@ type KV interface {
 	Exists() bool
 	// DataScope indicates the storage scope of the KV object
 	DataScope() DataScope
+	// Skip provides a way for a KV Object to avoid persisting it in the KV Store
+	Skip() bool
 }
 
 // DataScope indicates the storage scope

+ 14 - 3
libnetwork/datastore/datastore_test.go

@@ -122,6 +122,7 @@ type dummyObject struct {
 	ID          string
 	DBIndex     uint64
 	DBExists    bool
+	SkipSave    bool
 	ReturnValue bool
 }
 
@@ -162,6 +163,10 @@ func (n *dummyObject) Exists() bool {
 	return n.DBExists
 }
 
+func (n *dummyObject) Skip() bool {
+	return n.SkipSave
+}
+
 func (n *dummyObject) DataScope() DataScope {
 	return LocalScope
 }
@@ -194,6 +199,7 @@ type recStruct struct {
 	Dict     map[string]string `kv:"iterative"`
 	DBIndex  uint64
 	DBExists bool
+	SkipSave bool
 }
 
 func (r *recStruct) Key() []string {
@@ -224,6 +230,10 @@ func (r *recStruct) Exists() bool {
 	return r.DBExists
 }
 
+func (r *recStruct) Skip() bool {
+	return r.SkipSave
+}
+
 func dummyKVObject(id string, retValue bool) *dummyObject {
 	cDict := make(map[string]string)
 	cDict["foo"] = "bar"
@@ -232,13 +242,14 @@ func dummyKVObject(id string, retValue bool) *dummyObject {
 		Name:        "testNw",
 		NetworkType: "bridge",
 		EnableIPv6:  true,
-		Rec:         &recStruct{"gen", 5, cDict, 0, false},
+		Rec:         &recStruct{"gen", 5, cDict, 0, false, false},
 		ID:          id,
 		DBIndex:     0,
 		ReturnValue: retValue,
-		DBExists:    false}
+		DBExists:    false,
+		SkipSave:    false}
 	generic := make(map[string]interface{})
-	generic["label1"] = &recStruct{"value1", 1, cDict, 0, false}
+	generic["label1"] = &recStruct{"value1", 1, cDict, 0, false, false}
 	generic["label2"] = "subnet=10.1.1.0/16"
 	n.Generic = generic
 	return &n

+ 4 - 0
libnetwork/drivers/overlay/ov_network.go

@@ -297,6 +297,10 @@ func (n *network) Exists() bool {
 	return n.dbExists
 }
 
+func (n *network) Skip() bool {
+	return false
+}
+
 func (n *network) SetValue(value []byte) error {
 	var vni uint32
 	err := json.Unmarshal(value, &vni)

+ 4 - 0
libnetwork/endpoint.go

@@ -173,6 +173,10 @@ func (ep *endpoint) Exists() bool {
 	return ep.dbExists
 }
 
+func (ep *endpoint) Skip() bool {
+	return ep.getNetwork().Skip()
+}
+
 func (ep *endpoint) processOptions(options ...EndpointOption) {
 	ep.Lock()
 	defer ep.Unlock()

+ 5 - 0
libnetwork/ipam/store.go

@@ -111,6 +111,11 @@ func (a *Allocator) Exists() bool {
 	return a.dbExists
 }
 
+// Skip provides a way for a KV Object to avoid persisting it in the KV Store
+func (a *Allocator) Skip() bool {
+	return false
+}
+
 func (a *Allocator) watchForChanges() error {
 	if a.store == nil {
 		return nil

+ 18 - 0
libnetwork/network.go

@@ -68,6 +68,7 @@ type network struct {
 	dbIndex     uint64
 	svcRecords  svcMap
 	dbExists    bool
+	persist     bool
 	stopWatchCh chan struct{}
 	dataScope   datastore.DataScope
 	sync.Mutex
@@ -141,6 +142,12 @@ func (n *network) Exists() bool {
 	return n.dbExists
 }
 
+func (n *network) Skip() bool {
+	n.Lock()
+	defer n.Unlock()
+	return !n.persist
+}
+
 func (n *network) DataScope() datastore.DataScope {
 	n.Lock()
 	defer n.Unlock()
@@ -174,6 +181,7 @@ func (n *network) MarshalJSON() ([]byte, error) {
 	netMap["endpointCnt"] = n.endpointCnt
 	netMap["enableIPv6"] = n.enableIPv6
 	netMap["generic"] = n.generic
+	netMap["persist"] = n.persist
 	return json.Marshal(netMap)
 }
 
@@ -191,6 +199,9 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
 	if netMap["generic"] != nil {
 		n.generic = netMap["generic"].(map[string]interface{})
 	}
+	if netMap["persist"] != nil {
+		n.persist = netMap["persist"].(bool)
+	}
 	return nil
 }
 
@@ -210,6 +221,13 @@ func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption {
 	}
 }
 
+// NetworkOptionPersist returns an option setter to set persistence policy for a network
+func NetworkOptionPersist(persist bool) NetworkOption {
+	return func(n *network) {
+		n.persist = persist
+	}
+}
+
 func (n *network) processOptions(options ...NetworkOption) {
 	for _, opt := range options {
 		if opt != nil {

+ 7 - 1
libnetwork/store.go

@@ -110,6 +110,9 @@ func (c *controller) newEndpointFromStore(key string, ep *endpoint) error {
 }
 
 func (c *controller) updateToStore(kvObject datastore.KV) error {
+	if kvObject.Skip() {
+		return nil
+	}
 	cs := c.getDataStore(kvObject.DataScope())
 	if cs == nil {
 		log.Debugf("datastore not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
@@ -120,6 +123,9 @@ func (c *controller) updateToStore(kvObject datastore.KV) error {
 }
 
 func (c *controller) deleteFromStore(kvObject datastore.KV) error {
+	if kvObject.Skip() {
+		return nil
+	}
 	cs := c.getDataStore(kvObject.DataScope())
 	if cs == nil {
 		log.Debugf("datastore not initialized. kv object %s is not deleted from datastore", datastore.Key(kvObject.Key()...))
@@ -188,7 +194,7 @@ func (c *controller) watchNetworks() error {
 }
 
 func (n *network) watchEndpoints() error {
-	if !n.ctrlr.validateGlobalStoreConfig() {
+	if n.Skip() || !n.ctrlr.validateGlobalStoreConfig() {
 		return nil
 	}
 

+ 27 - 0
libnetwork/store_test.go

@@ -79,6 +79,33 @@ func testLocalBackend(t *testing.T, provider, url string, storeConfig *store.Con
 	}
 }
 
+func TestNoPersist(t *testing.T) {
+	cfgOptions, err := OptionBoltdbWithRandomDBFile()
+	if err != nil {
+		t.Fatalf("Error creating random boltdb file : %v", err)
+	}
+	ctrl, err := New(cfgOptions...)
+	if err != nil {
+		t.Fatalf("Error new controller: %v", err)
+	}
+	nw, err := ctrl.NewNetwork("host", "host", NetworkOptionPersist(false))
+	if err != nil {
+		t.Fatalf("Error creating default \"host\" network: %v", err)
+	}
+	ep, err := nw.CreateEndpoint("newendpoint", []EndpointOption{}...)
+	if err != nil {
+		t.Fatalf("Error creating endpoint: %v", err)
+	}
+	store := ctrl.(*controller).localStore.KVStore()
+	if exists, _ := store.Exists(datastore.Key(datastore.NetworkKeyPrefix, string(nw.ID()))); exists {
+		t.Fatalf("Network with persist=false should not be stored in KV Store")
+	}
+	if exists, _ := store.Exists(datastore.Key([]string{datastore.EndpointKeyPrefix, string(nw.ID()), string(ep.ID())}...)); exists {
+		t.Fatalf("Endpoint in Network with persist=false should not be stored in KV Store")
+	}
+	store.Close()
+}
+
 // OptionBoltdbWithRandomDBFile function returns a random dir for local store backend
 func OptionBoltdbWithRandomDBFile() ([]config.Option, error) {
 	tmp, err := ioutil.TempFile("", "libnetwork-")