blob: 3e508288e29b4531ac2eb9b357da38a6ea325ed1 [file] [log] [blame]
Author Namea594e632018-08-10 11:33:58 -04001/*
2 Copyright 2017 the original author or authors.
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
17package main
18
19import (
20 "flag"
21 "fmt"
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040022 "io/ioutil"
Author Namea594e632018-08-10 11:33:58 -040023 "log"
24 "net"
25 "net/http"
26 "os"
27 "strings"
donNewtonAlphac997d642018-10-17 13:22:48 -040028 "time"
Author Namea594e632018-08-10 11:33:58 -040029
30 "gerrit.opencord.org/abstract-olt/api"
31 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040032 "gerrit.opencord.org/abstract-olt/models"
Author Namea594e632018-08-10 11:33:58 -040033 "github.com/grpc-ecosystem/grpc-gateway/runtime"
donNewtonAlphac997d642018-10-17 13:22:48 -040034 "github.com/mongodb/mongo-go-driver/bson"
35 "github.com/mongodb/mongo-go-driver/mongo"
Author Namea594e632018-08-10 11:33:58 -040036 "golang.org/x/net/context"
37 "google.golang.org/grpc"
38 "google.golang.org/grpc/credentials"
39 "google.golang.org/grpc/metadata"
40)
41
42// private type for Context keys
43type contextKey int
44
donNewtonAlphab3279ea2018-09-18 15:55:32 -040045var useSsl *bool
46var useAuthentication *bool
47var certDirectory *string
48
Author Namea594e632018-08-10 11:33:58 -040049const (
50 clientIDKey contextKey = iota
51)
52
53/*
54GetLogger - returns the logger
55*/
56func credMatcher(headerName string) (mdName string, ok bool) {
57 if headerName == "Login" || headerName == "Password" {
58 return headerName, true
59 }
60 return "", false
61}
62
63// authenticateAgent check the client credentials
64func authenticateClient(ctx context.Context, s *api.Server) (string, error) {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040065 //TODO if we decide to handle Authentication with AbstractOLT this will need to be bound to an authentication service
Author Namea594e632018-08-10 11:33:58 -040066 if md, ok := metadata.FromIncomingContext(ctx); ok {
67 clientLogin := strings.Join(md["login"], "")
68 clientPassword := strings.Join(md["password"], "")
69
70 if clientLogin != "john" {
71 return "", fmt.Errorf("unknown user %s", clientLogin)
72 }
73 if clientPassword != "doe" {
74 return "", fmt.Errorf("bad password %s", clientPassword)
75 }
76
77 log.Printf("authenticated client: %s", clientLogin)
78 return "42", nil
79 }
80 return "", fmt.Errorf("missing credentials")
81}
82
83// unaryInterceptor call authenticateClient with current context
84func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
85 s, ok := info.Server.(*api.Server)
86 if !ok {
87 return nil, fmt.Errorf("unable to cast server")
88 }
89 clientID, err := authenticateClient(ctx, s)
90 if err != nil {
91 return nil, err
92 }
93
94 ctx = context.WithValue(ctx, clientIDKey, clientID)
95 return handler(ctx, req)
96}
97
98func startGRPCServer(address, certFile, keyFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040099 if settings.GetDebug() {
100 log.Printf("startGRPCServer(LisenAddress:%s,CertFile:%s,KeyFile:%s\n", address, certFile, keyFile)
101 }
Author Namea594e632018-08-10 11:33:58 -0400102 // create a listener on TCP port
103 lis, err := net.Listen("tcp", address)
Author Namea594e632018-08-10 11:33:58 -0400104
105 // create a server instance
106 s := api.Server{}
107
108 // Create the TLS credentials
Author Namea594e632018-08-10 11:33:58 -0400109
110 // Create an array of gRPC options with the credentials
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400111 var opts []grpc.ServerOption
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400112 creds, err := credentials.NewClientTLSFromFile(certFile, "")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400113 if *useSsl && *useAuthentication {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400114 if err != nil {
115 return fmt.Errorf("could not load TLS keys: %s", err)
116 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400117 opts = []grpc.ServerOption{grpc.Creds(creds),
118 grpc.UnaryInterceptor(unaryInterceptor)}
119 } else if *useAuthentication {
120 opts = []grpc.ServerOption{grpc.UnaryInterceptor(unaryInterceptor)}
121 } else if *useSsl {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400122 if err != nil {
123 return fmt.Errorf("could not load TLS keys: %s", err)
124 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400125 opts = []grpc.ServerOption{grpc.Creds(creds)}
126 } else {
127 opts = []grpc.ServerOption{}
128 }
Author Namea594e632018-08-10 11:33:58 -0400129
130 // create a gRPC server object
131 grpcServer := grpc.NewServer(opts...)
132
133 // attach the Ping service to the server
donNewtonAlpha5234b132018-08-16 14:12:28 -0400134 api.RegisterAbstractOLTServer(grpcServer, &s)
Author Namea594e632018-08-10 11:33:58 -0400135
136 // start the server
137 log.Printf("starting HTTP/2 gRPC server on %s", address)
138 if err := grpcServer.Serve(lis); err != nil {
139 return fmt.Errorf("failed to serve: %s", err)
140 }
141
142 return nil
143}
144func startRESTServer(address, grpcAddress, certFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400145 if settings.GetDebug() {
146 log.Printf("startRESTServer(Address:%s, GRPCAddress:%s,Cert File:%s\n", address, grpcAddress, certFile)
147 }
Author Namea594e632018-08-10 11:33:58 -0400148 ctx := context.Background()
149 ctx, cancel := context.WithCancel(ctx)
150 defer cancel()
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400151 var mux *runtime.ServeMux
Author Namea594e632018-08-10 11:33:58 -0400152
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400153 var opts []grpc.DialOption
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400154 if *useAuthentication {
155 mux = runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(credMatcher))
156 } else {
157 mux = runtime.NewServeMux()
158 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400159 if *useSsl {
160 creds, err := credentials.NewClientTLSFromFile(certFile, "")
161 opts = []grpc.DialOption{grpc.WithTransportCredentials(creds)}
162 if err != nil {
163 return fmt.Errorf("could not load TLS certificate: %s", err)
164 }
165 } else {
166 opts = []grpc.DialOption{grpc.WithInsecure()}
Author Namea594e632018-08-10 11:33:58 -0400167 }
Author Namea594e632018-08-10 11:33:58 -0400168 // Setup the client gRPC options
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400169 err := api.RegisterAbstractOLTHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
Author Namea594e632018-08-10 11:33:58 -0400170 if err != nil {
171 return fmt.Errorf("could not register service Ping: %s", err)
172 }
173
174 log.Printf("starting HTTP/1.1 REST server on %s", address)
175 http.ListenAndServe(address, mux)
176
177 return nil
178}
179func main() {
180 debugPtr := flag.Bool("d", false, "Log Level Debug")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400181 useAuthentication = flag.Bool("a", false, "Use Authentication")
182 useSsl = flag.Bool("s", false, "Use SSL")
183 certDirectory = flag.String("cert_dir", "cert", "Directory where key files exist")
184 listenAddress := flag.String("listenAddress", "localhost", "IP Address to listen on")
185 grpcPort := flag.String("grpc_port", "7777", "Port to listen for GRPC")
186 restPort := flag.String("rest_port", "7778", "Port to listen for Rest Server")
187 logFile := flag.String("log_file", "AbstractOLT.log", "Name of the LogFile to write to")
188 h := flag.Bool("h", false, "Show usage")
189 help := flag.Bool("help", false, "Show usage")
donNewtonAlphaaf229742018-09-19 13:22:00 -0400190 dummy := flag.Bool("dummy", false, "Run in dummy mode where YAML is not sent to XOS")
Author Namea594e632018-08-10 11:33:58 -0400191
donNewtonAlphac997d642018-10-17 13:22:48 -0400192 useMongo := flag.Bool("useMongo", false, "use mongo db for backup/restore")
193 mongodb := flag.String("mongodb", "mongodb://foundry:foundry@localhost:27017", "connect string for mongodb backup/restore")
194
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400195 flag.Parse()
donNewtonAlphaaf229742018-09-19 13:22:00 -0400196 settings.SetDummy(*dummy)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400197
198 if *help || *h {
199 var usage = `./AbstractOLT -d [default false] : Runs in Debug mode
200Params:
201 -s [default false] -cert_dir [default $WORKING_DIR/cert] DIR : Runs in SSL mode with server.crt and server.key found in DIR
202 -a [default false] : Run in Authentication mode currently very basic
203 -listenAddress IP_ADDRESS [default localhost] -grpc_port [default 7777] PORT1 -rest_port [default 7778] PORT2: Listen for grpc on IP_ADDRESS:PORT1 and rest on IP_ADDRESS:PORT2
204 -log_file [default $WORKING_DIR/AbstractOLT.log] LOG_FILE
donNewtonAlphac997d642018-10-17 13:22:48 -0400205 -mongo [default false] use mongodb for backup restore
206 -mongodb [default mongodb://foundry:foundry@localhost:27017] connect string for mongodb - Required if mongo == true
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400207 -h(elp) print this usage
donNewtonAlphac997d642018-10-17 13:22:48 -0400208
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400209`
210 fmt.Println(usage)
211 return
212 }
213 settings.SetDebug(*debugPtr)
donNewtonAlphac997d642018-10-17 13:22:48 -0400214 settings.SetMongo(*useMongo)
215 settings.SetMongodb(*mongodb)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400216 fmt.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
217 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
218
219 file, err := os.OpenFile(*logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
Author Namea594e632018-08-10 11:33:58 -0400220 if err != nil {
221 log.Fatalln("Failed to open log file", file, ":", err)
222 }
223 log.SetOutput(file)
224 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
donNewtonAlphaaf229742018-09-19 13:22:00 -0400225 if *dummy {
226 fmt.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
227 log.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
228 }
Author Namea594e632018-08-10 11:33:58 -0400229 log.Printf("Setting Debug to %t\n", settings.GetDebug())
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400230 if settings.GetDebug() {
231 log.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
232 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
233 }
Author Namea594e632018-08-10 11:33:58 -0400234
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400235 grpcAddress := fmt.Sprintf("%s:%s", *listenAddress, *grpcPort)
236 restAddress := fmt.Sprintf("%s:%s", *listenAddress, *restPort)
237
238 certFile := fmt.Sprintf("%s/server.crt", *certDirectory)
239 keyFile := fmt.Sprintf("%s/server.key", *certDirectory)
Author Namea594e632018-08-10 11:33:58 -0400240
241 // fire the gRPC server in a goroutine
242 go func() {
243 err := startGRPCServer(grpcAddress, certFile, keyFile)
244 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400245 log.Printf("failed to start gRPC server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400246 }
247 }()
248
249 // fire the REST server in a goroutine
250 go func() {
251 err := startRESTServer(restAddress, grpcAddress, certFile)
252 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400253 log.Printf("failed to start REST server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400254 }
255 }()
256
257 // infinite loop
donNewtonAlphac997d642018-10-17 13:22:48 -0400258 if *useMongo {
259 client, err := mongo.NewClient(*mongodb)
260 client.Connect(context.Background())
261 defer client.Disconnect(context.Background())
262 if err != nil {
263 log.Fatalf("unable to connect to mongodb with %v\n", err)
264 }
265 collection := client.Database("AbstractOLT").Collection("backup")
266 cur, err := collection.Find(context.Background(), nil)
267 if err != nil {
268 log.Fatalf("Unable to connect to collection with %v\n", err)
269 }
270 defer cur.Close(context.Background())
271 for cur.Next(context.Background()) {
272 elem := bson.NewDocument()
273 err := cur.Decode(elem)
donNewtonAlphab8f30752018-10-04 11:57:41 -0400274 if err != nil {
donNewtonAlphac997d642018-10-17 13:22:48 -0400275 log.Fatal(err)
donNewtonAlphab8f30752018-10-04 11:57:41 -0400276 }
donNewtonAlphac997d642018-10-17 13:22:48 -0400277 clli := elem.LookupElement("_id").Value()
278 body := elem.LookupElement("body").Value()
279 _, bodyBin := (*body).Binary()
280
281 chassisHolder := models.ChassisHolder{}
282 err = chassisHolder.Deserialize(bodyBin)
283 if err != nil {
284 log.Printf("Deserialize threw an error for clli %s %v\n", (*clli).StringValue(), err)
285 } else {
286 chassisMap := models.GetChassisMap()
287 (*chassisMap)[(*clli).StringValue()] = &chassisHolder
288
289 }
290 }
291 } else {
292 files, err := ioutil.ReadDir("backup")
293 if err != nil {
294 log.Fatal(err)
295 }
296 for _, file := range files {
297 chassisHolder := models.ChassisHolder{}
298 if file.Name() != "BackupPlaceHolder" {
299 fileName := fmt.Sprintf("backup/%s", file.Name())
300 json, _ := ioutil.ReadFile(fileName)
301 err := chassisHolder.Deserialize([]byte(json))
302 if err != nil {
303 fmt.Printf("Deserialize threw an error %v\n", err)
304 }
305 chassisMap := models.GetChassisMap()
306 (*chassisMap)[file.Name()] = &chassisHolder
307 } else {
308 fmt.Println("Ignoring BackupPlaceHolder")
309 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400310 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400311 }
312
Author Namea594e632018-08-10 11:33:58 -0400313 log.Printf("Entering infinite loop")
donNewtonAlphac997d642018-10-17 13:22:48 -0400314 var ticker = time.NewTicker(60 * time.Second)
315 for {
316 select {
317 case <-ticker.C:
318 api.DoOutput()
319 }
320 }
321
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400322 //TODO publish periodic stats etc
Author Namea594e632018-08-10 11:33:58 -0400323 fmt.Println("AbstractOLT")
324}