blob: 2e7257124732ca6df933a2edcb25302740554559 [file] [log] [blame]
sslobodr392ebd52019-01-18 12:41:49 -05001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
sslobodr392ebd52019-01-18 12:41:49 -050016
17package afrouter
18
19import (
sslobodr392ebd52019-01-18 12:41:49 -050020 "errors"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040021 "fmt"
22 "github.com/opencord/voltha-go/common/log"
sslobodr392ebd52019-01-18 12:41:49 -050023 "google.golang.org/grpc"
24 "google.golang.org/grpc/metadata"
sslobodr392ebd52019-01-18 12:41:49 -050025)
26
27type BindingRouter struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040028 name string
Kent Hagerman1e9061e2019-05-21 16:01:21 -040029 association associationType
sslobodr392ebd52019-01-18 12:41:49 -050030 //routingField string
31 grpcService string
32 //protoDescriptor *pb.FileDescriptorSet
33 //methodMap map[string]byte
Kent Hagerman1e9061e2019-05-21 16:01:21 -040034 beCluster *cluster
35 bindings map[string]*backend
36 bindingType string
37 bindingField string
38 bindingMethod string
39 currentBackend **backend
sslobodr392ebd52019-01-18 12:41:49 -050040}
41
Kent Hagerman70a49bb2019-08-29 17:21:03 -040042func (br BindingRouter) IsStreaming(_ string) (bool, bool) {
43 panic("not implemented")
44}
45
Kent Hagerman1e9061e2019-05-21 16:01:21 -040046func (br BindingRouter) BackendCluster(s string, metaKey string) (*cluster, error) {
47 return br.beCluster, nil
sslobodr392ebd52019-01-18 12:41:49 -050048 //return nil,errors.New("Not implemented yet")
49}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040050func (br BindingRouter) Name() string {
sslobodr392ebd52019-01-18 12:41:49 -050051 return br.name
52}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040053func (br BindingRouter) Service() string {
sslobodr392ebd52019-01-18 12:41:49 -050054 return br.grpcService
55}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040056func (br BindingRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string, string, error) {
Kent Hagerman1e9061e2019-05-21 16:01:21 -040057 var rtrnK = ""
58 var rtrnV = ""
sslobodr392ebd52019-01-18 12:41:49 -050059
60 // Get the metadata from the server stream
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040061 md, ok := metadata.FromIncomingContext(serverStream.Context())
sslobodr392ebd52019-01-18 12:41:49 -050062 if !ok {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040063 return rtrnK, rtrnV, errors.New("Could not get a server stream metadata")
64 }
sslobodr392ebd52019-01-18 12:41:49 -050065
66 // Determine if one of the method routing keys exists in the metadata
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040067 if _, ok := md[br.bindingField]; ok == true {
sslobodr392ebd52019-01-18 12:41:49 -050068 rtrnV = md[br.bindingField][0]
69 rtrnK = br.bindingField
70 }
71
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040072 return rtrnK, rtrnV, nil
sslobodr392ebd52019-01-18 12:41:49 -050073}
Kent Hagerman1e9061e2019-05-21 16:01:21 -040074func (br BindingRouter) FindBackendCluster(becName string) *cluster {
75 if becName == br.beCluster.name {
76 return br.beCluster
sslobodr360c8d72019-02-05 12:47:56 -050077 }
sslobodr392ebd52019-01-18 12:41:49 -050078 return nil
79}
80func (br BindingRouter) ReplyHandler(v interface{}) error {
81 return nil
82}
Scott Baker5f401472019-08-22 08:32:26 -070083func (br BindingRouter) Route(sel interface{}) (*backend, *connection) {
sslobodr392ebd52019-01-18 12:41:49 -050084 var err error
85 switch sl := sel.(type) {
Kent Hagerman70a49bb2019-08-29 17:21:03 -040086 case *requestFrame:
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040087 if b, ok := br.bindings[sl.metaVal]; ok == true { // binding exists, just return it
Scott Baker5f401472019-08-22 08:32:26 -070088 return b, nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040089 } else { // establish a new binding or error.
90 if sl.metaVal != "" {
91 err = errors.New(fmt.Sprintf("Attempt to route on non-existent metadata value '%s' in key '%s'",
92 sl.metaVal, sl.metaKey))
93 log.Error(err)
94 sl.err = err
Scott Baker5f401472019-08-22 08:32:26 -070095 return nil, nil
sslobodr392ebd52019-01-18 12:41:49 -050096 }
Kent Hagerman1e9061e2019-05-21 16:01:21 -040097 if sl.methodInfo.method != br.bindingMethod {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040098 err = errors.New(fmt.Sprintf("Binding must occur with method %s but attempted with method %s",
Kent Hagerman1e9061e2019-05-21 16:01:21 -040099 br.bindingMethod, sl.methodInfo.method))
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400100 log.Error(err)
101 sl.err = err
Scott Baker5f401472019-08-22 08:32:26 -0700102 return nil, nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400103 }
104 log.Debugf("MUST CREATE A NEW BINDING MAP ENTRY!!")
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400105 if len(br.bindings) < len(br.beCluster.backends) {
106 if *br.currentBackend, err = br.beCluster.nextBackend(*br.currentBackend, BackendSequenceRoundRobin); err == nil {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400107 // Use the name of the backend as the metaVal for this new binding
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400108 br.bindings[(*br.currentBackend).name] = *br.currentBackend
Scott Baker5f401472019-08-22 08:32:26 -0700109 return *br.currentBackend, nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400110 } else {
111 log.Error(err)
112 sl.err = err
Scott Baker5f401472019-08-22 08:32:26 -0700113 return nil, nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400114 }
115 } else {
116 err = errors.New(fmt.Sprintf("Backends exhausted in attempt to bind for metakey '%s' with value '%s'",
117 sl.metaKey, sl.metaVal))
118 log.Error(err)
119 sl.err = err
120 }
121 }
Scott Baker5f401472019-08-22 08:32:26 -0700122 return nil, nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400123 default:
Scott Baker5f401472019-08-22 08:32:26 -0700124 return nil, nil
sslobodr392ebd52019-01-18 12:41:49 -0500125 }
sslobodr392ebd52019-01-18 12:41:49 -0500126}
127
sslobodrcd37bc52019-01-24 11:47:16 -0500128func newBindingRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400129 var rtrn_err = false
sslobodr392ebd52019-01-18 12:41:49 -0500130 var err error = nil
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400131 log.Debugf("Creating binding router %s", config.Name)
sslobodr392ebd52019-01-18 12:41:49 -0500132 // A name must exist
133 if config.Name == "" {
134 log.Error("A router 'name' must be specified")
135 rtrn_err = true
136 }
137
138 if rconf.ProtoPackage == "" {
139 log.Error("A 'package' must be specified")
140 rtrn_err = true
141 }
142
143 if rconf.ProtoService == "" {
144 log.Error("A 'service' must be specified")
145 rtrn_err = true
146 }
147
148 //if config.RouteField == "" {
149 // log.Error("A 'routing_field' must be specified")
150 // rtrn_err = true
151 //}
152
153 // TODO: Using the specified service, the imported proto
154 // descriptor file should be scanned for all methods provided
155 // for this router to ensure that this field exists in
156 // the message(s) passed to the method. This will avoid run
157 // time failures that might not be detected for long periods
158 // of time.
159
160 // TODO The routes section is currently not being used
161 // so the router will route all methods based on the
162 // routing_field. This needs to be done.
163 var bptr *backend
164 bptr = nil
165 br := BindingRouter{
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400166 name: config.Name,
167 grpcService: rconf.ProtoService,
168 bindings: make(map[string]*backend),
sslobodr392ebd52019-01-18 12:41:49 -0500169 //methodMap:make(map[string]byte),
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400170 currentBackend: &bptr,
sslobodr392ebd52019-01-18 12:41:49 -0500171 //serialNo:0,
172 }
173
174 // A binding association must exist
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400175 br.association = config.Binding.Association
176 if br.association == AssociationUndefined {
177 log.Error("An binding association must be specified")
sslobodr392ebd52019-01-18 12:41:49 -0500178 rtrn_err = true
179 }
180 // A binding type must exist
181 // TODO: This is parsed but ignored and a header based type is used.
182 if config.Binding.Type != "header" {
183 log.Error("The binding type must be set to header")
184 rtrn_err = true
185 } else {
186 br.bindingType = config.Binding.Type
187 }
188 // A binding method must exist
189 if config.Binding.Method == "" {
190 log.Error("The binding method must be specified")
191 rtrn_err = true
192 } else {
193 br.bindingMethod = config.Binding.Method
194 }
195 // A binding field must exxist
196 if config.Binding.Field == "" {
197 log.Error("The binding field must be specified")
198 rtrn_err = true
199 } else {
200 br.bindingField = config.Binding.Field
201 }
202
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400203 // Create the backend cluster or link to an existing one
sslobodr392ebd52019-01-18 12:41:49 -0500204 ok := true
Kent Hagerman1e9061e2019-05-21 16:01:21 -0400205 if br.beCluster, ok = clusters[config.backendCluster.Name]; ok == false {
206 if br.beCluster, err = newBackendCluster(config.backendCluster); err != nil {
sslobodr392ebd52019-01-18 12:41:49 -0500207 log.Errorf("Could not create a backend for router %s", config.Name)
208 rtrn_err = true
209 }
210 }
211
212 // HERE HERE HERE
213
214 if rtrn_err {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400215 return br, errors.New(fmt.Sprintf("Failed to create a new router '%s'", br.name))
sslobodr392ebd52019-01-18 12:41:49 -0500216 }
217
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400218 return br, nil
sslobodr392ebd52019-01-18 12:41:49 -0500219}