[VOL-2782] Update go.mod of voltha-go,open-olt-adapter,ofagent-go and voltctl to be compatible with latest version of voltha-lig-go

Change-Id: Idd1a36b6059927af9a4f3c12581663d587a19176
diff --git a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go
index 6ed18e9..79fefc5 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager/ponresourcemanager.go
@@ -42,6 +42,16 @@
 	//Constants for passing command line arugments
 	OLT_MODEL_ARG = "--olt_model"
 	PATH_PREFIX   = "service/voltha/resource_manager/{%s}"
+
+	/*The path under which configuration data is stored is defined as technology/device agnostic.
+	  That means the path does not include any specific technology/device variable. Using technology/device
+	  agnostic path also makes northbound applications, that need to write to this path,
+	  technology/device agnostic.
+
+	  Default kv client of PonResourceManager reads from/writes to PATH_PREFIX defined above.
+	  That is why, an additional kv client (named KVStoreForConfig) is defined to read from the config path.
+	*/
+	PATH_PREFIX_FOR_CONFIG = "service/voltha/resource_manager/config"
 	/*The resource ranges for a given device model should be placed
 	  at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
 	  path on the KV store.
@@ -115,6 +125,9 @@
 	NUM_OF_PON_INTF = 16
 
 	KVSTORE_RETRY_TIMEOUT = 5
+	//Path on the KV store for storing reserved gem ports
+	//Format: reserved_gemport_ids
+	RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
 )
 
 //type ResourceTypeIndex string
@@ -122,15 +135,16 @@
 
 type PONResourceManager struct {
 	//Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
-	Technology     string
-	DeviceType     string
-	DeviceID       string
-	Backend        string // ETCD, or consul
-	Host           string // host ip of the KV store
-	Port           int    // port number for the KV store
-	OLTModel       string
-	KVStore        *db.Backend
-	TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
+	Technology       string
+	DeviceType       string
+	DeviceID         string
+	Backend          string // ETCD, or consul
+	Host             string // host ip of the KV store
+	Port             int    // port number for the KV store
+	OLTModel         string
+	KVStore          *db.Backend
+	KVStoreForConfig *db.Backend
+	TechProfileMgr   tp.TechProfileIf // create object of *tp.TechProfileMgr
 
 	// Below attribute, pon_resource_ranges, should be initialized
 	// by reading from KV store.
@@ -152,7 +166,7 @@
 	return nil, errors.New("unsupported-kv-store")
 }
 
-func SetKVClient(Technology string, Backend string, Host string, Port int) *db.Backend {
+func SetKVClient(Technology string, Backend string, Host string, Port int, configClient bool) *db.Backend {
 	addr := Host + ":" + strconv.Itoa(Port)
 	// TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
 	// issue between kv store and backend , core is not calling NewBackend directly
@@ -161,13 +175,21 @@
 		log.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
 		return nil
 	}
+
+	var pathPrefix string
+	if configClient {
+		pathPrefix = PATH_PREFIX_FOR_CONFIG
+	} else {
+		pathPrefix = fmt.Sprintf(PATH_PREFIX, Technology)
+	}
+
 	kvbackend := &db.Backend{
 		Client:     kvClient,
 		StoreType:  Backend,
 		Host:       Host,
 		Port:       Port,
 		Timeout:    KVSTORE_RETRY_TIMEOUT,
-		PathPrefix: fmt.Sprintf(PATH_PREFIX, Technology)}
+		PathPrefix: pathPrefix}
 
 	return kvbackend
 }
@@ -181,11 +203,17 @@
 	PONMgr.Backend = Backend
 	PONMgr.Host = Host
 	PONMgr.Port = Port
-	PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port)
+	PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port, false)
 	if PONMgr.KVStore == nil {
 		log.Error("KV Client initilization failed")
 		return nil, errors.New("Failed to init KV client")
 	}
+	// init kv client to read from the config path
+	PONMgr.KVStoreForConfig = SetKVClient(Technology, Backend, Host, Port, true)
+	if PONMgr.KVStoreForConfig == nil {
+		log.Error("KV Config Client initilization failed")
+		return nil, errors.New("Failed to init KV Config client")
+	}
 	// Initialize techprofile for this technology
 	if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
 		log.Error("Techprofile initialization failed")
@@ -493,7 +521,15 @@
 		log.Debugf("Resource %s already present in store ", Path)
 		return nil
 	} else {
-		FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID)
+		var excluded []uint32
+		if ResourceType == GEMPORT_ID {
+			//get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
+			if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
+				excluded = reservedGemPortIds
+				log.Debugw("Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
+			}
+		}
+		FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID, excluded)
 		if err != nil {
 			log.Errorf("Failed to format resource")
 			return err
@@ -511,12 +547,38 @@
 	return err
 }
 
-func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
+func (PONRMgr *PONResourceManager) getReservedGemPortIdsFromKVStore(ctx context.Context) ([]uint32, bool) {
+	var reservedGemPortIds []uint32
+	// read reserved gem ports from the config path
+	KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
+	if err != nil {
+		log.Errorw("Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
+		return reservedGemPortIds, false
+	}
+	if KvPair == nil || KvPair.Value == nil {
+		//no reserved gem port defined in the store
+		return reservedGemPortIds, false
+	}
+	Val, err := kvstore.ToByte(KvPair.Value)
+	if err != nil {
+		log.Errorw("Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
+		return reservedGemPortIds, false
+	}
+	if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
+		log.Errorw("Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
+		return reservedGemPortIds, false
+	}
+	return reservedGemPortIds, true
+}
+
+func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32,
+	Excluded []uint32) ([]byte, error) {
 	/*
 	   Format resource as json.
 	   :param pon_intf_id: OLT PON interface id
 	   :param start_idx: start index for id pool
 	   :param end_idx: end index for id pool
+	   :Id values to be Excluded from the pool
 	   :return dictionary: resource formatted as map
 	*/
 	// Format resource as json to be stored in backend store
@@ -534,6 +596,14 @@
 		log.Error("Failed to create a bitmap")
 		return nil, errors.New("Failed to create bitmap")
 	}
+	for _, excludedID := range Excluded {
+		if excludedID < StartIDx || excludedID > EndIDx {
+			log.Warnf("Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
+				StartIDx, EndIDx)
+			continue
+		}
+		PONRMgr.reserveID(TSData, StartIDx, excludedID)
+	}
 	Resource[POOL] = TSData.Data(false) //we pass false so as the TSData lib api does not do a copy of the data and return
 
 	Value, err := json.Marshal(Resource)
@@ -1147,6 +1217,21 @@
 	return true
 }
 
+/* Reserves a unique id in the specified resource pool.
+:param Resource: resource used to reserve ID
+:param Id: ID to be reserved
+*/
+func (PONRMgr *PONResourceManager) reserveID(TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
+	Data := bitmap.TSFromData(TSData.Data(false), false)
+	if Data == nil {
+		log.Error("Failed to get resource pool")
+		return false
+	}
+	Idx := Id - StartIndex
+	Data.Set(int(Idx), true)
+	return true
+}
+
 func (PONRMgr *PONResourceManager) GetTechnology() string {
 	return PONRMgr.Technology
 }