blob: 2cc29763da99d2ae641047f68ec7cfdb7a46ed49 [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 */
16// gRPC affinity router with active/active backends
17
18package afrouter
19
20// Command line parameters and parsing
21import (
sslobodr392ebd52019-01-18 12:41:49 -050022 "encoding/json"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040023 "errors"
24 "flag"
25 "fmt"
sslobodr392ebd52019-01-18 12:41:49 -050026 "github.com/opencord/voltha-go/common/log"
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040027 "io/ioutil"
28 "os"
29 "path"
sslobodr392ebd52019-01-18 12:41:49 -050030)
31
32func ParseCmd() (*Configuration, error) {
33 config := &Configuration{}
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040034 cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError)
sslobodr392ebd52019-01-18 12:41:49 -050035 config.ConfigFile = cmdParse.String("config", "arouter.json", "The configuration file for the affinity router")
36 config.LogLevel = cmdParse.Int("logLevel", 0, "The log level for the affinity router")
37 config.GrpcLog = cmdParse.Bool("grpclog", false, "Enable GRPC logging")
38
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040039 err := cmdParse.Parse(os.Args[1:])
sslobodr3d587c62019-01-24 12:33:39 -050040 if err != nil {
sslobodr392ebd52019-01-18 12:41:49 -050041 //return err
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040042 return nil, errors.New("Error parsing the command line")
sslobodr392ebd52019-01-18 12:41:49 -050043 }
44 //if(!cmdParse.Parsed()) {
45 //}
46 return config, nil
47}
48
49// Configuration file loading and parsing
50type Configuration struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040051 ConfigFile *string
52 LogLevel *int
53 GrpcLog *bool
54 Servers []ServerConfig `json:"servers"`
55 Ports PortConfig `json:"ports"`
56 ServerCertificates ServerCertConfig `json:"serverCertificates"`
57 ClientCertificates ClientCertConfig `json:"clientCertificates"`
58 BackendClusters []BackendClusterConfig `json:"backend_clusters"`
59 Routers []RouterConfig `json:"routers"`
60 Api ApiConfig
sslobodr392ebd52019-01-18 12:41:49 -050061}
62
63type RouterConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040064 Name string `json:"name"`
65 ProtoService string `json:"service"`
66 ProtoPackage string `json:"package"`
67 Routes []RouteConfig `json:"routes"`
sslobodr392ebd52019-01-18 12:41:49 -050068}
69
70type RouteConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040071 Name string `json:"name"`
72 Type string `json:"type"`
73 ProtoFile string `json:"proto_descriptor"`
74 Association string `json:"association"`
75 RouteField string `json:"routing_field"`
76 Methods []string `json:"methods"` // The GRPC methods to route using the route field
77 NbBindingMethods []string `json:"nb_binding_methods"`
78 BackendCluster string `json:"backend_cluster"`
79 Binding BindingConfig `json:"binding"`
80 Overrides []OverrideConfig `json:"overrides"`
81 backendCluster *BackendClusterConfig
sslobodr392ebd52019-01-18 12:41:49 -050082}
83
84type BindingConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040085 Type string `json:"type"`
86 Field string `json:"field"`
87 Method string `json:"method"`
sslobodr392ebd52019-01-18 12:41:49 -050088 Association string `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -050089}
90
91type OverrideConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040092 Methods []string `json:"methods"`
93 Method string `json:"method"`
94 RouteField string `json:"routing_field"`
sslobodr392ebd52019-01-18 12:41:49 -050095}
96
97// Backend configuration
98
99type BackendClusterConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400100 Name string `json:"name"`
sslobodr392ebd52019-01-18 12:41:49 -0500101 Backends []BackendConfig `json:"backends"`
102}
103
104type BackendConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400105 Name string `json:"name"`
106 Type string `json:"type"`
107 Association AssociationConfig `json:"association"`
sslobodr392ebd52019-01-18 12:41:49 -0500108 Connections []ConnectionConfig `json:"connections"`
109}
110
111type AssociationConfig struct {
112 Strategy string `json:"strategy"`
113 Location string `json:"location"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400114 Field string `json:"field"`
115 Key string `json:"key"`
sslobodr392ebd52019-01-18 12:41:49 -0500116}
117
118type ConnectionConfig struct {
119 Name string `json:"name"`
120 Addr string `json:"addr"`
121 Port string `json:"port"`
122}
123
124// Server configuration
125
126type ServerConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400127 Name string `json:"name"`
128 Port uint `json:"port"`
129 Addr string `json:"address"`
130 Type string `json:"type"`
sslobodr392ebd52019-01-18 12:41:49 -0500131 Routers []RouterPackage `json:"routers"`
132 routers map[string]*RouterConfig
133}
134
135type RouterPackage struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400136 Router string `json:"router"`
sslobodr392ebd52019-01-18 12:41:49 -0500137 Package string `json:"package"`
138}
139
140// Port configuration
141type PortConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400142 GrpcPort uint `json:"grpcPort"`
143 StreamingGrpcPort uint `json:"streamingGrpcPort"`
144 TlsGrpcPort uint `json:"tlsGrpcPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500145 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400146 ControlPort uint `json:"controlPort"`
sslobodr392ebd52019-01-18 12:41:49 -0500147}
148
149// Server Certificate configuration
150type ServerCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400151 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
152 GrpcKey string `json:"grpcKey"` // File path to the key file
153 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500154}
155
156// Client Certificate configuration
157type ClientCertConfig struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400158 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
159 GrpcKey string `json:"grpcKey"` // File path to the key file
160 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
sslobodr392ebd52019-01-18 12:41:49 -0500161}
162
163// Api configuration
164type ApiConfig struct {
165 Addr string `json:"address"`
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400166 Port uint `json:"port"`
sslobodr392ebd52019-01-18 12:41:49 -0500167}
168
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400169func (conf *Configuration) LoadConfig() error {
sslobodr392ebd52019-01-18 12:41:49 -0500170
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400171 configF, err := os.Open(*conf.ConfigFile)
sslobodr392ebd52019-01-18 12:41:49 -0500172 log.Info("Loading configuration from: ", *conf.ConfigFile)
173 if err != nil {
174 log.Error(err)
175 return err
176 }
177
178 defer configF.Close()
179
180 configBytes, err := ioutil.ReadAll(configF)
181 if err != nil {
182 log.Error(err)
183 return err
184 }
185
sslobodr8e2ccb52019-02-05 09:21:47 -0500186 if err := json.Unmarshal(configBytes, conf); err != nil {
187 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
188 return err
189 }
sslobodr392ebd52019-01-18 12:41:49 -0500190
191 // Now resolve references to different config objects in the
192 // config file. Currently there are 2 possible references
193 // to resolve: referecnes to routers in the servers, and
194 // references to backend_cluster in the routers.
195
196 // Resolve router references for the servers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400197 log.Debug("Resolving references in the config file")
198 for k, _ := range conf.Servers {
sslobodr392ebd52019-01-18 12:41:49 -0500199 //s.routers =make(map[string]*RouterConfig)
200 conf.Servers[k].routers = make(map[string]*RouterConfig)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400201 for _, rPkg := range conf.Servers[k].Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500202 var found bool = false
203 // Locate the router "r" in the top lever Routers array
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400204 log.Debugf("Resolving router reference to router '%s' from server '%s'", rPkg.Router, conf.Servers[k].Name)
sslobodr3d587c62019-01-24 12:33:39 -0500205 for rk, _ := range conf.Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500206 if conf.Routers[rk].Name == rPkg.Router && !found {
207 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
208 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
209 found = true
210 } else if conf.Routers[rk].Name == rPkg.Router && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400211 if _, ok := conf.Servers[k].routers[rPkg.Package]; !ok {
sslobodr392ebd52019-01-18 12:41:49 -0500212 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
213 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
214 } else {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400215 err := errors.New(fmt.Sprintf("Duplicate router '%s' defined for package '%s'", rPkg.Router, rPkg.Package))
sslobodr392ebd52019-01-18 12:41:49 -0500216 log.Error(err)
217 return err
218 }
219 }
220 }
221 if !found {
222 err := errors.New(fmt.Sprintf("Router %s for server %s not found in config", conf.Servers[k].Name, rPkg.Router))
223 log.Error(err)
224 return err
225 }
226 }
227 }
228
229 // Resolve backend references for the routers
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400230 for rk, rv := range conf.Routers {
231 for rtk, rtv := range rv.Routes {
sslobodr392ebd52019-01-18 12:41:49 -0500232 var found bool = false
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400233 log.Debugf("Resolving backend reference to %s from router %s", rtv.BackendCluster, rv.Name)
234 for bek, bev := range conf.BackendClusters {
sslobodr392ebd52019-01-18 12:41:49 -0500235 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
236 if rtv.BackendCluster == bev.Name && !found {
237 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
238 found = true
239 } else if rtv.BackendCluster == bev.Name && found {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400240 err := errors.New(fmt.Sprintf("Duplicate backend defined, %s", conf.BackendClusters[bek].Name))
sslobodr392ebd52019-01-18 12:41:49 -0500241 log.Error(err)
242 return err
243 }
244 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400245 if !found {
sslobodr392ebd52019-01-18 12:41:49 -0500246 err := errors.New(fmt.Sprintf("Backend %s for router %s not found in config",
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400247 rtv.BackendCluster, rv.Name))
sslobodr392ebd52019-01-18 12:41:49 -0500248 log.Error(err)
249 return err
250 }
251 }
252 }
253
sslobodr392ebd52019-01-18 12:41:49 -0500254 return nil
255}