blob: d3c177c4d9f9daf24bc33c8b6278b7500c29767a [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"
Don Newtone973d342018-10-26 16:44:12 -040031 "gerrit.opencord.org/abstract-olt/internal/pkg/impl"
Author Namea594e632018-08-10 11:33:58 -040032 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040033 "gerrit.opencord.org/abstract-olt/models"
Author Namea594e632018-08-10 11:33:58 -040034 "github.com/grpc-ecosystem/grpc-gateway/runtime"
donNewtonAlphac997d642018-10-17 13:22:48 -040035 "github.com/mongodb/mongo-go-driver/mongo"
Don Newton16520672018-11-28 14:44:42 -050036 "github.com/mongodb/mongo-go-driver/mongo/options"
37 "github.com/mongodb/mongo-go-driver/x/bsonx"
Author Namea594e632018-08-10 11:33:58 -040038 "golang.org/x/net/context"
39 "google.golang.org/grpc"
40 "google.golang.org/grpc/credentials"
41 "google.golang.org/grpc/metadata"
42)
43
44// private type for Context keys
45type contextKey int
46
donNewtonAlphab3279ea2018-09-18 15:55:32 -040047var useSsl *bool
48var useAuthentication *bool
49var certDirectory *string
50
Author Namea594e632018-08-10 11:33:58 -040051const (
52 clientIDKey contextKey = iota
53)
54
55/*
56GetLogger - returns the logger
57*/
58func credMatcher(headerName string) (mdName string, ok bool) {
59 if headerName == "Login" || headerName == "Password" {
60 return headerName, true
61 }
62 return "", false
63}
64
65// authenticateAgent check the client credentials
66func authenticateClient(ctx context.Context, s *api.Server) (string, error) {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040067 //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 -040068 if md, ok := metadata.FromIncomingContext(ctx); ok {
69 clientLogin := strings.Join(md["login"], "")
70 clientPassword := strings.Join(md["password"], "")
71
72 if clientLogin != "john" {
73 return "", fmt.Errorf("unknown user %s", clientLogin)
74 }
75 if clientPassword != "doe" {
76 return "", fmt.Errorf("bad password %s", clientPassword)
77 }
78
79 log.Printf("authenticated client: %s", clientLogin)
80 return "42", nil
81 }
82 return "", fmt.Errorf("missing credentials")
83}
84
85// unaryInterceptor call authenticateClient with current context
86func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
87 s, ok := info.Server.(*api.Server)
88 if !ok {
89 return nil, fmt.Errorf("unable to cast server")
90 }
91 clientID, err := authenticateClient(ctx, s)
92 if err != nil {
93 return nil, err
94 }
95
96 ctx = context.WithValue(ctx, clientIDKey, clientID)
97 return handler(ctx, req)
98}
99
100func startGRPCServer(address, certFile, keyFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400101 if settings.GetDebug() {
102 log.Printf("startGRPCServer(LisenAddress:%s,CertFile:%s,KeyFile:%s\n", address, certFile, keyFile)
103 }
Author Namea594e632018-08-10 11:33:58 -0400104 // create a listener on TCP port
105 lis, err := net.Listen("tcp", address)
Author Namea594e632018-08-10 11:33:58 -0400106
107 // create a server instance
108 s := api.Server{}
109
110 // Create the TLS credentials
Author Namea594e632018-08-10 11:33:58 -0400111
112 // Create an array of gRPC options with the credentials
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400113 var opts []grpc.ServerOption
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400114 creds, err := credentials.NewClientTLSFromFile(certFile, "")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400115 if *useSsl && *useAuthentication {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400116 if err != nil {
117 return fmt.Errorf("could not load TLS keys: %s", err)
118 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400119 opts = []grpc.ServerOption{grpc.Creds(creds),
120 grpc.UnaryInterceptor(unaryInterceptor)}
121 } else if *useAuthentication {
122 opts = []grpc.ServerOption{grpc.UnaryInterceptor(unaryInterceptor)}
123 } else if *useSsl {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400124 if err != nil {
125 return fmt.Errorf("could not load TLS keys: %s", err)
126 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400127 opts = []grpc.ServerOption{grpc.Creds(creds)}
128 } else {
129 opts = []grpc.ServerOption{}
130 }
Author Namea594e632018-08-10 11:33:58 -0400131
132 // create a gRPC server object
133 grpcServer := grpc.NewServer(opts...)
134
135 // attach the Ping service to the server
donNewtonAlpha5234b132018-08-16 14:12:28 -0400136 api.RegisterAbstractOLTServer(grpcServer, &s)
Author Namea594e632018-08-10 11:33:58 -0400137
138 // start the server
139 log.Printf("starting HTTP/2 gRPC server on %s", address)
140 if err := grpcServer.Serve(lis); err != nil {
141 return fmt.Errorf("failed to serve: %s", err)
142 }
143
144 return nil
145}
146func startRESTServer(address, grpcAddress, certFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400147 if settings.GetDebug() {
148 log.Printf("startRESTServer(Address:%s, GRPCAddress:%s,Cert File:%s\n", address, grpcAddress, certFile)
149 }
Author Namea594e632018-08-10 11:33:58 -0400150 ctx := context.Background()
151 ctx, cancel := context.WithCancel(ctx)
152 defer cancel()
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400153 var mux *runtime.ServeMux
Author Namea594e632018-08-10 11:33:58 -0400154
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400155 var opts []grpc.DialOption
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400156 if *useAuthentication {
157 mux = runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(credMatcher))
158 } else {
159 mux = runtime.NewServeMux()
160 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400161 if *useSsl {
162 creds, err := credentials.NewClientTLSFromFile(certFile, "")
163 opts = []grpc.DialOption{grpc.WithTransportCredentials(creds)}
164 if err != nil {
165 return fmt.Errorf("could not load TLS certificate: %s", err)
166 }
167 } else {
168 opts = []grpc.DialOption{grpc.WithInsecure()}
Author Namea594e632018-08-10 11:33:58 -0400169 }
Author Namea594e632018-08-10 11:33:58 -0400170 // Setup the client gRPC options
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400171 err := api.RegisterAbstractOLTHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
Author Namea594e632018-08-10 11:33:58 -0400172 if err != nil {
173 return fmt.Errorf("could not register service Ping: %s", err)
174 }
175
176 log.Printf("starting HTTP/1.1 REST server on %s", address)
177 http.ListenAndServe(address, mux)
178
179 return nil
180}
181func main() {
182 debugPtr := flag.Bool("d", false, "Log Level Debug")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400183 useAuthentication = flag.Bool("a", false, "Use Authentication")
184 useSsl = flag.Bool("s", false, "Use SSL")
185 certDirectory = flag.String("cert_dir", "cert", "Directory where key files exist")
186 listenAddress := flag.String("listenAddress", "localhost", "IP Address to listen on")
187 grpcPort := flag.String("grpc_port", "7777", "Port to listen for GRPC")
188 restPort := flag.String("rest_port", "7778", "Port to listen for Rest Server")
189 logFile := flag.String("log_file", "AbstractOLT.log", "Name of the LogFile to write to")
190 h := flag.Bool("h", false, "Show usage")
191 help := flag.Bool("help", false, "Show usage")
donNewtonAlphaaf229742018-09-19 13:22:00 -0400192 dummy := flag.Bool("dummy", false, "Run in dummy mode where YAML is not sent to XOS")
Don Newton16520672018-11-28 14:44:42 -0500193 grpc := flag.Bool("grpc", false, "Use XOS GRPC interface instead of TOSCA")
Author Namea594e632018-08-10 11:33:58 -0400194
donNewtonAlphac997d642018-10-17 13:22:48 -0400195 useMongo := flag.Bool("useMongo", false, "use mongo db for backup/restore")
196 mongodb := flag.String("mongodb", "mongodb://foundry:foundry@localhost:27017", "connect string for mongodb backup/restore")
197
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400198 flag.Parse()
donNewtonAlphaaf229742018-09-19 13:22:00 -0400199 settings.SetDummy(*dummy)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400200
201 if *help || *h {
202 var usage = `./AbstractOLT -d [default false] : Runs in Debug mode
203Params:
204 -s [default false] -cert_dir [default $WORKING_DIR/cert] DIR : Runs in SSL mode with server.crt and server.key found in DIR
205 -a [default false] : Run in Authentication mode currently very basic
206 -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
207 -log_file [default $WORKING_DIR/AbstractOLT.log] LOG_FILE
donNewtonAlphac997d642018-10-17 13:22:48 -0400208 -mongo [default false] use mongodb for backup restore
209 -mongodb [default mongodb://foundry:foundry@localhost:27017] connect string for mongodb - Required if mongo == true
Don Newton16520672018-11-28 14:44:42 -0500210 -grpc [default false] tell AbstractOLT to use XOS GRPC interface instead of TOSCA
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400211 -h(elp) print this usage
donNewtonAlphac997d642018-10-17 13:22:48 -0400212
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400213`
214 fmt.Println(usage)
215 return
216 }
217 settings.SetDebug(*debugPtr)
donNewtonAlphac997d642018-10-17 13:22:48 -0400218 settings.SetMongo(*useMongo)
219 settings.SetMongodb(*mongodb)
Don Newton276cd1f2019-02-06 17:14:03 -0500220 if len(*mongodb) > 1 {
221 userPassHost := strings.Split(*mongodb, "://")[1]
222 passwdHost := strings.Split(userPassHost, ":")
223 user := strings.Split(userPassHost, ":")[0]
224 password := strings.Split(passwdHost[1], "@")[0]
225 settings.SetMongoUser(user)
226 settings.SetMongoPassword(password)
227 }
Don Newton16520672018-11-28 14:44:42 -0500228 settings.SetGrpc(*grpc)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400229 fmt.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
Don Newton16520672018-11-28 14:44:42 -0500230 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile, "Use XOS GRPC ", *grpc)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400231
232 file, err := os.OpenFile(*logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
Author Namea594e632018-08-10 11:33:58 -0400233 if err != nil {
234 log.Fatalln("Failed to open log file", file, ":", err)
235 }
236 log.SetOutput(file)
237 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
donNewtonAlphaaf229742018-09-19 13:22:00 -0400238 if *dummy {
239 fmt.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
240 log.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
241 }
Author Namea594e632018-08-10 11:33:58 -0400242 log.Printf("Setting Debug to %t\n", settings.GetDebug())
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400243 if settings.GetDebug() {
244 log.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
245 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
246 }
Author Namea594e632018-08-10 11:33:58 -0400247
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400248 grpcAddress := fmt.Sprintf("%s:%s", *listenAddress, *grpcPort)
249 restAddress := fmt.Sprintf("%s:%s", *listenAddress, *restPort)
250
251 certFile := fmt.Sprintf("%s/server.crt", *certDirectory)
252 keyFile := fmt.Sprintf("%s/server.key", *certDirectory)
Author Namea594e632018-08-10 11:33:58 -0400253
254 // fire the gRPC server in a goroutine
255 go func() {
256 err := startGRPCServer(grpcAddress, certFile, keyFile)
257 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400258 log.Printf("failed to start gRPC server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400259 }
260 }()
261
262 // fire the REST server in a goroutine
263 go func() {
264 err := startRESTServer(restAddress, grpcAddress, certFile)
265 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400266 log.Printf("failed to start REST server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400267 }
268 }()
269
270 // infinite loop
donNewtonAlphac997d642018-10-17 13:22:48 -0400271 if *useMongo {
Don Newton16520672018-11-28 14:44:42 -0500272 clientOptions := options.Client()
Don Newton276cd1f2019-02-06 17:14:03 -0500273 creds := options.Credential{AuthMechanism: "SCRAM-SHA-256", AuthSource: "AbstractOLT", Username: settings.GetMongoUser(), Password: settings.GetMongoPassword()}
Don Newton16520672018-11-28 14:44:42 -0500274 clientOptions.SetAuth(creds)
275
276 client, err := mongo.NewClientWithOptions(*mongodb, clientOptions)
277
donNewtonAlphac997d642018-10-17 13:22:48 -0400278 client.Connect(context.Background())
Don Newton16520672018-11-28 14:44:42 -0500279 fmt.Println(client)
donNewtonAlphac997d642018-10-17 13:22:48 -0400280 defer client.Disconnect(context.Background())
281 if err != nil {
282 log.Fatalf("unable to connect to mongodb with %v\n", err)
283 }
Don Newton16520672018-11-28 14:44:42 -0500284 collection := client.Database("AbstractOLT").Collection("backups")
donNewtonAlphac997d642018-10-17 13:22:48 -0400285 cur, err := collection.Find(context.Background(), nil)
286 if err != nil {
287 log.Fatalf("Unable to connect to collection with %v\n", err)
288 }
289 defer cur.Close(context.Background())
290 for cur.Next(context.Background()) {
Don Newton16520672018-11-28 14:44:42 -0500291 doc := bsonx.Doc{}
292 err := cur.Decode(&doc)
donNewtonAlphab8f30752018-10-04 11:57:41 -0400293 if err != nil {
donNewtonAlphac997d642018-10-17 13:22:48 -0400294 log.Fatal(err)
donNewtonAlphab8f30752018-10-04 11:57:41 -0400295 }
Don Newton16520672018-11-28 14:44:42 -0500296 clli := doc.LookupElement("_id").Value
297 body := doc.LookupElement("body").Value
298 _, bodyBin := (body).Binary()
donNewtonAlphac997d642018-10-17 13:22:48 -0400299
300 chassisHolder := models.ChassisHolder{}
301 err = chassisHolder.Deserialize(bodyBin)
302 if err != nil {
Don Newton16520672018-11-28 14:44:42 -0500303 log.Printf("Deserialize threw an error for clli %s %v\n", (clli).StringValue(), err)
donNewtonAlphac997d642018-10-17 13:22:48 -0400304 } else {
305 chassisMap := models.GetChassisMap()
Don Newton16520672018-11-28 14:44:42 -0500306 (*chassisMap)[(clli).StringValue()] = &chassisHolder
donNewtonAlphac997d642018-10-17 13:22:48 -0400307
308 }
309 }
310 } else {
311 files, err := ioutil.ReadDir("backup")
312 if err != nil {
313 log.Fatal(err)
314 }
315 for _, file := range files {
316 chassisHolder := models.ChassisHolder{}
317 if file.Name() != "BackupPlaceHolder" {
318 fileName := fmt.Sprintf("backup/%s", file.Name())
319 json, _ := ioutil.ReadFile(fileName)
320 err := chassisHolder.Deserialize([]byte(json))
321 if err != nil {
322 fmt.Printf("Deserialize threw an error %v\n", err)
323 }
324 chassisMap := models.GetChassisMap()
325 (*chassisMap)[file.Name()] = &chassisHolder
326 } else {
327 fmt.Println("Ignoring BackupPlaceHolder")
328 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400329 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400330 }
331
Author Namea594e632018-08-10 11:33:58 -0400332 log.Printf("Entering infinite loop")
donNewtonAlphac997d642018-10-17 13:22:48 -0400333 var ticker = time.NewTicker(60 * time.Second)
334 for {
335 select {
336 case <-ticker.C:
Don Newtone973d342018-10-26 16:44:12 -0400337 impl.DoOutput()
donNewtonAlphac997d642018-10-17 13:22:48 -0400338 }
339 }
340
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400341 //TODO publish periodic stats etc
Author Namea594e632018-08-10 11:33:58 -0400342 fmt.Println("AbstractOLT")
343}