Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 1 | /* |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 2 | * Copyright 2018-present Open Networking Foundation |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 3 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 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 |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 7 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 9 | |
Matteo Scandolo | 9f61949 | 2019-10-25 13:11:58 -0700 | [diff] [blame] | 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. |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 17 | package main |
| 18 | |
| 19 | import ( |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 20 | "context" |
| 21 | "net" |
| 22 | "net/http" |
| 23 | "os" |
| 24 | "os/signal" |
| 25 | "runtime/pprof" |
| 26 | "sync" |
| 27 | "syscall" |
| 28 | |
Holger Hildebrandt | c10bab1 | 2021-04-27 09:23:48 +0000 | [diff] [blame] | 29 | "github.com/opencord/bbsim/internal/bbsim/responders/webserver" |
| 30 | |
Shrey Baid | 64cda47 | 2020-04-24 18:58:18 +0530 | [diff] [blame] | 31 | "github.com/Shopify/sarama" |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 32 | "github.com/grpc-ecosystem/grpc-gateway/runtime" |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 33 | "github.com/opencord/bbsim/api/bbsim" |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 34 | "github.com/opencord/bbsim/api/legacy" |
Matteo Scandolo | 82c16d0 | 2019-09-24 09:34:32 -0700 | [diff] [blame] | 35 | "github.com/opencord/bbsim/internal/bbsim/api" |
Matteo Scandolo | 1100699 | 2019-08-28 11:29:46 -0700 | [diff] [blame] | 36 | "github.com/opencord/bbsim/internal/bbsim/devices" |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame] | 37 | "github.com/opencord/bbsim/internal/bbsim/dmiserver" |
Matteo Scandolo | 40e067f | 2019-10-16 16:59:41 -0700 | [diff] [blame] | 38 | "github.com/opencord/bbsim/internal/common" |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 39 | log "github.com/sirupsen/logrus" |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 40 | "google.golang.org/grpc" |
| 41 | "google.golang.org/grpc/reflection" |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 42 | ) |
| 43 | |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 44 | func startApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) { |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 45 | address := common.Config.BBSim.ApiAddress |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 46 | log.Debugf("APIServer listening on %v", address) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 47 | 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 Scandolo | 82c16d0 | 2019-09-24 09:34:32 -0700 | [diff] [blame] | 52 | bbsim.RegisterBBSimServer(grpcServer, api.BBSimServer{}) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 53 | |
| 54 | reflection.Register(grpcServer) |
| 55 | |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 56 | go func() { _ = grpcServer.Serve(lis) }() |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 57 | go startApiRestServer(apiDoneChannel, group, address) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 58 | |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 59 | x := <-apiDoneChannel |
| 60 | if x { |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 61 | // if the API channel is closed, stop the gRPC server |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 62 | grpcServer.Stop() |
| 63 | log.Warnf("Stopping API gRPC server") |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 64 | } |
| 65 | |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 66 | group.Done() |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | // startApiRestServer method starts the REST server (grpc gateway) for BBSim. |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 70 | func startApiRestServer(apiDoneChannel chan bool, group *sync.WaitGroup, grpcAddress string) { |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 71 | ctx := context.Background() |
| 72 | ctx, cancel := context.WithCancel(ctx) |
| 73 | defer cancel() |
| 74 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 75 | address := common.Config.BBSim.RestApiAddress |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 76 | |
| 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 Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 88 | log.Infof("REST API server listening on %s", address) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 89 | 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 Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 95 | x := <-apiDoneChannel |
| 96 | if x { |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 97 | log.Warnf("Stopping API REST server") |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 98 | _ = s.Shutdown(ctx) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 99 | } |
| 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 Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 105 | func startLegacyApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) { |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 106 | grpcAddress := common.Config.BBSim.LegacyApiAddress |
| 107 | restAddress := common.Config.BBSim.LegacyRestApiAddress |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 108 | |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 109 | log.Debugf("Legacy APIServer listening on %v", grpcAddress) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 110 | 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 Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 118 | go func() { _ = apiserver.Serve(listener) }() |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 119 | // Start rest gateway for BBSim server |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 120 | go api.StartRestGatewayService(apiDoneChannel, group, grpcAddress, restAddress) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 121 | |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 122 | x := <-apiDoneChannel |
| 123 | if x { |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 124 | // if the API channel is closed, stop the gRPC server |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 125 | log.Warnf("Stopping legacy API gRPC server") |
| 126 | apiserver.Stop() |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | group.Done() |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 130 | } |
| 131 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 132 | func main() { |
Zdravko Bozakov | 3ddb245 | 2019-11-29 14:33:41 +0100 | [diff] [blame] | 133 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 134 | common.LoadConfig() |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 135 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 136 | common.SetLogLevel(log.StandardLogger(), common.Config.BBSim.LogLevel, common.Config.BBSim.LogCaller) |
Matteo Scandolo | 2bf742a | 2019-10-01 11:33:34 -0700 | [diff] [blame] | 137 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 138 | if *common.Config.BBSim.CpuProfile != "" { |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 139 | // start profiling |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 140 | log.Infof("Creating profile file at: %s", *common.Config.BBSim.CpuProfile) |
| 141 | f, err := os.Create(*common.Config.BBSim.CpuProfile) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 142 | if err != nil { |
| 143 | log.Fatal(err) |
| 144 | } |
Shrey Baid | 688b424 | 2020-07-10 20:40:10 +0530 | [diff] [blame] | 145 | _ = pprof.StartCPUProfile(f) |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 146 | } |
| 147 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 148 | log.WithFields(log.Fields{ |
Matteo Scandolo | cfedba4 | 2022-02-14 16:08:54 -0800 | [diff] [blame] | 149 | "OltID": common.Config.Olt.ID, |
| 150 | "NumNniPerOlt": common.Config.Olt.NniPorts, |
| 151 | "NumPonPerOlt": common.Config.Olt.PonPorts, |
| 152 | "NumOnuPerPon": common.Config.Olt.OnusPonPort, |
| 153 | "PonConfiguration": *common.PonsConfig, |
| 154 | "TotalOnus": common.Config.Olt.PonPorts * common.Config.Olt.OnusPonPort, |
Andrea Campanella | 6f5f355 | 2022-03-10 17:14:25 +0100 | [diff] [blame] | 155 | "NniDhcpTrapVid": common.Config.Olt.NniDhcpTrapVid, |
Matteo Scandolo | cfedba4 | 2022-02-14 16:08:54 -0800 | [diff] [blame] | 156 | "Delay": common.Config.BBSim.Delay, |
| 157 | "Events": common.Config.BBSim.Events, |
| 158 | "KafkaEventTopic": common.Config.BBSim.KafkaEventTopic, |
| 159 | "ControlledActivation": common.Config.BBSim.ControlledActivation, |
| 160 | "EnablePerf": common.Config.BBSim.EnablePerf, |
| 161 | "DhcpRetry": common.Config.BBSim.DhcpRetry, |
| 162 | "AuthRetry": common.Config.BBSim.AuthRetry, |
| 163 | "OltRebootDelay": common.Config.Olt.OltRebootDelay, |
| 164 | "OmciResponseRate": common.Config.Olt.OmciResponseRate, |
Matteo Scandolo | 7011fc9 | 2022-03-16 15:50:15 -0700 | [diff] [blame] | 165 | "injectOmciUnknownMe": common.Config.BBSim.InjectOmciUnknownMe, |
Matteo Scandolo | cfedba4 | 2022-02-14 16:08:54 -0800 | [diff] [blame] | 166 | "injectOmciUnknownAttributes": common.Config.BBSim.InjectOmciUnknownAttributes, |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 167 | }).Info("BroadBand Simulator is on") |
| 168 | |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 169 | // control channels, they are only closed when the goroutine needs to be terminated |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 170 | apiDoneChannel := make(chan bool) |
| 171 | |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 172 | olt := devices.CreateOLT( |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 173 | *common.Config, |
| 174 | common.Services, |
Matteo Scandolo | c114709 | 2019-10-29 09:38:33 -0700 | [diff] [blame] | 175 | false, |
| 176 | ) |
Matteo Scandolo | e33447a | 2019-10-31 12:38:23 -0700 | [diff] [blame] | 177 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 178 | log.Debugf("Created OLT with id: %d", common.Config.Olt.ID) |
Zdravko Bozakov | 681364d | 2019-11-10 14:28:46 +0100 | [diff] [blame] | 179 | |
| 180 | sigs := make(chan os.Signal, 1) |
| 181 | // stop API servers on SIGTERM |
| 182 | signal.Notify(sigs, syscall.SIGTERM) |
| 183 | |
| 184 | go func() { |
| 185 | <-sigs |
| 186 | close(apiDoneChannel) |
| 187 | }() |
| 188 | |
| 189 | wg := sync.WaitGroup{} |
| 190 | wg.Add(4) |
| 191 | |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 192 | go startApiServer(apiDoneChannel, &wg) |
Zdravko Bozakov | 2da7634 | 2019-10-21 09:47:35 +0200 | [diff] [blame] | 193 | go startLegacyApiServer(apiDoneChannel, &wg) |
Matteo Scandolo | 84f7d48 | 2019-08-08 19:00:47 -0700 | [diff] [blame] | 194 | log.Debugf("Started APIService") |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 195 | if common.Config.BBSim.SadisServer { |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 196 | wg.Add(1) |
Matteo Scandolo | cedde46 | 2021-03-09 17:37:16 -0800 | [diff] [blame] | 197 | go webserver.StartRestServer(olt, &wg) |
Zdravko Bozakov | 958d81c | 2019-12-13 22:09:48 +0100 | [diff] [blame] | 198 | } |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 199 | |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame] | 200 | dms, dmserr := dmiserver.StartDmiAPIServer() |
| 201 | if dmserr != nil { |
| 202 | log.Errorf("Failed to start Device Management Interface Server %v", dmserr) |
| 203 | } |
| 204 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 205 | if common.Config.BBSim.Events { |
Pragya Arya | 324337e | 2020-02-20 14:35:08 +0530 | [diff] [blame] | 206 | // initialize a publisher |
Shrey Baid | 64cda47 | 2020-04-24 18:58:18 +0530 | [diff] [blame] | 207 | if err := common.InitializePublisher(sarama.NewAsyncProducer, olt.ID); err == nil { |
Pragya Arya | 324337e | 2020-02-20 14:35:08 +0530 | [diff] [blame] | 208 | // start a go routine which will read from channel and publish on kafka |
| 209 | go common.KafkaPublisher(olt.EventChannel) |
| 210 | } else { |
| 211 | log.Errorf("Failed to start kafka publisher: %v", err) |
| 212 | } |
| 213 | } |
| 214 | |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 215 | wg.Wait() |
| 216 | |
| 217 | defer func() { |
| 218 | log.Info("BroadBand Simulator is off") |
amit.ghosh | 258d14c | 2020-10-02 15:13:38 +0200 | [diff] [blame] | 219 | |
| 220 | dms.Stop() |
| 221 | |
Matteo Scandolo | 4a03626 | 2020-08-17 15:56:13 -0700 | [diff] [blame] | 222 | if *common.Config.BBSim.CpuProfile != "" { |
Matteo Scandolo | 47e69bb | 2019-08-28 15:41:12 -0700 | [diff] [blame] | 223 | log.Info("Stopping profiler") |
| 224 | pprof.StopCPUProfile() |
| 225 | } |
Matteo Scandolo | 4747d29 | 2019-08-05 11:50:18 -0700 | [diff] [blame] | 226 | }() |
Matteo Scandolo | 4b3fc7e | 2019-09-17 16:49:54 -0700 | [diff] [blame] | 227 | } |