blob: 48ac7b84a305c8ad4c642dc717b8804093613d2f [file] [log] [blame]
Elia Battistonc8d0d462022-02-22 16:30:51 +01001/*
2* Copyright 2022-present Open Networking Foundation
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 "context"
21 "fmt"
22 "os"
23 "os/signal"
Elia Battistonbe9edc12022-03-09 11:35:58 +010024 "sync"
Elia Battistonc8d0d462022-02-22 16:30:51 +010025 "syscall"
26 "time"
27
Elia Battistonbe9edc12022-03-09 11:35:58 +010028 "github.com/golang/protobuf/ptypes/empty"
Elia Battistonc8d0d462022-02-22 16:30:51 +010029 "github.com/opencord/voltha-lib-go/v7/pkg/log"
30 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
31 "github.com/opencord/voltha-lib-go/v7/pkg/version"
Elia Battistonac8d23f2022-03-14 17:54:56 +010032 "github.com/opencord/voltha-northbound-bbf-adapter/internal/clients"
Elia Battistonc8d0d462022-02-22 16:30:51 +010033 "github.com/opencord/voltha-northbound-bbf-adapter/internal/config"
Elia Battistonac8d23f2022-03-14 17:54:56 +010034 "github.com/opencord/voltha-northbound-bbf-adapter/internal/sysrepo"
Elia Battistonc8d0d462022-02-22 16:30:51 +010035)
36
Elia Battistonbe9edc12022-03-09 11:35:58 +010037//String for readiness probe services
Elia Battistonc8d0d462022-02-22 16:30:51 +010038const (
39 bbfAdapterService = "bbf-adapter-service"
Elia Battistonac8d23f2022-03-14 17:54:56 +010040 sysrepoService = "sysrepo"
Elia Battistonc8d0d462022-02-22 16:30:51 +010041)
42
Elia Battistonbe9edc12022-03-09 11:35:58 +010043type bbfAdapter struct {
44 conf *config.BBFAdapterConfig
45 volthaNbiClient *clients.VolthaNbiClient
46 oltAppClient *clients.OltAppClient
Elia Battistonac8d23f2022-03-14 17:54:56 +010047 sysrepoPlugin *sysrepo.SysrepoPlugin
Elia Battistonbe9edc12022-03-09 11:35:58 +010048}
49
50func newBbfAdapter(conf *config.BBFAdapterConfig) *bbfAdapter {
51 return &bbfAdapter{
52 conf: conf,
53 }
54}
55
56func (a *bbfAdapter) start(ctx context.Context, wg *sync.WaitGroup) {
57 var err error
58
59 //Connect to the voltha northbound api
60 a.volthaNbiClient = clients.NewVolthaNbiClient(a.conf.VolthaNbiEndpoint)
61 if err = a.volthaNbiClient.Connect(ctx, a.conf.TlsEnabled, a.conf.TlsVerify); err != nil {
62 logger.Fatalw(ctx, "failed-to-open-voltha-nbi-grpc-connection", log.Fields{"err": err})
63 } else {
64 probe.UpdateStatusFromContext(ctx, a.conf.VolthaNbiEndpoint, probe.ServiceStatusRunning)
65 }
66
67 //Check if the REST APIs of the olt app are reachable
68 a.oltAppClient = clients.NewOltAppClient(a.conf.OnosRestEndpoint, a.conf.OnosUser, a.conf.OnosPassword)
69 if err := a.oltAppClient.CheckConnection(ctx); err != nil {
70 logger.Fatalw(ctx, "failed-to-connect-to-onos-olt-app-api", log.Fields{"err": err})
71 } else {
72 probe.UpdateStatusFromContext(ctx, a.conf.OnosRestEndpoint, probe.ServiceStatusRunning)
73 }
74
Elia Battistonac8d23f2022-03-14 17:54:56 +010075 //Load sysrepo plugin
76 a.sysrepoPlugin, err = sysrepo.StartNewPlugin(ctx)
77 if err != nil {
78 logger.Fatalw(ctx, "failed-to-start-sysrepo-plugin", log.Fields{"err": err})
79 } else {
80 probe.UpdateStatusFromContext(ctx, sysrepoService, probe.ServiceStatusRunning)
81 }
82
Elia Battistonbe9edc12022-03-09 11:35:58 +010083 //Run the main logic of the BBF adapter
84
85 //Set the service as running, making the adapter finally ready
86 probe.UpdateStatusFromContext(ctx, bbfAdapterService, probe.ServiceStatusRunning)
87 logger.Info(ctx, "bbf-adapter-ready")
88
89loop:
90 for {
91 select {
92 case <-ctx.Done():
93 logger.Info(ctx, "stop-for-context-done")
94 break loop
95 case <-time.After(15 * time.Second):
96 //TODO: this is just to test functionality
97
98 //Make a request to voltha
99 devices, err := a.volthaNbiClient.Service.ListDevices(ctx, &empty.Empty{})
100 if err != nil {
101 logger.Errorw(ctx, "failed-to-list-devices", log.Fields{"err": err})
102 continue
103 }
104 logger.Debugw(ctx, "Got devices from VOLTHA", log.Fields{"devNum": len(devices.Items)})
105
106 //Make a request to Olt app
107 response, err := a.oltAppClient.GetStatus()
108 if err != nil {
109 logger.Errorw(ctx, "failed-to-get-status", log.Fields{
110 "err": err,
111 "reponse": response,
112 })
113 continue
114 } else {
115 logger.Debugw(ctx, "Got status from OltApp", log.Fields{"response": response})
116 }
117
118 logger.Warn(ctx, "BBF Adapter currently has no implemented logic.")
119 }
120 }
121
122 probe.UpdateStatusFromContext(ctx, bbfAdapterService, probe.ServiceStatusStopped)
123 wg.Done()
124}
125
126//Close all connections of the adapter
Elia Battistonac8d23f2022-03-14 17:54:56 +0100127func (a *bbfAdapter) cleanup(ctx context.Context) {
128 a.volthaNbiClient.Close(ctx)
129 err := a.sysrepoPlugin.Stop(ctx)
130 if err != nil {
131 logger.Errorw(ctx, "failed-to-stop-sysrepo-plugin", log.Fields{"err": err})
132 }
Elia Battistonbe9edc12022-03-09 11:35:58 +0100133}
134
Elia Battistonc8d0d462022-02-22 16:30:51 +0100135func printBanner() {
136 fmt.Println(" ____ ____ ______ _ _ ")
137 fmt.Println(" | _ \\| _ \\| ____| /\\ | | | | ")
138 fmt.Println(" | |_) | |_) | |__ / \\ __| | __ _ _ __ | |_ ___ _ __ ")
139 fmt.Println(" | _ <| _ <| __| / /\\ \\ / _` |/ _` | '_ \\| __/ _ \\ '__|")
140 fmt.Println(" | |_) | |_) | | / ____ \\ (_| | (_| | |_) | || __/ | ")
141 fmt.Println(" |____/|____/|_| /_/ \\_\\__,_|\\__,_| .__/ \\__\\___|_| ")
142 fmt.Println(" | | ")
143 fmt.Println(" |_| ")
144}
145
146func printVersion() {
147 fmt.Println("VOLTHA Northbound BBF Adapter")
148 fmt.Println(version.VersionInfo.String(" "))
149}
150
151func waitForExit(ctx context.Context) int {
152 signalChannel := make(chan os.Signal, 1)
153 signal.Notify(signalChannel,
154 syscall.SIGHUP,
155 syscall.SIGINT,
156 syscall.SIGTERM,
157 syscall.SIGQUIT)
158
159 exitChannel := make(chan int)
160
161 go func() {
162 s := <-signalChannel
163 switch s {
164 case syscall.SIGHUP,
165 syscall.SIGINT,
166 syscall.SIGTERM,
167 syscall.SIGQUIT:
168 logger.Infow(ctx, "closing-signal-received", log.Fields{"signal": s})
169 exitChannel <- 0
170 default:
171 logger.Infow(ctx, "unexpected-signal-received", log.Fields{"signal": s})
172 exitChannel <- 1
173 }
174 }()
175
176 code := <-exitChannel
177 return code
178}
179
180func main() {
Elia Battistonbe9edc12022-03-09 11:35:58 +0100181 ctx, cancelCtx := context.WithCancel(context.Background())
182
Elia Battistonc8d0d462022-02-22 16:30:51 +0100183 start := time.Now()
184
185 conf := config.LoadConfig(ctx)
186
187 //Logging
188 logLevel, err := log.StringToLogLevel(conf.LogLevel)
189 if err != nil {
190 logger.Fatalf(ctx, "Cannot setup logging, %s", err)
191 }
192
193 // Setup default logger - applies for packages that do not have specific logger set
194 if _, err := log.SetDefaultLogger(log.JSON, logLevel, log.Fields{}); err != nil {
195 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
196 }
197
198 // Update all loggers (provisionned via init) with a common field
199 if err := log.UpdateAllLoggers(log.Fields{}); err != nil {
200 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
201 }
202
203 log.SetAllLogLevel(logLevel)
204
205 defer func() {
206 err := log.CleanUp()
207 if err != nil {
208 logger.Errorw(context.Background(), "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
209 }
210 }()
211
212 // Print version and exit
213 if conf.PrintVersion {
214 printVersion()
215 return
216 }
217
218 // Print banner if specified
219 if conf.PrintBanner {
220 printBanner()
221 }
222
223 logger.Infow(ctx, "config", log.Fields{"config": *conf})
224
225 p := &probe.Probe{}
226 go p.ListenAndServe(ctx, conf.ProbeAddress)
227
Elia Battistonbe9edc12022-03-09 11:35:58 +0100228 //Register all services that will need to be initialized before considering the adapter ready
Elia Battistonc8d0d462022-02-22 16:30:51 +0100229 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
Elia Battistonbe9edc12022-03-09 11:35:58 +0100230 p.RegisterService(
231 ctx,
232 bbfAdapterService,
233 conf.VolthaNbiEndpoint,
234 conf.OnosRestEndpoint,
Elia Battistonac8d23f2022-03-14 17:54:56 +0100235 sysrepoService,
Elia Battistonbe9edc12022-03-09 11:35:58 +0100236 )
237
Elia Battistonc8d0d462022-02-22 16:30:51 +0100238 closer, err := log.GetGlobalLFM().InitTracingAndLogCorrelation(conf.TraceEnabled, conf.TraceAgentAddress, conf.LogCorrelationEnabled)
239 if err != nil {
240 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
241 } else {
242 defer log.TerminateTracing(closer)
243 }
244
Elia Battistonbe9edc12022-03-09 11:35:58 +0100245 adapter := newBbfAdapter(conf)
Elia Battistonc8d0d462022-02-22 16:30:51 +0100246
Elia Battistonbe9edc12022-03-09 11:35:58 +0100247 //Run the adapter
248 wg := &sync.WaitGroup{}
249 wg.Add(1)
250 go adapter.start(probeCtx, wg)
Elia Battistonac8d23f2022-03-14 17:54:56 +0100251 defer adapter.cleanup(probeCtx)
Elia Battistonc8d0d462022-02-22 16:30:51 +0100252
Elia Battistonbe9edc12022-03-09 11:35:58 +0100253 //Wait a signal to stop execution
Elia Battistonc8d0d462022-02-22 16:30:51 +0100254 code := waitForExit(ctx)
255 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
256
Elia Battistonbe9edc12022-03-09 11:35:58 +0100257 //Stop everything that waits for the context to be done
258 cancelCtx()
259 //Wait for the adapter logic to stop
260 wg.Wait()
261
Elia Battistonc8d0d462022-02-22 16:30:51 +0100262 elapsed := time.Since(start)
263 logger.Infow(ctx, "run-time", log.Fields{"time": elapsed.Seconds()})
264}