diff --git a/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/client.go b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/client.go
new file mode 100644
index 0000000..c0ebe5f
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/client.go
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kvstore
+
+import (
+	"github.com/opencord/voltha-lib-go/v2/pkg/log"
+)
+
+const (
+	// Default timeout in seconds when making a kvstore request
+	defaultKVGetTimeout = 5
+	// Maximum channel buffer between publisher/subscriber goroutines
+	maxClientChannelBufferSize = 10
+)
+
+// These constants represent the event types returned by the KV client
+const (
+	PUT = iota
+	DELETE
+	CONNECTIONDOWN
+	UNKNOWN
+)
+
+// KVPair is a common wrapper for key-value pairs returned from the KV store
+type KVPair struct {
+	Key     string
+	Value   interface{}
+	Version int64
+	Session string
+	Lease   int64
+}
+
+func init() {
+	log.AddPackage(log.JSON, log.WarnLevel, nil)
+}
+
+// NewKVPair creates a new KVPair object
+func NewKVPair(key string, value interface{}, session string, lease int64, version int64) *KVPair {
+	kv := new(KVPair)
+	kv.Key = key
+	kv.Value = value
+	kv.Session = session
+	kv.Lease = lease
+	kv.Version = version
+	return kv
+}
+
+// Event is generated by the KV client when a key change is detected
+type Event struct {
+	EventType int
+	Key       interface{}
+	Value     interface{}
+	Version   int64
+}
+
+// NewEvent creates a new Event object
+func NewEvent(eventType int, key interface{}, value interface{}, version int64) *Event {
+	evnt := new(Event)
+	evnt.EventType = eventType
+	evnt.Key = key
+	evnt.Value = value
+	evnt.Version = version
+
+	return evnt
+}
+
+// Client represents the set of APIs a KV Client must implement
+type Client interface {
+	List(key string, timeout int, lock ...bool) (map[string]*KVPair, error)
+	Get(key string, timeout int, lock ...bool) (*KVPair, error)
+	Put(key string, value interface{}, timeout int, lock ...bool) error
+	Delete(key string, timeout int, lock ...bool) error
+	Reserve(key string, value interface{}, ttl int64) (interface{}, error)
+	ReleaseReservation(key string) error
+	ReleaseAllReservations() error
+	RenewReservation(key string) error
+	Watch(key string) chan *Event
+	AcquireLock(lockName string, timeout int) error
+	ReleaseLock(lockName string) error
+	IsConnectionUp(timeout int) bool // timeout in second
+	CloseWatch(key string, ch chan *Event)
+	Close()
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/consulclient.go b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/consulclient.go
new file mode 100644
index 0000000..e0e8550
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/consulclient.go
@@ -0,0 +1,513 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kvstore
+
+import (
+	"bytes"
+	"context"
+	"errors"
+	log "github.com/opencord/voltha-lib-go/v2/pkg/log"
+	"sync"
+	"time"
+	//log "ciena.com/coordinator/common"
+	consulapi "github.com/hashicorp/consul/api"
+)
+
+type channelContextMap struct {
+	ctx     context.Context
+	channel chan *Event
+	cancel  context.CancelFunc
+}
+
+// ConsulClient represents the consul KV store client
+type ConsulClient struct {
+	session                *consulapi.Session
+	sessionID              string
+	consul                 *consulapi.Client
+	doneCh                 *chan int
+	keyReservations        map[string]interface{}
+	watchedChannelsContext map[string][]*channelContextMap
+	writeLock              sync.Mutex
+}
+
+// NewConsulClient returns a new client for the Consul KV store
+func NewConsulClient(addr string, timeout int) (*ConsulClient, error) {
+
+	duration := GetDuration(timeout)
+
+	config := consulapi.DefaultConfig()
+	config.Address = addr
+	config.WaitTime = duration
+	consul, err := consulapi.NewClient(config)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	doneCh := make(chan int, 1)
+	wChannelsContext := make(map[string][]*channelContextMap)
+	reservations := make(map[string]interface{})
+	return &ConsulClient{consul: consul, doneCh: &doneCh, watchedChannelsContext: wChannelsContext, keyReservations: reservations}, nil
+}
+
+// IsConnectionUp returns whether the connection to the Consul KV store is up
+func (c *ConsulClient) IsConnectionUp(timeout int) bool {
+	log.Error("Unimplemented function")
+	return false
+}
+
+// List returns an array of key-value pairs with key as a prefix.  Timeout defines how long the function will
+// wait for a response
+func (c *ConsulClient) List(key string, timeout int, lock ...bool) (map[string]*KVPair, error) {
+	duration := GetDuration(timeout)
+
+	kv := c.consul.KV()
+	var queryOptions consulapi.QueryOptions
+	queryOptions.WaitTime = duration
+	// For now we ignore meta data
+	kvps, _, err := kv.List(key, &queryOptions)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	m := make(map[string]*KVPair)
+	for _, kvp := range kvps {
+		m[string(kvp.Key)] = NewKVPair(string(kvp.Key), kvp.Value, string(kvp.Session), 0, -1)
+	}
+	return m, nil
+}
+
+// Get returns a key-value pair for a given key. Timeout defines how long the function will
+// wait for a response
+func (c *ConsulClient) Get(key string, timeout int, lock ...bool) (*KVPair, error) {
+
+	duration := GetDuration(timeout)
+
+	kv := c.consul.KV()
+	var queryOptions consulapi.QueryOptions
+	queryOptions.WaitTime = duration
+	// For now we ignore meta data
+	kvp, _, err := kv.Get(key, &queryOptions)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if kvp != nil {
+		return NewKVPair(string(kvp.Key), kvp.Value, string(kvp.Session), 0, -1), nil
+	}
+
+	return nil, nil
+}
+
+// Put writes a key-value pair to the KV store.  Value can only be a string or []byte since the consul API
+// accepts only a []byte as a value for a put operation. Timeout defines how long the function will
+// wait for a response
+func (c *ConsulClient) Put(key string, value interface{}, timeout int, lock ...bool) error {
+
+	// Validate that we can create a byte array from the value as consul API expects a byte array
+	var val []byte
+	var er error
+	if val, er = ToByte(value); er != nil {
+		log.Error(er)
+		return er
+	}
+
+	// Create a key value pair
+	kvp := consulapi.KVPair{Key: key, Value: val}
+	kv := c.consul.KV()
+	var writeOptions consulapi.WriteOptions
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	_, err := kv.Put(&kvp, &writeOptions)
+	if err != nil {
+		log.Error(err)
+		return err
+	}
+	return nil
+}
+
+// Delete removes a key from the KV store. Timeout defines how long the function will
+// wait for a response
+func (c *ConsulClient) Delete(key string, timeout int, lock ...bool) error {
+	kv := c.consul.KV()
+	var writeOptions consulapi.WriteOptions
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	_, err := kv.Delete(key, &writeOptions)
+	if err != nil {
+		log.Error(err)
+		return err
+	}
+	return nil
+}
+
+func (c *ConsulClient) deleteSession() {
+	if c.sessionID != "" {
+		log.Debug("cleaning-up-session")
+		session := c.consul.Session()
+		_, err := session.Destroy(c.sessionID, nil)
+		if err != nil {
+			log.Errorw("error-cleaning-session", log.Fields{"session": c.sessionID, "error": err})
+		}
+	}
+	c.sessionID = ""
+	c.session = nil
+}
+
+func (c *ConsulClient) createSession(ttl int64, retries int) (*consulapi.Session, string, error) {
+	session := c.consul.Session()
+	entry := &consulapi.SessionEntry{
+		Behavior: consulapi.SessionBehaviorDelete,
+		TTL:      "10s", // strconv.FormatInt(ttl, 10) + "s", // disable ttl
+	}
+
+	for {
+		id, meta, err := session.Create(entry, nil)
+		if err != nil {
+			log.Errorw("create-session-error", log.Fields{"error": err})
+			if retries == 0 {
+				return nil, "", err
+			}
+		} else if meta.RequestTime == 0 {
+			log.Errorw("create-session-bad-meta-data", log.Fields{"meta-data": meta})
+			if retries == 0 {
+				return nil, "", errors.New("bad-meta-data")
+			}
+		} else if id == "" {
+			log.Error("create-session-nil-id")
+			if retries == 0 {
+				return nil, "", errors.New("ID-nil")
+			}
+		} else {
+			return session, id, nil
+		}
+		// If retry param is -1 we will retry indefinitely
+		if retries > 0 {
+			retries--
+		}
+		log.Debug("retrying-session-create-after-a-second-delay")
+		time.Sleep(time.Duration(1) * time.Second)
+	}
+}
+
+// Helper function to verify mostly whether the content of two interface types are the same.  Focus is []byte and
+// string types
+func isEqual(val1 interface{}, val2 interface{}) bool {
+	b1, err := ToByte(val1)
+	b2, er := ToByte(val2)
+	if err == nil && er == nil {
+		return bytes.Equal(b1, b2)
+	}
+	return val1 == val2
+}
+
+// Reserve is invoked to acquire a key and set it to a given value. Value can only be a string or []byte since
+// the consul API accepts only a []byte.  Timeout defines how long the function will wait for a response.  TTL
+// defines how long that reservation is valid.  When TTL expires the key is unreserved by the KV store itself.
+// If the key is acquired then the value returned will be the value passed in.  If the key is already acquired
+// then the value assigned to that key will be returned.
+func (c *ConsulClient) Reserve(key string, value interface{}, ttl int64) (interface{}, error) {
+
+	// Validate that we can create a byte array from the value as consul API expects a byte array
+	var val []byte
+	var er error
+	if val, er = ToByte(value); er != nil {
+		log.Error(er)
+		return nil, er
+	}
+
+	// Cleanup any existing session and recreate new ones.  A key is reserved against a session
+	if c.sessionID != "" {
+		c.deleteSession()
+	}
+
+	// Clear session if reservation is not successful
+	reservationSuccessful := false
+	defer func() {
+		if !reservationSuccessful {
+			log.Debug("deleting-session")
+			c.deleteSession()
+		}
+	}()
+
+	session, sessionID, err := c.createSession(ttl, -1)
+	if err != nil {
+		log.Errorw("no-session-created", log.Fields{"error": err})
+		return "", errors.New("no-session-created")
+	}
+	log.Debugw("session-created", log.Fields{"session-id": sessionID})
+	c.sessionID = sessionID
+	c.session = session
+
+	// Try to grap the Key using the session
+	kv := c.consul.KV()
+	kvp := consulapi.KVPair{Key: key, Value: val, Session: c.sessionID}
+	result, _, err := kv.Acquire(&kvp, nil)
+	if err != nil {
+		log.Errorw("error-acquiring-keys", log.Fields{"error": err})
+		return nil, err
+	}
+
+	log.Debugw("key-acquired", log.Fields{"key": key, "status": result})
+
+	// Irrespective whether we were successful in acquiring the key, let's read it back and see if it's us.
+	m, err := c.Get(key, defaultKVGetTimeout)
+	if err != nil {
+		return nil, err
+	}
+	if m != nil {
+		log.Debugw("response-received", log.Fields{"key": m.Key, "m.value": string(m.Value.([]byte)), "value": value})
+		if m.Key == key && isEqual(m.Value, value) {
+			// My reservation is successful - register it.  For now, support is only for 1 reservation per key
+			// per session.
+			reservationSuccessful = true
+			c.writeLock.Lock()
+			c.keyReservations[key] = m.Value
+			c.writeLock.Unlock()
+			return m.Value, nil
+		}
+		// My reservation has failed.  Return the owner of that key
+		return m.Value, nil
+	}
+	return nil, nil
+}
+
+// ReleaseAllReservations releases all key reservations previously made (using Reserve API)
+func (c *ConsulClient) ReleaseAllReservations() error {
+	kv := c.consul.KV()
+	var kvp consulapi.KVPair
+	var result bool
+	var err error
+
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+
+	for key, value := range c.keyReservations {
+		kvp = consulapi.KVPair{Key: key, Value: value.([]byte), Session: c.sessionID}
+		result, _, err = kv.Release(&kvp, nil)
+		if err != nil {
+			log.Errorw("cannot-release-reservation", log.Fields{"key": key, "error": err})
+			return err
+		}
+		if !result {
+			log.Errorw("cannot-release-reservation", log.Fields{"key": key})
+		}
+		delete(c.keyReservations, key)
+	}
+	return nil
+}
+
+// ReleaseReservation releases reservation for a specific key.
+func (c *ConsulClient) ReleaseReservation(key string) error {
+	var ok bool
+	var reservedValue interface{}
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if reservedValue, ok = c.keyReservations[key]; !ok {
+		return errors.New("key-not-reserved:" + key)
+	}
+	// Release the reservation
+	kv := c.consul.KV()
+	kvp := consulapi.KVPair{Key: key, Value: reservedValue.([]byte), Session: c.sessionID}
+
+	result, _, er := kv.Release(&kvp, nil)
+	if er != nil {
+		return er
+	}
+	// Remove that key entry on success
+	if result {
+		delete(c.keyReservations, key)
+		return nil
+	}
+	return errors.New("key-cannot-be-unreserved")
+}
+
+// RenewReservation renews a reservation.  A reservation will go stale after the specified TTL (Time To Live)
+// period specified when reserving the key
+func (c *ConsulClient) RenewReservation(key string) error {
+	// In the case of Consul, renew reservation of a reserve key only require renewing the client session.
+
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+
+	// Verify the key was reserved
+	if _, ok := c.keyReservations[key]; !ok {
+		return errors.New("key-not-reserved")
+	}
+
+	if c.session == nil {
+		return errors.New("no-session-exist")
+	}
+
+	var writeOptions consulapi.WriteOptions
+	if _, _, err := c.session.Renew(c.sessionID, &writeOptions); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Watch provides the watch capability on a given key.  It returns a channel onto which the callee needs to
+// listen to receive Events.
+func (c *ConsulClient) Watch(key string) chan *Event {
+
+	// Create a new channel
+	ch := make(chan *Event, maxClientChannelBufferSize)
+
+	// Create a context to track this request
+	watchContext, cFunc := context.WithCancel(context.Background())
+
+	// Save the channel and context reference for later
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	ccm := channelContextMap{channel: ch, ctx: watchContext, cancel: cFunc}
+	c.watchedChannelsContext[key] = append(c.watchedChannelsContext[key], &ccm)
+
+	// Launch a go routine to listen for updates
+	go c.listenForKeyChange(watchContext, key, ch)
+
+	return ch
+}
+
+// CloseWatch closes a specific watch. Both the key and the channel are required when closing a watch as there
+// may be multiple listeners on the same key.  The previously created channel serves as a key
+func (c *ConsulClient) CloseWatch(key string, ch chan *Event) {
+	// First close the context
+	var ok bool
+	var watchedChannelsContexts []*channelContextMap
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if watchedChannelsContexts, ok = c.watchedChannelsContext[key]; !ok {
+		log.Errorw("key-has-no-watched-context-or-channel", log.Fields{"key": key})
+		return
+	}
+	// Look for the channels
+	var pos = -1
+	for i, chCtxMap := range watchedChannelsContexts {
+		if chCtxMap.channel == ch {
+			log.Debug("channel-found")
+			chCtxMap.cancel()
+			//close the channel
+			close(ch)
+			pos = i
+			break
+		}
+	}
+	// Remove that entry if present
+	if pos >= 0 {
+		c.watchedChannelsContext[key] = append(c.watchedChannelsContext[key][:pos], c.watchedChannelsContext[key][pos+1:]...)
+	}
+	log.Debugw("watched-channel-exiting", log.Fields{"key": key, "channel": c.watchedChannelsContext[key]})
+}
+
+func (c *ConsulClient) isKVEqual(kv1 *consulapi.KVPair, kv2 *consulapi.KVPair) bool {
+	if (kv1 == nil) && (kv2 == nil) {
+		return true
+	} else if (kv1 == nil) || (kv2 == nil) {
+		return false
+	}
+	// Both the KV should be non-null here
+	if kv1.Key != kv2.Key ||
+		!bytes.Equal(kv1.Value, kv2.Value) ||
+		kv1.Session != kv2.Session ||
+		kv1.LockIndex != kv2.LockIndex ||
+		kv1.ModifyIndex != kv2.ModifyIndex {
+		return false
+	}
+	return true
+}
+
+func (c *ConsulClient) listenForKeyChange(watchContext context.Context, key string, ch chan *Event) {
+	log.Debugw("start-watching-channel", log.Fields{"key": key, "channel": ch})
+
+	defer c.CloseWatch(key, ch)
+	duration := GetDuration(defaultKVGetTimeout)
+	kv := c.consul.KV()
+	var queryOptions consulapi.QueryOptions
+	queryOptions.WaitTime = duration
+
+	// Get the existing value, if any
+	previousKVPair, meta, err := kv.Get(key, &queryOptions)
+	if err != nil {
+		log.Debug(err)
+	}
+	lastIndex := meta.LastIndex
+
+	// Wait for change.  Push any change onto the channel and keep waiting for new update
+	//var waitOptions consulapi.QueryOptions
+	var pair *consulapi.KVPair
+	//watchContext, _ := context.WithCancel(context.Background())
+	waitOptions := queryOptions.WithContext(watchContext)
+	for {
+		//waitOptions = consulapi.QueryOptions{WaitIndex: lastIndex}
+		waitOptions.WaitIndex = lastIndex
+		pair, meta, err = kv.Get(key, waitOptions)
+		select {
+		case <-watchContext.Done():
+			log.Debug("done-event-received-exiting")
+			return
+		default:
+			if err != nil {
+				log.Warnw("error-from-watch", log.Fields{"error": err})
+				ch <- NewEvent(CONNECTIONDOWN, key, []byte(""), -1)
+			} else {
+				log.Debugw("index-state", log.Fields{"lastindex": lastIndex, "newindex": meta.LastIndex, "key": key})
+			}
+		}
+		if err != nil {
+			log.Debug(err)
+			// On error, block for 10 milliseconds to prevent endless loop
+			time.Sleep(10 * time.Millisecond)
+		} else if meta.LastIndex <= lastIndex {
+			log.Info("no-index-change-or-negative")
+		} else {
+			log.Debugw("update-received", log.Fields{"pair": pair})
+			if pair == nil {
+				ch <- NewEvent(DELETE, key, []byte(""), -1)
+			} else if !c.isKVEqual(pair, previousKVPair) {
+				// Push the change onto the channel if the data has changed
+				// For now just assume it's a PUT change
+				log.Debugw("pair-details", log.Fields{"session": pair.Session, "key": pair.Key, "value": pair.Value})
+				ch <- NewEvent(PUT, pair.Key, pair.Value, -1)
+			}
+			previousKVPair = pair
+			lastIndex = meta.LastIndex
+		}
+	}
+}
+
+// Close closes the KV store client
+func (c *ConsulClient) Close() {
+	var writeOptions consulapi.WriteOptions
+	// Inform any goroutine it's time to say goodbye.
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if c.doneCh != nil {
+		close(*c.doneCh)
+	}
+
+	// Clear the sessionID
+	if _, err := c.consul.Session().Destroy(c.sessionID, &writeOptions); err != nil {
+		log.Errorw("error-closing-client", log.Fields{"error": err})
+	}
+}
+
+func (c *ConsulClient) AcquireLock(lockName string, timeout int) error {
+	return nil
+}
+
+func (c *ConsulClient) ReleaseLock(lockName string) error {
+	return nil
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/etcdclient.go b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/etcdclient.go
new file mode 100644
index 0000000..8db047c
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/etcdclient.go
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kvstore
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"github.com/opencord/voltha-lib-go/v2/pkg/log"
+	v3Client "go.etcd.io/etcd/clientv3"
+	v3Concurrency "go.etcd.io/etcd/clientv3/concurrency"
+	v3rpcTypes "go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
+	"sync"
+)
+
+// EtcdClient represents the Etcd KV store client
+type EtcdClient struct {
+	ectdAPI          *v3Client.Client
+	leaderRev        v3Client.Client
+	keyReservations  map[string]*v3Client.LeaseID
+	watchedChannels  sync.Map
+	writeLock        sync.Mutex
+	lockToMutexMap   map[string]*v3Concurrency.Mutex
+	lockToSessionMap map[string]*v3Concurrency.Session
+	lockToMutexLock  sync.Mutex
+}
+
+// NewEtcdClient returns a new client for the Etcd KV store
+func NewEtcdClient(addr string, timeout int) (*EtcdClient, error) {
+	duration := GetDuration(timeout)
+
+	c, err := v3Client.New(v3Client.Config{
+		Endpoints:   []string{addr},
+		DialTimeout: duration,
+	})
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	reservations := make(map[string]*v3Client.LeaseID)
+	lockMutexMap := make(map[string]*v3Concurrency.Mutex)
+	lockSessionMap := make(map[string]*v3Concurrency.Session)
+
+	return &EtcdClient{ectdAPI: c, keyReservations: reservations, lockToMutexMap: lockMutexMap,
+		lockToSessionMap: lockSessionMap}, nil
+}
+
+// IsConnectionUp returns whether the connection to the Etcd KV store is up.  If a timeout occurs then
+// it is assumed the connection is down or unreachable.
+func (c *EtcdClient) IsConnectionUp(timeout int) bool {
+	// Let's try to get a non existent key.  If the connection is up then there will be no error returned.
+	if _, err := c.Get("non-existent-key", timeout); err != nil {
+		return false
+	}
+	return true
+}
+
+// List returns an array of key-value pairs with key as a prefix.  Timeout defines how long the function will
+// wait for a response
+func (c *EtcdClient) List(key string, timeout int, lock ...bool) (map[string]*KVPair, error) {
+	duration := GetDuration(timeout)
+
+	ctx, cancel := context.WithTimeout(context.Background(), duration)
+
+	resp, err := c.ectdAPI.Get(ctx, key, v3Client.WithPrefix())
+	cancel()
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	m := make(map[string]*KVPair)
+	for _, ev := range resp.Kvs {
+		m[string(ev.Key)] = NewKVPair(string(ev.Key), ev.Value, "", ev.Lease, ev.Version)
+	}
+	return m, nil
+}
+
+// Get returns a key-value pair for a given key. Timeout defines how long the function will
+// wait for a response
+func (c *EtcdClient) Get(key string, timeout int, lock ...bool) (*KVPair, error) {
+	duration := GetDuration(timeout)
+
+	ctx, cancel := context.WithTimeout(context.Background(), duration)
+
+	resp, err := c.ectdAPI.Get(ctx, key)
+	cancel()
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	for _, ev := range resp.Kvs {
+		// Only one value is returned
+		return NewKVPair(string(ev.Key), ev.Value, "", ev.Lease, ev.Version), nil
+	}
+	return nil, nil
+}
+
+// Put writes a key-value pair to the KV store.  Value can only be a string or []byte since the etcd API
+// accepts only a string as a value for a put operation. Timeout defines how long the function will
+// wait for a response
+func (c *EtcdClient) Put(key string, value interface{}, timeout int, lock ...bool) error {
+
+	// Validate that we can convert value to a string as etcd API expects a string
+	var val string
+	var er error
+	if val, er = ToString(value); er != nil {
+		return fmt.Errorf("unexpected-type-%T", value)
+	}
+
+	duration := GetDuration(timeout)
+
+	ctx, cancel := context.WithTimeout(context.Background(), duration)
+
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+
+	var err error
+	// Check if there is already a lease for this key - if there is then use it, otherwise a PUT will make
+	// that KV key permanent instead of automatically removing it after a lease expiration
+	if leaseID, ok := c.keyReservations[key]; ok {
+		_, err = c.ectdAPI.Put(ctx, key, val, v3Client.WithLease(*leaseID))
+	} else {
+		_, err = c.ectdAPI.Put(ctx, key, val)
+	}
+	cancel()
+	if err != nil {
+		switch err {
+		case context.Canceled:
+			log.Warnw("context-cancelled", log.Fields{"error": err})
+		case context.DeadlineExceeded:
+			log.Warnw("context-deadline-exceeded", log.Fields{"error": err})
+		case v3rpcTypes.ErrEmptyKey:
+			log.Warnw("etcd-client-error", log.Fields{"error": err})
+		default:
+			log.Warnw("bad-endpoints", log.Fields{"error": err})
+		}
+		return err
+	}
+	return nil
+}
+
+// Delete removes a key from the KV store. Timeout defines how long the function will
+// wait for a response
+func (c *EtcdClient) Delete(key string, timeout int, lock ...bool) error {
+
+	duration := GetDuration(timeout)
+
+	ctx, cancel := context.WithTimeout(context.Background(), duration)
+
+	defer cancel()
+
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+
+	// delete the key
+	if _, err := c.ectdAPI.Delete(ctx, key); err != nil {
+		log.Errorw("failed-to-delete-key", log.Fields{"key": key, "error": err})
+		return err
+	}
+	log.Debugw("key(s)-deleted", log.Fields{"key": key})
+	return nil
+}
+
+// Reserve is invoked to acquire a key and set it to a given value. Value can only be a string or []byte since
+// the etcd API accepts only a string.  Timeout defines how long the function will wait for a response.  TTL
+// defines how long that reservation is valid.  When TTL expires the key is unreserved by the KV store itself.
+// If the key is acquired then the value returned will be the value passed in.  If the key is already acquired
+// then the value assigned to that key will be returned.
+func (c *EtcdClient) Reserve(key string, value interface{}, ttl int64) (interface{}, error) {
+	// Validate that we can convert value to a string as etcd API expects a string
+	var val string
+	var er error
+	if val, er = ToString(value); er != nil {
+		return nil, fmt.Errorf("unexpected-type%T", value)
+	}
+
+	// Create a lease
+	resp, err := c.ectdAPI.Grant(context.Background(), ttl)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	// Register the lease id
+	c.writeLock.Lock()
+	c.keyReservations[key] = &resp.ID
+	c.writeLock.Unlock()
+
+	// Revoke lease if reservation is not successful
+	reservationSuccessful := false
+	defer func() {
+		if !reservationSuccessful {
+			if err = c.ReleaseReservation(key); err != nil {
+				log.Error("cannot-release-lease")
+			}
+		}
+	}()
+
+	// Try to grap the Key with the above lease
+	c.ectdAPI.Txn(context.Background())
+	txn := c.ectdAPI.Txn(context.Background())
+	txn = txn.If(v3Client.Compare(v3Client.Version(key), "=", 0))
+	txn = txn.Then(v3Client.OpPut(key, val, v3Client.WithLease(resp.ID)))
+	txn = txn.Else(v3Client.OpGet(key))
+	result, er := txn.Commit()
+	if er != nil {
+		return nil, er
+	}
+
+	if !result.Succeeded {
+		// Verify whether we are already the owner of that Key
+		if len(result.Responses) > 0 &&
+			len(result.Responses[0].GetResponseRange().Kvs) > 0 {
+			kv := result.Responses[0].GetResponseRange().Kvs[0]
+			if string(kv.Value) == val {
+				reservationSuccessful = true
+				return value, nil
+			}
+			return kv.Value, nil
+		}
+	} else {
+		// Read the Key to ensure this is our Key
+		m, err := c.Get(key, defaultKVGetTimeout, false)
+		if err != nil {
+			return nil, err
+		}
+		if m != nil {
+			if m.Key == key && isEqual(m.Value, value) {
+				// My reservation is successful - register it.  For now, support is only for 1 reservation per key
+				// per session.
+				reservationSuccessful = true
+				return value, nil
+			}
+			// My reservation has failed.  Return the owner of that key
+			return m.Value, nil
+		}
+	}
+	return nil, nil
+}
+
+// ReleaseAllReservations releases all key reservations previously made (using Reserve API)
+func (c *EtcdClient) ReleaseAllReservations() error {
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	for key, leaseID := range c.keyReservations {
+		_, err := c.ectdAPI.Revoke(context.Background(), *leaseID)
+		if err != nil {
+			log.Errorw("cannot-release-reservation", log.Fields{"key": key, "error": err})
+			return err
+		}
+		delete(c.keyReservations, key)
+	}
+	return nil
+}
+
+// ReleaseReservation releases reservation for a specific key.
+func (c *EtcdClient) ReleaseReservation(key string) error {
+	// Get the leaseid using the key
+	log.Debugw("Release-reservation", log.Fields{"key": key})
+	var ok bool
+	var leaseID *v3Client.LeaseID
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if leaseID, ok = c.keyReservations[key]; !ok {
+		return nil
+	}
+	if leaseID != nil {
+		_, err := c.ectdAPI.Revoke(context.Background(), *leaseID)
+		if err != nil {
+			log.Error(err)
+			return err
+		}
+		delete(c.keyReservations, key)
+	}
+	return nil
+}
+
+// RenewReservation renews a reservation.  A reservation will go stale after the specified TTL (Time To Live)
+// period specified when reserving the key
+func (c *EtcdClient) RenewReservation(key string) error {
+	// Get the leaseid using the key
+	var ok bool
+	var leaseID *v3Client.LeaseID
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if leaseID, ok = c.keyReservations[key]; !ok {
+		return errors.New("key-not-reserved")
+	}
+
+	if leaseID != nil {
+		_, err := c.ectdAPI.KeepAliveOnce(context.Background(), *leaseID)
+		if err != nil {
+			log.Errorw("lease-may-have-expired", log.Fields{"error": err})
+			return err
+		}
+	} else {
+		return errors.New("lease-expired")
+	}
+	return nil
+}
+
+// Watch provides the watch capability on a given key.  It returns a channel onto which the callee needs to
+// listen to receive Events.
+func (c *EtcdClient) Watch(key string) chan *Event {
+	w := v3Client.NewWatcher(c.ectdAPI)
+	ctx, cancel := context.WithCancel(context.Background())
+	channel := w.Watch(ctx, key)
+
+	// Create a new channel
+	ch := make(chan *Event, maxClientChannelBufferSize)
+
+	// Keep track of the created channels so they can be closed when required
+	channelMap := make(map[chan *Event]v3Client.Watcher)
+	channelMap[ch] = w
+
+	channelMaps := c.addChannelMap(key, channelMap)
+
+	// Changing the log field (from channelMaps) as the underlying logger cannot format the map of channels into a
+	// json format.
+	log.Debugw("watched-channels", log.Fields{"len": len(channelMaps)})
+	// Launch a go routine to listen for updates
+	go c.listenForKeyChange(channel, ch, cancel)
+
+	return ch
+
+}
+
+func (c *EtcdClient) addChannelMap(key string, channelMap map[chan *Event]v3Client.Watcher) []map[chan *Event]v3Client.Watcher {
+	var channels interface{}
+	var exists bool
+
+	if channels, exists = c.watchedChannels.Load(key); exists {
+		channels = append(channels.([]map[chan *Event]v3Client.Watcher), channelMap)
+	} else {
+		channels = []map[chan *Event]v3Client.Watcher{channelMap}
+	}
+	c.watchedChannels.Store(key, channels)
+
+	return channels.([]map[chan *Event]v3Client.Watcher)
+}
+
+func (c *EtcdClient) removeChannelMap(key string, pos int) []map[chan *Event]v3Client.Watcher {
+	var channels interface{}
+	var exists bool
+
+	if channels, exists = c.watchedChannels.Load(key); exists {
+		channels = append(channels.([]map[chan *Event]v3Client.Watcher)[:pos], channels.([]map[chan *Event]v3Client.Watcher)[pos+1:]...)
+		c.watchedChannels.Store(key, channels)
+	}
+
+	return channels.([]map[chan *Event]v3Client.Watcher)
+}
+
+func (c *EtcdClient) getChannelMaps(key string) ([]map[chan *Event]v3Client.Watcher, bool) {
+	var channels interface{}
+	var exists bool
+
+	channels, exists = c.watchedChannels.Load(key)
+
+	if channels == nil {
+		return nil, exists
+	}
+
+	return channels.([]map[chan *Event]v3Client.Watcher), exists
+}
+
+// CloseWatch closes a specific watch. Both the key and the channel are required when closing a watch as there
+// may be multiple listeners on the same key.  The previously created channel serves as a key
+func (c *EtcdClient) CloseWatch(key string, ch chan *Event) {
+	// Get the array of channels mapping
+	var watchedChannels []map[chan *Event]v3Client.Watcher
+	var ok bool
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+
+	if watchedChannels, ok = c.getChannelMaps(key); !ok {
+		log.Warnw("key-has-no-watched-channels", log.Fields{"key": key})
+		return
+	}
+	// Look for the channels
+	var pos = -1
+	for i, chMap := range watchedChannels {
+		if t, ok := chMap[ch]; ok {
+			log.Debug("channel-found")
+			// Close the etcd watcher before the client channel.  This should close the etcd channel as well
+			if err := t.Close(); err != nil {
+				log.Errorw("watcher-cannot-be-closed", log.Fields{"key": key, "error": err})
+			}
+			pos = i
+			break
+		}
+	}
+
+	channelMaps, _ := c.getChannelMaps(key)
+	// Remove that entry if present
+	if pos >= 0 {
+		channelMaps = c.removeChannelMap(key, pos)
+	}
+	log.Infow("watcher-channel-exiting", log.Fields{"key": key, "channel": channelMaps})
+}
+
+func (c *EtcdClient) listenForKeyChange(channel v3Client.WatchChan, ch chan<- *Event, cancel context.CancelFunc) {
+	log.Debug("start-listening-on-channel ...")
+	defer cancel()
+	defer close(ch)
+	for resp := range channel {
+		for _, ev := range resp.Events {
+			ch <- NewEvent(getEventType(ev), ev.Kv.Key, ev.Kv.Value, ev.Kv.Version)
+		}
+	}
+	log.Debug("stop-listening-on-channel ...")
+}
+
+func getEventType(event *v3Client.Event) int {
+	switch event.Type {
+	case v3Client.EventTypePut:
+		return PUT
+	case v3Client.EventTypeDelete:
+		return DELETE
+	}
+	return UNKNOWN
+}
+
+// Close closes the KV store client
+func (c *EtcdClient) Close() {
+	c.writeLock.Lock()
+	defer c.writeLock.Unlock()
+	if err := c.ectdAPI.Close(); err != nil {
+		log.Errorw("error-closing-client", log.Fields{"error": err})
+	}
+}
+
+func (c *EtcdClient) addLockName(lockName string, lock *v3Concurrency.Mutex, session *v3Concurrency.Session) {
+	c.lockToMutexLock.Lock()
+	defer c.lockToMutexLock.Unlock()
+	c.lockToMutexMap[lockName] = lock
+	c.lockToSessionMap[lockName] = session
+}
+
+func (c *EtcdClient) deleteLockName(lockName string) {
+	c.lockToMutexLock.Lock()
+	defer c.lockToMutexLock.Unlock()
+	delete(c.lockToMutexMap, lockName)
+	delete(c.lockToSessionMap, lockName)
+}
+
+func (c *EtcdClient) getLock(lockName string) (*v3Concurrency.Mutex, *v3Concurrency.Session) {
+	c.lockToMutexLock.Lock()
+	defer c.lockToMutexLock.Unlock()
+	var lock *v3Concurrency.Mutex
+	var session *v3Concurrency.Session
+	if l, exist := c.lockToMutexMap[lockName]; exist {
+		lock = l
+	}
+	if s, exist := c.lockToSessionMap[lockName]; exist {
+		session = s
+	}
+	return lock, session
+}
+
+func (c *EtcdClient) AcquireLock(lockName string, timeout int) error {
+	duration := GetDuration(timeout)
+	ctx, cancel := context.WithTimeout(context.Background(), duration)
+	defer cancel()
+	session, _ := v3Concurrency.NewSession(c.ectdAPI, v3Concurrency.WithContext(ctx))
+	mu := v3Concurrency.NewMutex(session, "/devicelock_"+lockName)
+	if err := mu.Lock(context.Background()); err != nil {
+		cancel()
+		return err
+	}
+	c.addLockName(lockName, mu, session)
+	return nil
+}
+
+func (c *EtcdClient) ReleaseLock(lockName string) error {
+	lock, session := c.getLock(lockName)
+	var err error
+	if lock != nil {
+		if e := lock.Unlock(context.Background()); e != nil {
+			err = e
+		}
+	}
+	if session != nil {
+		if e := session.Close(); e != nil {
+			err = e
+		}
+	}
+	c.deleteLockName(lockName)
+
+	return err
+}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/kvutils.go b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/kvutils.go
new file mode 100644
index 0000000..cf9a95c
--- /dev/null
+++ b/vendor/github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore/kvutils.go
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package kvstore
+
+import (
+	"fmt"
+	"time"
+)
+
+// GetDuration converts a timeout value from int to duration.  If the timeout value is
+// either not set of -ve then we default KV timeout (configurable) is used.
+func GetDuration(timeout int) time.Duration {
+	if timeout <= 0 {
+		return defaultKVGetTimeout * time.Second
+	}
+	return time.Duration(timeout) * time.Second
+}
+
+// ToString converts an interface value to a string.  The interface should either be of
+// a string type or []byte.  Otherwise, an error is returned.
+func ToString(value interface{}) (string, error) {
+	switch t := value.(type) {
+	case []byte:
+		return string(value.([]byte)), nil
+	case string:
+		return value.(string), nil
+	default:
+		return "", fmt.Errorf("unexpected-type-%T", t)
+	}
+}
+
+// ToByte converts an interface value to a []byte.  The interface should either be of
+// a string type or []byte.  Otherwise, an error is returned.
+func ToByte(value interface{}) ([]byte, error) {
+	switch t := value.(type) {
+	case []byte:
+		return value.([]byte), nil
+	case string:
+		return []byte(value.(string)), nil
+	default:
+		return nil, fmt.Errorf("unexpected-type-%T", t)
+	}
+}
