blob: 869c2c02b8b987f407c8c6d07677d4cdb558142b [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"
28
29 "gerrit.opencord.org/abstract-olt/api"
30 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
donNewtonAlphae7ab5b92018-09-27 15:09:14 -040031 "gerrit.opencord.org/abstract-olt/models"
Author Namea594e632018-08-10 11:33:58 -040032 "github.com/grpc-ecosystem/grpc-gateway/runtime"
33 "golang.org/x/net/context"
34 "google.golang.org/grpc"
35 "google.golang.org/grpc/credentials"
36 "google.golang.org/grpc/metadata"
37)
38
39// private type for Context keys
40type contextKey int
41
donNewtonAlphab3279ea2018-09-18 15:55:32 -040042var useSsl *bool
43var useAuthentication *bool
44var certDirectory *string
45
Author Namea594e632018-08-10 11:33:58 -040046const (
47 clientIDKey contextKey = iota
48)
49
50/*
51GetLogger - returns the logger
52*/
53func credMatcher(headerName string) (mdName string, ok bool) {
54 if headerName == "Login" || headerName == "Password" {
55 return headerName, true
56 }
57 return "", false
58}
59
60// authenticateAgent check the client credentials
61func authenticateClient(ctx context.Context, s *api.Server) (string, error) {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040062 //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 -040063 if md, ok := metadata.FromIncomingContext(ctx); ok {
64 clientLogin := strings.Join(md["login"], "")
65 clientPassword := strings.Join(md["password"], "")
66
67 if clientLogin != "john" {
68 return "", fmt.Errorf("unknown user %s", clientLogin)
69 }
70 if clientPassword != "doe" {
71 return "", fmt.Errorf("bad password %s", clientPassword)
72 }
73
74 log.Printf("authenticated client: %s", clientLogin)
75 return "42", nil
76 }
77 return "", fmt.Errorf("missing credentials")
78}
79
80// unaryInterceptor call authenticateClient with current context
81func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
82 s, ok := info.Server.(*api.Server)
83 if !ok {
84 return nil, fmt.Errorf("unable to cast server")
85 }
86 clientID, err := authenticateClient(ctx, s)
87 if err != nil {
88 return nil, err
89 }
90
91 ctx = context.WithValue(ctx, clientIDKey, clientID)
92 return handler(ctx, req)
93}
94
95func startGRPCServer(address, certFile, keyFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040096 if settings.GetDebug() {
97 log.Printf("startGRPCServer(LisenAddress:%s,CertFile:%s,KeyFile:%s\n", address, certFile, keyFile)
98 }
Author Namea594e632018-08-10 11:33:58 -040099 // create a listener on TCP port
100 lis, err := net.Listen("tcp", address)
Author Namea594e632018-08-10 11:33:58 -0400101
102 // create a server instance
103 s := api.Server{}
104
105 // Create the TLS credentials
Author Namea594e632018-08-10 11:33:58 -0400106
107 // Create an array of gRPC options with the credentials
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400108 var opts []grpc.ServerOption
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400109 creds, err := credentials.NewClientTLSFromFile(certFile, "")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400110 if *useSsl && *useAuthentication {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400111 if err != nil {
112 return fmt.Errorf("could not load TLS keys: %s", err)
113 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400114 opts = []grpc.ServerOption{grpc.Creds(creds),
115 grpc.UnaryInterceptor(unaryInterceptor)}
116 } else if *useAuthentication {
117 opts = []grpc.ServerOption{grpc.UnaryInterceptor(unaryInterceptor)}
118 } else if *useSsl {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400119 if err != nil {
120 return fmt.Errorf("could not load TLS keys: %s", err)
121 }
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400122 opts = []grpc.ServerOption{grpc.Creds(creds)}
123 } else {
124 opts = []grpc.ServerOption{}
125 }
Author Namea594e632018-08-10 11:33:58 -0400126
127 // create a gRPC server object
128 grpcServer := grpc.NewServer(opts...)
129
130 // attach the Ping service to the server
donNewtonAlpha5234b132018-08-16 14:12:28 -0400131 api.RegisterAbstractOLTServer(grpcServer, &s)
Author Namea594e632018-08-10 11:33:58 -0400132
133 // start the server
134 log.Printf("starting HTTP/2 gRPC server on %s", address)
135 if err := grpcServer.Serve(lis); err != nil {
136 return fmt.Errorf("failed to serve: %s", err)
137 }
138
139 return nil
140}
141func startRESTServer(address, grpcAddress, certFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400142 if settings.GetDebug() {
143 log.Printf("startRESTServer(Address:%s, GRPCAddress:%s,Cert File:%s\n", address, grpcAddress, certFile)
144 }
Author Namea594e632018-08-10 11:33:58 -0400145 ctx := context.Background()
146 ctx, cancel := context.WithCancel(ctx)
147 defer cancel()
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400148 var mux *runtime.ServeMux
Author Namea594e632018-08-10 11:33:58 -0400149
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400150 var opts []grpc.DialOption
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400151 if *useAuthentication {
152 mux = runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(credMatcher))
153 } else {
154 mux = runtime.NewServeMux()
155 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400156 if *useSsl {
157 creds, err := credentials.NewClientTLSFromFile(certFile, "")
158 opts = []grpc.DialOption{grpc.WithTransportCredentials(creds)}
159 if err != nil {
160 return fmt.Errorf("could not load TLS certificate: %s", err)
161 }
162 } else {
163 opts = []grpc.DialOption{grpc.WithInsecure()}
Author Namea594e632018-08-10 11:33:58 -0400164 }
Author Namea594e632018-08-10 11:33:58 -0400165 // Setup the client gRPC options
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400166 err := api.RegisterAbstractOLTHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
Author Namea594e632018-08-10 11:33:58 -0400167 if err != nil {
168 return fmt.Errorf("could not register service Ping: %s", err)
169 }
170
171 log.Printf("starting HTTP/1.1 REST server on %s", address)
172 http.ListenAndServe(address, mux)
173
174 return nil
175}
176func main() {
177 debugPtr := flag.Bool("d", false, "Log Level Debug")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400178 useAuthentication = flag.Bool("a", false, "Use Authentication")
179 useSsl = flag.Bool("s", false, "Use SSL")
180 certDirectory = flag.String("cert_dir", "cert", "Directory where key files exist")
181 listenAddress := flag.String("listenAddress", "localhost", "IP Address to listen on")
182 grpcPort := flag.String("grpc_port", "7777", "Port to listen for GRPC")
183 restPort := flag.String("rest_port", "7778", "Port to listen for Rest Server")
184 logFile := flag.String("log_file", "AbstractOLT.log", "Name of the LogFile to write to")
185 h := flag.Bool("h", false, "Show usage")
186 help := flag.Bool("help", false, "Show usage")
donNewtonAlphaaf229742018-09-19 13:22:00 -0400187 dummy := flag.Bool("dummy", false, "Run in dummy mode where YAML is not sent to XOS")
Author Namea594e632018-08-10 11:33:58 -0400188
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400189 flag.Parse()
donNewtonAlphaaf229742018-09-19 13:22:00 -0400190 settings.SetDummy(*dummy)
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400191
192 if *help || *h {
193 var usage = `./AbstractOLT -d [default false] : Runs in Debug mode
194Params:
195 -s [default false] -cert_dir [default $WORKING_DIR/cert] DIR : Runs in SSL mode with server.crt and server.key found in DIR
196 -a [default false] : Run in Authentication mode currently very basic
197 -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
198 -log_file [default $WORKING_DIR/AbstractOLT.log] LOG_FILE
199 -h(elp) print this usage
200`
201 fmt.Println(usage)
202 return
203 }
204 settings.SetDebug(*debugPtr)
205 fmt.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
206 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
207
208 file, err := os.OpenFile(*logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
Author Namea594e632018-08-10 11:33:58 -0400209 if err != nil {
210 log.Fatalln("Failed to open log file", file, ":", err)
211 }
212 log.SetOutput(file)
213 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
donNewtonAlphaaf229742018-09-19 13:22:00 -0400214 if *dummy {
215 fmt.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
216 log.Println("RUNNING IN DUMMY MODE NO YAML WILL BE SENT TO XOS")
217 }
Author Namea594e632018-08-10 11:33:58 -0400218 log.Printf("Setting Debug to %t\n", settings.GetDebug())
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400219 if settings.GetDebug() {
220 log.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
221 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
222 }
Author Namea594e632018-08-10 11:33:58 -0400223
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400224 grpcAddress := fmt.Sprintf("%s:%s", *listenAddress, *grpcPort)
225 restAddress := fmt.Sprintf("%s:%s", *listenAddress, *restPort)
226
227 certFile := fmt.Sprintf("%s/server.crt", *certDirectory)
228 keyFile := fmt.Sprintf("%s/server.key", *certDirectory)
Author Namea594e632018-08-10 11:33:58 -0400229
230 // fire the gRPC server in a goroutine
231 go func() {
232 err := startGRPCServer(grpcAddress, certFile, keyFile)
233 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400234 log.Printf("failed to start gRPC server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400235 }
236 }()
237
238 // fire the REST server in a goroutine
239 go func() {
240 err := startRESTServer(restAddress, grpcAddress, certFile)
241 if err != nil {
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400242 log.Printf("failed to start REST server: %s", err)
Author Namea594e632018-08-10 11:33:58 -0400243 }
244 }()
245
246 // infinite loop
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400247 files, err := ioutil.ReadDir("backup")
248 if err != nil {
249 log.Fatal(err)
250 }
251 for _, file := range files {
252 fmt.Println(file.Name())
253 chassisHolder := models.ChassisHolder{}
donNewtonAlphab8f30752018-10-04 11:57:41 -0400254 if file.Name() != "BackupPlaceHolder" {
255 fileName := fmt.Sprintf("backup/%s", file.Name())
256 json, _ := ioutil.ReadFile(fileName)
257 err := chassisHolder.Deserialize([]byte(json))
258 if err != nil {
259 fmt.Printf("Deserialize threw an error %v\n", err)
260 }
261 chassisMap := models.GetChassisMap()
262 (*chassisMap)[file.Name()] = &chassisHolder
263 } else {
264 fmt.Println("Ignoring BackupPlaceHolder")
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400265 }
donNewtonAlphae7ab5b92018-09-27 15:09:14 -0400266 }
267
Author Namea594e632018-08-10 11:33:58 -0400268 log.Printf("Entering infinite loop")
269 select {}
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400270 //TODO publish periodic stats etc
Author Namea594e632018-08-10 11:33:58 -0400271 fmt.Println("AbstractOLT")
272}