blob: 23221c6d7e84e0fff6b90ddcdcbda05a6378cd37 [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
29 "github.com/grpc-ecosystem/grpc-gateway/runtime"
Matteo Scandolo11006992019-08-28 11:29:46 -070030 "github.com/opencord/bbsim/api/bbsim"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020031 "github.com/opencord/bbsim/api/legacy"
Matteo Scandolo82c16d02019-09-24 09:34:32 -070032 "github.com/opencord/bbsim/internal/bbsim/api"
Matteo Scandolo11006992019-08-28 11:29:46 -070033 "github.com/opencord/bbsim/internal/bbsim/devices"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070034 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4747d292019-08-05 11:50:18 -070035 log "github.com/sirupsen/logrus"
Matteo Scandolo84f7d482019-08-08 19:00:47 -070036 "google.golang.org/grpc"
37 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070038)
39
Zdravko Bozakov681364d2019-11-10 14:28:46 +010040func startApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Matteo Scandolo84f7d482019-08-08 19:00:47 -070041 // TODO make configurable
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070042 address := "0.0.0.0:50070"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020043 log.Debugf("APIServer listening on: %v", address)
Matteo Scandolo84f7d482019-08-08 19:00:47 -070044 lis, err := net.Listen("tcp", address)
45 if err != nil {
46 log.Fatalf("APIServer failed to listen: %v", err)
47 }
48 grpcServer := grpc.NewServer()
Matteo Scandolo82c16d02019-09-24 09:34:32 -070049 bbsim.RegisterBBSimServer(grpcServer, api.BBSimServer{})
Matteo Scandolo84f7d482019-08-08 19:00:47 -070050
51 reflection.Register(grpcServer)
52
53 go grpcServer.Serve(lis)
Zdravko Bozakov681364d2019-11-10 14:28:46 +010054 go startApiRestServer(apiDoneChannel, group, address)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070055
Zdravko Bozakov2da76342019-10-21 09:47:35 +020056 select {
Zdravko Bozakov681364d2019-11-10 14:28:46 +010057 case <-apiDoneChannel:
58 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +020059 grpcServer.Stop()
60 log.Warnf("Stopping API gRPC server")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070061 }
62
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070063 group.Done()
Zdravko Bozakov2da76342019-10-21 09:47:35 +020064}
65
66// startApiRestServer method starts the REST server (grpc gateway) for BBSim.
Zdravko Bozakov681364d2019-11-10 14:28:46 +010067func startApiRestServer(apiDoneChannel chan bool, group *sync.WaitGroup, grpcAddress string) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +020068 ctx := context.Background()
69 ctx, cancel := context.WithCancel(ctx)
70 defer cancel()
71
72 // TODO make configurable
73 address := "0.0.0.0:50071"
74
75 mux := runtime.NewServeMux()
76 opts := []grpc.DialOption{grpc.WithInsecure()}
77
78 if err := bbsim.RegisterBBSimHandlerFromEndpoint(ctx, mux, grpcAddress, opts); err != nil {
79 log.Errorf("Could not register API server: %v", err)
80 return
81 }
82
83 s := &http.Server{Addr: address, Handler: mux}
84
85 go func() {
86 log.Infof("REST API server listening on %s ...", address)
87 if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
88 log.Errorf("Could not start API server: %v", err)
89 return
90 }
91 }()
92
93 select {
Zdravko Bozakov681364d2019-11-10 14:28:46 +010094 case <-apiDoneChannel:
Zdravko Bozakov2da76342019-10-21 09:47:35 +020095 log.Warnf("Stopping API REST server")
96 s.Shutdown(ctx)
97 }
98
99 group.Done()
100}
101
102// 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 +0100103func startLegacyApiServer(apiDoneChannel chan bool, group *sync.WaitGroup) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200104 // TODO make configurable
105 grpcAddress := "0.0.0.0:50072"
106 restAddress := "0.0.0.0:50073"
107
108 log.Debugf("Legacy APIServer listening on: %v", grpcAddress)
109 listener, err := net.Listen("tcp", grpcAddress)
110 if err != nil {
111 log.Fatalf("Legacy APIServer failed to listen: %v", err)
112 return
113 }
114 apiserver := grpc.NewServer()
115 legacy.RegisterBBSimServiceServer(apiserver, api.BBSimLegacyServer{})
116
117 go apiserver.Serve(listener)
118 // Start rest gateway for BBSim server
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100119 go api.StartRestGatewayService(apiDoneChannel, group, grpcAddress, restAddress)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200120
121 select {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100122 case <-apiDoneChannel:
123 // if the API channel is closed, stop the gRPC server
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200124 log.Warnf("Stopping legacy API gRPC server")
125 apiserver.Stop()
126 break
127
128 }
129
130 group.Done()
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700131}
132
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133func main() {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700134 options := common.GetBBSimOpts()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700136 common.SetLogLevel(log.StandardLogger(), options.LogLevel, options.LogCaller)
Matteo Scandolo2bf742a2019-10-01 11:33:34 -0700137
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700138 if *options.ProfileCpu != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700139 // start profiling
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700140 log.Infof("Creating profile file at: %s", *options.ProfileCpu)
141 f, err := os.Create(*options.ProfileCpu)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700142 if err != nil {
143 log.Fatal(err)
144 }
145 pprof.StartCPUProfile(f)
146 }
147
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 log.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149 "OltID": options.OltID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 "NumNniPerOlt": options.NumNniPerOlt,
151 "NumPonPerOlt": options.NumPonPerOlt,
152 "NumOnuPerPon": options.NumOnuPerPon,
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700153 "TotalOnus": options.NumPonPerOlt * options.NumOnuPerPon,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700154 "Auth": options.Auth,
155 "Dhcp": options.Dhcp,
Matteo Scandolo5e081b52019-11-21 14:34:25 -0800156 "Delay": options.Delay,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 }).Info("BroadBand Simulator is on")
158
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700159 // control channels, they are only closed when the goroutine needs to be terminated
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700160 apiDoneChannel := make(chan bool)
161
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100162 devices.CreateOLT(
Matteo Scandoloc1147092019-10-29 09:38:33 -0700163 options.OltID,
164 options.NumNniPerOlt,
165 options.NumPonPerOlt,
166 options.NumOnuPerPon,
167 options.STag,
168 options.CTagInit,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700169 options.Auth,
170 options.Dhcp,
Matteo Scandoloe33447a2019-10-31 12:38:23 -0700171 options.Delay,
Matteo Scandoloc1147092019-10-29 09:38:33 -0700172 false,
173 )
Matteo Scandoloe33447a2019-10-31 12:38:23 -0700174
Matteo Scandolo4747d292019-08-05 11:50:18 -0700175 log.Debugf("Created OLT with id: %d", options.OltID)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100176
177 sigs := make(chan os.Signal, 1)
178 // stop API servers on SIGTERM
179 signal.Notify(sigs, syscall.SIGTERM)
180
181 go func() {
182 <-sigs
183 close(apiDoneChannel)
184 }()
185
186 wg := sync.WaitGroup{}
187 wg.Add(4)
188
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700189 go startApiServer(apiDoneChannel, &wg)
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200190 go startLegacyApiServer(apiDoneChannel, &wg)
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700191 log.Debugf("Started APIService")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700192
193 wg.Wait()
194
195 defer func() {
196 log.Info("BroadBand Simulator is off")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700197 if *options.ProfileCpu != "" {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700198 log.Info("Stopping profiler")
199 pprof.StopCPUProfile()
200 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700201 }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700202}