VOL-1399: The value of the metadata field used by OFAgent & Arouter
          should not be hard-coded
- Added grpc-timeout and core-binding-key options to OFAgent run command
- Added core_binding_key option to rw_core run command

Change-Id: Icf5fe226d17a1a5fcd9459a85e41c434fc7ac8b9
diff --git a/rw_core/config/config.go b/rw_core/config/config.go
index b924376..f977be0 100644
--- a/rw_core/config/config.go
+++ b/rw_core/config/config.go
@@ -50,6 +50,7 @@
 	default_InCompetingMode     = true
 	default_LongRunningRequestTimeout = int64(2000)
 	default_DefaultRequestTimeout = int64(500)
+	default_CoreBindingKey      = "voltha_backend_name"
 )
 
 // RWCoreFlags represents the set of configurations used by the read-write core service
@@ -79,6 +80,7 @@
 	InCompetingMode     bool
 	LongRunningRequestTimeout int64
 	DefaultRequestTimeout int64
+	CoreBindingKey      string
 }
 
 func init() {
@@ -112,6 +114,7 @@
 		InCompetingMode:     default_InCompetingMode,
 		DefaultRequestTimeout:default_DefaultRequestTimeout,
 		LongRunningRequestTimeout:default_LongRunningRequestTimeout,
+		CoreBindingKey:      default_CoreBindingKey,
 	}
 	return &rwCoreFlag
 }
@@ -181,6 +184,9 @@
 	help = fmt.Sprintf("Show startup banner log lines")
 	flag.BoolVar(&cf.Banner, "banner", default_Banner, help)
 
+	help = fmt.Sprintf("The name of the meta-key whose value is the rw-core group to which the ofagent is bound")
+	flag.StringVar(&(cf.CoreBindingKey), "core_binding_key", default_CoreBindingKey, help)
+
 	flag.Parse()
 
 	containerName := getContainerInfo()
diff --git a/rw_core/core/core.go b/rw_core/core/core.go
index b3bbc71..13baf84 100644
--- a/rw_core/core/core.go
+++ b/rw_core/core/core.go
@@ -124,6 +124,7 @@
 
 	//core.grpcNBIAPIHandler = NewAPIHandler(core.deviceMgr, core.logicalDeviceMgr, core.adapterMgr, core.config.InCompetingMode, core.config.LongRunningRequestTimeout, core.config.DefaultRequestTimeout)
 	core.grpcNBIAPIHandler = NewAPIHandler(core)
+	log.Infow("grpc-handler", log.Fields{"core_binding_key": core.config.CoreBindingKey})
 	core.logicalDeviceMgr.setGrpcNbiHandler(core.grpcNBIAPIHandler)
 	//	Create a function to register the core GRPC service with the GRPC server
 	f := func(gs *grpc.Server) {
diff --git a/rw_core/core/grpc_nbi_api_handler.go b/rw_core/core/grpc_nbi_api_handler.go
index 0bbe5de..7b486bd 100644
--- a/rw_core/core/grpc_nbi_api_handler.go
+++ b/rw_core/core/grpc_nbi_api_handler.go
@@ -32,9 +32,6 @@
 	"time"
 )
 
-//TODO:  Move this Tag into the proto file
-const OF_CONTROLLER_TAG= "voltha_backend_name"
-
 const (
 	IMAGE_DOWNLOAD = iota
 	CANCEL_IMAGE_DOWNLOAD     = iota
@@ -124,10 +121,10 @@
 
 // isOFControllerRequest is a helper function to determine if a request was initiated
 // from the OpenFlow controller (or its proxy, e.g. OFAgent)
-func isOFControllerRequest(ctx context.Context) bool {
+func (handler *APIHandler) isOFControllerRequest(ctx context.Context) bool {
 	if md, ok := metadata.FromIncomingContext(ctx); ok {
 		// Metadata in context
-		if _, ok = md[OF_CONTROLLER_TAG]; ok {
+		if _, ok = md[handler.core.config.CoreBindingKey]; ok {
 			// OFAgent field in metadata
 			return true
 		}
@@ -271,7 +268,7 @@
 	}
 
 	if handler.competeForTransaction() {
-		if !isOFControllerRequest(ctx) { // No need to acquire the transaction as request is sent to one core only
+		if !handler.isOFControllerRequest(ctx) { // No need to acquire the transaction as request is sent to one core only
 			if txn, err := handler.acquireTransaction(ctx, &logicalDeviceID{id:flow.Id}); err != nil {
 				return new(empty.Empty), err
 			} else {
@@ -294,7 +291,7 @@
 	}
 
 	if handler.competeForTransaction() {
-		if !isOFControllerRequest(ctx) { // No need to acquire the transaction as request is sent to one core only
+		if !handler.isOFControllerRequest(ctx) { // No need to acquire the transaction as request is sent to one core only
 			if txn, err := handler.acquireTransaction(ctx, &logicalDeviceID{id:flow.Id}); err != nil {
 				return new(empty.Empty), err
 			} else {