blob: 23a00ef08affe6e762e811943ffcad64a8f48cd8 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
Matteo Scandolo9f619492019-10-25 13:11:58 -07002* Copyright 2018-present Open Networking Foundation
Matteo Scandolo11006992019-08-28 11:29:46 -07003
Matteo Scandolo9f619492019-10-25 13:11:58 -07004* 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
Matteo Scandolo11006992019-08-28 11:29:46 -07007
Matteo Scandolo9f619492019-10-25 13:11:58 -07008* http://www.apache.org/licenses/LICENSE-2.0
Matteo Scandolo11006992019-08-28 11:29:46 -07009
Matteo Scandolo9f619492019-10-25 13:11:58 -070010* 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.
Matteo Scandolo11006992019-08-28 11:29:46 -070015 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package main
18
19import (
Zdravko Bozakov2da76342019-10-21 09:47:35 +020020 "context"
21 "net"
22 "net/http"
23 "os"
24 "os/signal"
25 "runtime/pprof"
26 "sync"
27 "syscall"
28
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000029 "github.com/opencord/bbsim/internal/bbsim/responders/webserver"
30
Shrey Baid64cda472020-04-24 18:58:18 +053031 "github.com/Shopify/sarama"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020032 "github.com/grpc-ecosystem/grpc-gateway/runtime"
Matteo Scandolo11006992019-08-28 11:29:46 -070033 "github.com/opencord/bbsim/api/bbsim"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020034 "github.com/opencord/bbsim/api/legacy"
Matteo Scandolo82c16d02019-09-24 09:34:32 -070035 "github.com/opencord/bbsim/internal/bbsim/api"
Matteo Scandolo11006992019-08-28 11:29:46 -070036 "github.com/opencord/bbsim/internal/bbsim/devices"
amit.ghosh258d14c2020-10-02 15:13:38 +020037 "github.com/opencord/bbsim/internal/bbsim/dmiserver"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070038 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4747d292019-08-05 11:50:18 -070039 log "github.com/sirupsen/logrus"
Matteo Scandolo84f7d482019-08-08 19:00:47 -070040 "google.golang.org/grpc"
41 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042)
43
Zdravko Bozakov681364d2019-11-10 14:28:46 +010044func startApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Matteo Scandolo4a036262020-08-17 15:56:13 -070045 address := common.Config.BBSim.ApiAddress
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010046 log.Debugf("APIServer listening on %v", address)
Matteo Scandolo84f7d482019-08-08 19:00:47 -070047 lis, err := net.Listen("tcp", address)
48 if err != nil {
49 log.Fatalf("APIServer failed to listen: %v", err)
50 }
51 grpcServer := grpc.NewServer()
Matteo Scandolo82c16d02019-09-24 09:34:32 -070052 bbsim.RegisterBBSimServer(grpcServer, api.BBSimServer{})
Matteo Scandolo84f7d482019-08-08 19:00:47 -070053
54 reflection.Register(grpcServer)
55
Shrey Baid688b4242020-07-10 20:40:10 +053056 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov681364d2019-11-10 14:28:46 +010057 go startApiRestServer(apiDoneChannel, group, address)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070058
Shrey Baid688b4242020-07-10 20:40:10 +053059 x := <-apiDoneChannel
60 if x {
Zdravko Bozakov681364d2019-11-10 14:28:46 +010061 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +020062 grpcServer.Stop()
63 log.Warnf("Stopping API gRPC server")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070064 }
65
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070066 group.Done()
Zdravko Bozakov2da76342019-10-21 09:47:35 +020067}
68
69// startApiRestServer method starts the REST server (grpc gateway) for BBSim.
Zdravko Bozakov681364d2019-11-10 14:28:46 +010070func startApiRestServer(apiDoneChannel chan bool, group *sync.WaitGroup, grpcAddress string) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +020071 ctx := context.Background()
72 ctx, cancel := context.WithCancel(ctx)
73 defer cancel()
74
Matteo Scandolo4a036262020-08-17 15:56:13 -070075 address := common.Config.BBSim.RestApiAddress
Zdravko Bozakov2da76342019-10-21 09:47:35 +020076
77 mux := runtime.NewServeMux()
78 opts := []grpc.DialOption{grpc.WithInsecure()}
79
80 if err := bbsim.RegisterBBSimHandlerFromEndpoint(ctx, mux, grpcAddress, opts); err != nil {
81 log.Errorf("Could not register API server: %v", err)
82 return
83 }
84
85 s := &http.Server{Addr: address, Handler: mux}
86
87 go func() {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +010088 log.Infof("REST API server listening on %s", address)
Zdravko Bozakov2da76342019-10-21 09:47:35 +020089 if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
90 log.Errorf("Could not start API server: %v", err)
91 return
92 }
93 }()
94
Shrey Baid688b4242020-07-10 20:40:10 +053095 x := <-apiDoneChannel
96 if x {
Zdravko Bozakov2da76342019-10-21 09:47:35 +020097 log.Warnf("Stopping API REST server")
Shrey Baid688b4242020-07-10 20:40:10 +053098 _ = s.Shutdown(ctx)
Zdravko Bozakov2da76342019-10-21 09:47:35 +020099 }
100
101 group.Done()
102}
103
104// This server aims to provide compatibility with the previous BBSim version. It is deprecated and will be removed in the future.
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100105func startLegacyApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106 grpcAddress := common.Config.BBSim.LegacyApiAddress
107 restAddress := common.Config.BBSim.LegacyRestApiAddress
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200108
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100109 log.Debugf("Legacy APIServer listening on %v", grpcAddress)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200110 listener, err := net.Listen("tcp", grpcAddress)
111 if err != nil {
112 log.Fatalf("Legacy APIServer failed to listen: %v", err)
113 return
114 }
115 apiserver := grpc.NewServer()
116 legacy.RegisterBBSimServiceServer(apiserver, api.BBSimLegacyServer{})
117
Shrey Baid688b4242020-07-10 20:40:10 +0530118 go func() { _ = apiserver.Serve(listener) }()
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200119 // Start rest gateway for BBSim server
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100120 go api.StartRestGatewayService(apiDoneChannel, group, grpcAddress, restAddress)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200121
Shrey Baid688b4242020-07-10 20:40:10 +0530122 x := <-apiDoneChannel
123 if x {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100124 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200125 log.Warnf("Stopping legacy API gRPC server")
126 apiserver.Stop()
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200127 }
128
129 group.Done()
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700130}
131
Matteo Scandolo4747d292019-08-05 11:50:18 -0700132func main() {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100133
Matteo Scandolo4a036262020-08-17 15:56:13 -0700134 common.LoadConfig()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135
Matteo Scandolo4a036262020-08-17 15:56:13 -0700136 common.SetLogLevel(log.StandardLogger(), common.Config.BBSim.LogLevel, common.Config.BBSim.LogCaller)
Matteo Scandolo2bf742a2019-10-01 11:33:34 -0700137
Matteo Scandolo4a036262020-08-17 15:56:13 -0700138 if *common.Config.BBSim.CpuProfile != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700139 // start profiling
Matteo Scandolo4a036262020-08-17 15:56:13 -0700140 log.Infof("Creating profile file at: %s", *common.Config.BBSim.CpuProfile)
141 f, err := os.Create(*common.Config.BBSim.CpuProfile)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700142 if err != nil {
143 log.Fatal(err)
144 }
Shrey Baid688b4242020-07-10 20:40:10 +0530145 _ = pprof.StartCPUProfile(f)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700146 }
147
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 log.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -0700149 "OltID": common.Config.Olt.ID,
150 "NumNniPerOlt": common.Config.Olt.NniPorts,
151 "NumPonPerOlt": common.Config.Olt.PonPorts,
152 "NumOnuPerPon": common.Config.Olt.OnusPonPort,
153 "TotalOnus": common.Config.Olt.PonPorts * common.Config.Olt.OnusPonPort,
154 "Delay": common.Config.BBSim.Delay,
155 "Events": common.Config.BBSim.Events,
156 "KafkaEventTopic": common.Config.BBSim.KafkaEventTopic,
157 "ControlledActivation": common.Config.BBSim.ControlledActivation,
158 "EnablePerf": common.Config.BBSim.EnablePerf,
159 "DhcpRetry": common.Config.BBSim.DhcpRetry,
160 "AuthRetry": common.Config.BBSim.AuthRetry,
Matteo Scandolo93566702020-09-30 15:19:27 -0700161 "OltRebootDelay": common.Config.Olt.OltRebootDelay,
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000162 "OmciResponseRate": common.Config.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700163 }).Info("BroadBand Simulator is on")
164
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700165 // control channels, they are only closed when the goroutine needs to be terminated
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700166 apiDoneChannel := make(chan bool)
167
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100168 olt := devices.CreateOLT(
Matteo Scandolo4a036262020-08-17 15:56:13 -0700169 *common.Config,
170 common.Services,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700171 false,
172 )
Matteo Scandoloe33447a2019-10-31 12:38:23 -0700173
Matteo Scandolo4a036262020-08-17 15:56:13 -0700174 log.Debugf("Created OLT with id: %d", common.Config.Olt.ID)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100175
176 sigs := make(chan os.Signal, 1)
177 // stop API servers on SIGTERM
178 signal.Notify(sigs, syscall.SIGTERM)
179
180 go func() {
181 <-sigs
182 close(apiDoneChannel)
183 }()
184
185 wg := sync.WaitGroup{}
186 wg.Add(4)
187
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700188 go startApiServer(apiDoneChannel, &wg)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200189 go startLegacyApiServer(apiDoneChannel, &wg)
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700190 log.Debugf("Started APIService")
Matteo Scandolo4a036262020-08-17 15:56:13 -0700191 if common.Config.BBSim.SadisServer {
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100192 wg.Add(1)
Matteo Scandolocedde462021-03-09 17:37:16 -0800193 go webserver.StartRestServer(olt, &wg)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100194 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700195
amit.ghosh258d14c2020-10-02 15:13:38 +0200196 dms, dmserr := dmiserver.StartDmiAPIServer()
197 if dmserr != nil {
198 log.Errorf("Failed to start Device Management Interface Server %v", dmserr)
199 }
200
Matteo Scandolo4a036262020-08-17 15:56:13 -0700201 if common.Config.BBSim.Events {
Pragya Arya324337e2020-02-20 14:35:08 +0530202 // initialize a publisher
Shrey Baid64cda472020-04-24 18:58:18 +0530203 if err := common.InitializePublisher(sarama.NewAsyncProducer, olt.ID); err == nil {
Pragya Arya324337e2020-02-20 14:35:08 +0530204 // start a go routine which will read from channel and publish on kafka
205 go common.KafkaPublisher(olt.EventChannel)
206 } else {
207 log.Errorf("Failed to start kafka publisher: %v", err)
208 }
209 }
210
Matteo Scandolo4747d292019-08-05 11:50:18 -0700211 wg.Wait()
212
213 defer func() {
214 log.Info("BroadBand Simulator is off")
amit.ghosh258d14c2020-10-02 15:13:38 +0200215
216 dms.Stop()
217
Matteo Scandolo4a036262020-08-17 15:56:13 -0700218 if *common.Config.BBSim.CpuProfile != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700219 log.Info("Stopping profiler")
220 pprof.StopCPUProfile()
221 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700222 }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700223}