blob: a9a01ebc3432bf0e825316f8e760a5ce7b09ee27 [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 (
22 "os"
23 "fmt"
24 "flag"
25 "path"
26 "errors"
27 "io/ioutil"
28 "encoding/json"
29 "github.com/opencord/voltha-go/common/log"
30)
31
32func ParseCmd() (*Configuration, error) {
33 config := &Configuration{}
34 cmdParse := flag.NewFlagSet(path.Base(os.Args[0]), flag.ContinueOnError);
35 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
39 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
42 return nil, errors.New("Error parsing the command line");
43 }
44 //if(!cmdParse.Parsed()) {
45 //}
46 return config, nil
47}
48
49// Configuration file loading and parsing
50type Configuration struct {
51 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
61}
62
63type RouterConfig struct {
64 Name string `json:"name"`
65 ProtoService string `json:"service"`
66 ProtoPackage string `json:"package"`
67 Routes []RouteConfig `json:"routes"`
68}
69
70type RouteConfig struct {
71 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
82}
83
84type BindingConfig struct {
85 Type string `json:"type"`
86 Field string `json:"field"`
87 Method string `json:"method"`
88 Association string `json:"association"`
89
90}
91
92type OverrideConfig struct {
93 Methods []string `json:"methods"`
sslobodr8e2ccb52019-02-05 09:21:47 -050094 Method string `json:"method"`
sslobodr392ebd52019-01-18 12:41:49 -050095 RouteField string `json:"routing_field"`
96}
97
98// Backend configuration
99
100type BackendClusterConfig struct {
101 Name string `json:"name"`
102 Backends []BackendConfig `json:"backends"`
103}
104
105type BackendConfig struct {
106 Name string `json:"name"`
107 Type string `json:"type"`
108 Association AssociationConfig `json:"association"`
109 Connections []ConnectionConfig `json:"connections"`
110}
111
112type AssociationConfig struct {
113 Strategy string `json:"strategy"`
114 Location string `json:"location"`
115 Field string `json:"field"`
sslobodr8e2ccb52019-02-05 09:21:47 -0500116 Key string `json:"key"`
sslobodr392ebd52019-01-18 12:41:49 -0500117}
118
119type ConnectionConfig struct {
120 Name string `json:"name"`
121 Addr string `json:"addr"`
122 Port string `json:"port"`
123}
124
125// Server configuration
126
127type ServerConfig struct {
128 Name string `json:"name"`
129 Port uint `json:"port"`
130 Addr string `json:"address"`
131 Type string `json:"type"`
132 Routers []RouterPackage `json:"routers"`
133 routers map[string]*RouterConfig
134}
135
136type RouterPackage struct {
137 Router string `json:"router"`
138 Package string `json:"package"`
139}
140
141// Port configuration
142type PortConfig struct {
143 GrpcPort uint `json:"grpcPort"`
144 StreamingGrpcPort uint `json:"streamingGrpcPort"`
145 TlsGrpcPort uint `json:"tlsGrpcPort"`
146 TlsStreamingGrpcPort uint `json:"tlsStreamingGrpcPort"`
147 ControlPort uint `json:"controlPort"`
148}
149
150// Server Certificate configuration
151type ServerCertConfig struct {
152 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
153 GrpcKey string `json:"grpcKey"` // File path to the key file
154 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
155}
156
157// Client Certificate configuration
158type ClientCertConfig struct {
159 GrpcCert string `json:"grpcCertificate"` // File path to the certificate file
160 GrpcKey string `json:"grpcKey"` // File path to the key file
161 GrpcCsr string `json:"grpcCsr"` // File path to the CSR file
162}
163
164// Api configuration
165type ApiConfig struct {
166 Addr string `json:"address"`
167 Port uint `json:"port"`
168}
169
170func (conf * Configuration) LoadConfig() error {
171
172 configF, err := os.Open(*conf.ConfigFile);
173 log.Info("Loading configuration from: ", *conf.ConfigFile)
174 if err != nil {
175 log.Error(err)
176 return err
177 }
178
179 defer configF.Close()
180
181 configBytes, err := ioutil.ReadAll(configF)
182 if err != nil {
183 log.Error(err)
184 return err
185 }
186
sslobodr8e2ccb52019-02-05 09:21:47 -0500187 if err := json.Unmarshal(configBytes, conf); err != nil {
188 log.Errorf("Unmarshaling of the configuratino file failed: %v", err)
189 return err
190 }
sslobodr392ebd52019-01-18 12:41:49 -0500191
192 // Now resolve references to different config objects in the
193 // config file. Currently there are 2 possible references
194 // to resolve: referecnes to routers in the servers, and
195 // references to backend_cluster in the routers.
196
197 // Resolve router references for the servers
198 log.Debug("Resolving references in the config file");
sslobodr3d587c62019-01-24 12:33:39 -0500199 for k,_ := range conf.Servers {
sslobodr392ebd52019-01-18 12:41:49 -0500200 //s.routers =make(map[string]*RouterConfig)
201 conf.Servers[k].routers = make(map[string]*RouterConfig)
sslobodr3d587c62019-01-24 12:33:39 -0500202 for _,rPkg := range conf.Servers[k].Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500203 var found bool = false
204 // Locate the router "r" in the top lever Routers array
205 log.Debugf("Resolving router reference to router '%s' from server '%s'",rPkg.Router, conf.Servers[k].Name)
sslobodr3d587c62019-01-24 12:33:39 -0500206 for rk, _ := range conf.Routers {
sslobodr392ebd52019-01-18 12:41:49 -0500207 if conf.Routers[rk].Name == rPkg.Router && !found {
208 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
209 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
210 found = true
211 } else if conf.Routers[rk].Name == rPkg.Router && found {
212 if _,ok := conf.Servers[k].routers[rPkg.Package]; !ok {
213 log.Debugf("Reference to router '%s' found for package '%s'", rPkg.Router, rPkg.Package)
214 conf.Servers[k].routers[rPkg.Package] = &conf.Routers[rk]
215 } else {
khenaidoo731697e2019-01-29 16:03:29 -0500216 err := errors.New(fmt.Sprintf("Duplicate router '%s' defined for package '%s'",rPkg.Router, rPkg.Package))
sslobodr392ebd52019-01-18 12:41:49 -0500217 log.Error(err)
218 return err
219 }
220 }
221 }
222 if !found {
223 err := errors.New(fmt.Sprintf("Router %s for server %s not found in config", conf.Servers[k].Name, rPkg.Router))
224 log.Error(err)
225 return err
226 }
227 }
228 }
229
230 // Resolve backend references for the routers
sslobodr3d587c62019-01-24 12:33:39 -0500231 for rk,rv := range conf.Routers {
232 for rtk,rtv := range rv.Routes {
sslobodr392ebd52019-01-18 12:41:49 -0500233 var found bool = false
234 log.Debugf("Resolving backend reference to %s from router %s",rtv.BackendCluster, rv.Name)
sslobodr3d587c62019-01-24 12:33:39 -0500235 for bek,bev := range conf.BackendClusters {
sslobodr392ebd52019-01-18 12:41:49 -0500236 log.Debugf("Checking cluster %s", conf.BackendClusters[bek].Name)
237 if rtv.BackendCluster == bev.Name && !found {
238 conf.Routers[rk].Routes[rtk].backendCluster = &conf.BackendClusters[bek]
239 found = true
240 } else if rtv.BackendCluster == bev.Name && found {
241 err := errors.New(fmt.Sprintf("Duplicate backend defined, %s",conf.BackendClusters[bek].Name))
242 log.Error(err)
243 return err
244 }
245 }
246 if !found {
247 err := errors.New(fmt.Sprintf("Backend %s for router %s not found in config",
248 rtv.BackendCluster, rv.Name))
249 log.Error(err)
250 return err
251 }
252 }
253 }
254
255
256 return nil
257}