blob: 9e8e9e52b0e36b53a17bea070a6539ae2596ae42 [file] [log] [blame]
cuilin20187b2a8c32019-03-26 19:52:28 -07001/*
Joey Armstrongf9bffdf2022-12-27 07:05:28 -05002* Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
cuilin20187b2a8c32019-03-26 19:52:28 -07003
cbabu116b73f2019-12-10 17:56:32 +05304* 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
cuilin20187b2a8c32019-03-26 19:52:28 -07007
cbabu116b73f2019-12-10 17:56:32 +05308* http://www.apache.org/licenses/LICENSE-2.0
cuilin20187b2a8c32019-03-26 19:52:28 -07009
cbabu116b73f2019-12-10 17:56:32 +053010* 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.
cuilin20187b2a8c32019-03-26 19:52:28 -070015 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
17//Package main invokes the application
cuilin20187b2a8c32019-03-26 19:52:28 -070018package main
19
20import (
21 "context"
22 "errors"
23 "fmt"
nikesh.krishnan6dd882b2023-03-14 10:02:41 +053024 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
25 codes "google.golang.org/grpc/codes"
kdarapu381c6902019-07-31 18:23:16 +053026 "os"
27 "os/signal"
kdarapu381c6902019-07-31 18:23:16 +053028 "syscall"
29 "time"
30
khenaidoo106c61a2021-08-11 18:05:46 -040031 conf "github.com/opencord/voltha-lib-go/v7/pkg/config"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
33 "github.com/opencord/voltha-lib-go/v7/pkg/events"
34 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
35 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
36 "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
37 "github.com/opencord/voltha-lib-go/v7/pkg/log"
38 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
39 "github.com/opencord/voltha-lib-go/v7/pkg/version"
Scott Bakerdbd960e2020-02-28 08:57:51 -080040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
41 ac "github.com/opencord/voltha-openolt-adapter/internal/pkg/core"
khenaidoodc2116e2021-10-19 17:33:19 -040042 "github.com/opencord/voltha-protos/v5/go/adapter_service"
43 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
44 "github.com/opencord/voltha-protos/v5/go/core_service"
khenaidoodc2116e2021-10-19 17:33:19 -040045 "github.com/opencord/voltha-protos/v5/go/olt_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040046 "github.com/opencord/voltha-protos/v5/go/voltha"
47 "google.golang.org/grpc"
48)
49
50const (
51 clusterMessagingService = "cluster-message-service"
52 oltAdapterService = "olt-adapter-service"
53 kvService = "kv-service"
54 coreService = "core-service"
cuilin20187b2a8c32019-03-26 19:52:28 -070055)
56
57type adapter struct {
khenaidooefff76e2021-12-15 16:51:30 -050058 instanceID string
59 config *config.AdapterFlags
60 grpcServer *vgrpc.GrpcServer
61 oltAdapter *ac.OpenOLT
62 oltInterAdapter *ac.OpenOLTInterAdapter
63 kafkaClient kafka.Client
64 kvClient kvstore.Client
65 coreClient *vgrpc.Client
66 eventProxy eventif.EventProxy
67 halted bool
68 exitChannel chan int
cuilin20187b2a8c32019-03-26 19:52:28 -070069}
70
cuilin20187b2a8c32019-03-26 19:52:28 -070071func newAdapter(cf *config.AdapterFlags) *adapter {
72 var a adapter
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070073 a.instanceID = cf.InstanceID
cuilin20187b2a8c32019-03-26 19:52:28 -070074 a.config = cf
75 a.halted = false
76 a.exitChannel = make(chan int, 1)
cuilin20187b2a8c32019-03-26 19:52:28 -070077 return &a
78}
79
80func (a *adapter) start(ctx context.Context) {
Neha Sharma96b7bf22020-06-15 10:37:32 +000081 logger.Info(ctx, "Starting Core Adapter components")
cuilin20187b2a8c32019-03-26 19:52:28 -070082 var err error
83
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000084 var p *probe.Probe
85 if value := ctx.Value(probe.ProbeContextKey); value != nil {
86 if _, ok := value.(*probe.Probe); ok {
87 p = value.(*probe.Probe)
88 p.RegisterService(
Neha Sharma96b7bf22020-06-15 10:37:32 +000089 ctx,
khenaidoo106c61a2021-08-11 18:05:46 -040090 clusterMessagingService,
91 kvService,
92 oltAdapterService,
93 coreService,
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000094 )
95 }
96 }
97
cuilin20187b2a8c32019-03-26 19:52:28 -070098 // Setup KV Client
Neha Sharma96b7bf22020-06-15 10:37:32 +000099 logger.Debugw(ctx, "create-kv-client", log.Fields{"kvstore": a.config.KVStoreType})
100 if err = a.setKVClient(ctx); err != nil {
101 logger.Fatalw(ctx, "error-setting-kv-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700102 }
103
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000104 if p != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400105 p.UpdateStatus(ctx, kvService, probe.ServiceStatusRunning)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000106 }
107
divyadesaia37f78b2020-02-07 12:41:22 +0000108 // Setup Log Config
Neha Sharma96b7bf22020-06-15 10:37:32 +0000109 cm := conf.NewConfigManager(ctx, a.kvClient, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800110
divyadesaid26f6b12020-03-19 06:30:28 +0000111 go conf.StartLogLevelConfigProcessing(cm, ctx)
Girish Kumar935f7af2020-08-18 11:59:42 +0000112 go conf.StartLogFeaturesConfigProcessing(cm, ctx)
divyadesaia37f78b2020-02-07 12:41:22 +0000113
cuilin20187b2a8c32019-03-26 19:52:28 -0700114 // Setup Kafka Client
khenaidoo106c61a2021-08-11 18:05:46 -0400115 if a.kafkaClient, err = newKafkaClient(ctx, "sarama", a.config.KafkaClusterAddress); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000116 logger.Fatalw(ctx, "Unsupported-common-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700117 }
118
khenaidoo106c61a2021-08-11 18:05:46 -0400119 // Start kafka communication with the broker
120 if err := kafka.StartAndWaitUntilKafkaConnectionIsUp(ctx, a.kafkaClient, a.config.HeartbeatCheckInterval, clusterMessagingService); err != nil {
121 logger.Fatal(ctx, "unable-to-connect-to-kafka")
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000122 }
123
Devmalya Paulfb990a52019-07-09 10:01:49 -0400124 // Create the event proxy to post events to KAFKA
Himani Chawlacd407802020-12-10 12:08:59 +0530125 a.eventProxy = events.NewEventProxy(events.MsgClient(a.kafkaClient), events.MsgTopic(kafka.Topic{Name: a.config.EventTopic}))
khenaidoo106c61a2021-08-11 18:05:46 -0400126 go func() {
127 if err := a.eventProxy.Start(); err != nil {
128 logger.Fatalw(ctx, "event-proxy-cannot-start", log.Fields{"error": err})
129 }
130 }()
131
132 // Create the Core client to handle requests to the Core. Note that the coreClient is an interface and needs to be
133 // cast to the appropriate grpc client by invoking GetCoreGrpcClient on the a.coreClient
khenaidoo27e7ac92021-12-08 14:43:09 -0500134 if a.coreClient, err = vgrpc.NewClient(
135 a.config.AdapterEndpoint,
136 a.config.CoreEndpoint,
khenaidooefff76e2021-12-15 16:51:30 -0500137 "core_service.CoreService",
khenaidoo27e7ac92021-12-08 14:43:09 -0500138 a.coreRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400139 logger.Fatal(ctx, "grpc-client-not-created")
140 }
141 // Start the core grpc client
nikesh.krishnan6dd882b2023-03-14 10:02:41 +0530142 retryCodes := []codes.Code{
143 codes.Unavailable, // server is currently unavailable
144 codes.DeadlineExceeded, // deadline for the operation was exceeded
145 }
146 grpcRetryOptions := grpc_retry.UnaryClientInterceptor(grpc_retry.WithMax(a.config.MaxRetries), grpc_retry.WithPerRetryTimeout(a.config.PerRPCRetryTimeout), grpc_retry.WithCodes(retryCodes...))
147 logger.Debug(ctx, "Configuration values", log.Fields{"RETRY": a.config.MaxRetries, "TIMEOUT": a.config.PerRPCRetryTimeout})
148 go a.coreClient.Start(ctx, getCoreServiceClientHandler, grpcRetryOptions)
Devmalya Paulfb990a52019-07-09 10:01:49 -0400149
cuilin20187b2a8c32019-03-26 19:52:28 -0700150 // Create the open OLT adapter
khenaidoo106c61a2021-08-11 18:05:46 -0400151 if a.oltAdapter, err = a.startOpenOLT(ctx, a.coreClient, a.eventProxy, a.config, cm); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000152 logger.Fatalw(ctx, "error-starting-openolt", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 }
154
khenaidooefff76e2021-12-15 16:51:30 -0500155 // Create the open OLT Inter adapter adapter
156 if a.oltInterAdapter, err = a.startOpenOLTInterAdapter(ctx, a.oltAdapter); err != nil {
157 logger.Fatalw(ctx, "error-starting-openolt-inter-adapter", log.Fields{"error": err})
158 }
159
khenaidoo106c61a2021-08-11 18:05:46 -0400160 // Create and start the grpc server
161 a.grpcServer = vgrpc.NewGrpcServer(a.config.GrpcAddress, nil, false, p)
162
163 //Register the adapter service
164 a.addAdapterService(ctx, a.grpcServer, a.oltAdapter)
165
166 //Register the olt inter-adapter service
khenaidooefff76e2021-12-15 16:51:30 -0500167 a.addOltInterAdapterService(ctx, a.grpcServer, a.oltInterAdapter)
khenaidoo106c61a2021-08-11 18:05:46 -0400168
169 // Start the grpc server
170 go a.startGRPCService(ctx, a.grpcServer, oltAdapterService)
cuilin20187b2a8c32019-03-26 19:52:28 -0700171
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700172 // Register this adapter to the Core - retries indefinitely
khenaidoo106c61a2021-08-11 18:05:46 -0400173 if err = a.registerWithCore(ctx, coreService, -1); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000174 logger.Fatal(ctx, "error-registering-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700175 }
cbabu95f21522019-11-13 14:25:18 +0100176
cbabu116b73f2019-12-10 17:56:32 +0530177 // check the readiness and liveliness and update the probe status
178 a.checkServicesReadiness(ctx)
cbabu95f21522019-11-13 14:25:18 +0100179}
180
khenaidoo106c61a2021-08-11 18:05:46 -0400181// TODO: Any action the adapter needs to do following a Core restart?
182func (a *adapter) coreRestarted(ctx context.Context, endPoint string) error {
183 logger.Errorw(ctx, "core-restarted", log.Fields{"endpoint": endPoint})
184 return nil
185}
186
khenaidooefff76e2021-12-15 16:51:30 -0500187// getCoreServiceClientHandler is used to test whether the remote gRPC service is up
188func getCoreServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
189 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400190 return nil
191 }
khenaidooefff76e2021-12-15 16:51:30 -0500192 return core_service.NewCoreServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -0400193}
194
cbabu95f21522019-11-13 14:25:18 +0100195/**
196This function checks the liveliness and readiness of the kakfa and kv-client services
197and update the status in the probe.
198*/
cbabu116b73f2019-12-10 17:56:32 +0530199func (a *adapter) checkServicesReadiness(ctx context.Context) {
200 // checks the kafka readiness
khenaidoo106c61a2021-08-11 18:05:46 -0400201 go kafka.MonitorKafkaReadiness(ctx, a.kafkaClient, a.config.LiveProbeInterval, a.config.NotLiveProbeInterval, clusterMessagingService)
cbabu116b73f2019-12-10 17:56:32 +0530202
203 // checks the kv-store readiness
204 go a.checkKvStoreReadiness(ctx)
205}
206
207/**
208This function checks the liveliness and readiness of the kv-store service
209and update the status in the probe.
210*/
211func (a *adapter) checkKvStoreReadiness(ctx context.Context) {
212 // dividing the live probe interval by 2 to get updated status every 30s
213 timeout := a.config.LiveProbeInterval / 2
214 kvStoreChannel := make(chan bool, 1)
215
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700216 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
217 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
218 cancelFunc()
219
cbabu95f21522019-11-13 14:25:18 +0100220 for {
cbabu116b73f2019-12-10 17:56:32 +0530221 timeoutTimer := time.NewTimer(timeout)
222 select {
223 case liveliness := <-kvStoreChannel:
224 if !liveliness {
225 // kv-store not reachable or down, updating the status to not ready state
khenaidoo106c61a2021-08-11 18:05:46 -0400226 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusNotReady)
cbabu116b73f2019-12-10 17:56:32 +0530227 timeout = a.config.NotLiveProbeInterval
228 } else {
229 // kv-store is reachable , updating the status to running state
khenaidoo106c61a2021-08-11 18:05:46 -0400230 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusRunning)
cbabu116b73f2019-12-10 17:56:32 +0530231 timeout = a.config.LiveProbeInterval / 2
232 }
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700233
cbabu116b73f2019-12-10 17:56:32 +0530234 // Check if the timer has expired or not
235 if !timeoutTimer.Stop() {
236 <-timeoutTimer.C
237 }
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700238
cbabu116b73f2019-12-10 17:56:32 +0530239 case <-timeoutTimer.C:
Girish Kumarbeadc112020-02-26 18:41:02 +0000240 // Check the status of the kv-store. Use timeout of 2 seconds to avoid forever blocking
Neha Sharma96b7bf22020-06-15 10:37:32 +0000241 logger.Info(ctx, "kv-store liveliness-recheck")
Girish Kumarbeadc112020-02-26 18:41:02 +0000242 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
243
244 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
245 // Cleanup cancel func resources
246 cancelFunc()
cbabu95f21522019-11-13 14:25:18 +0100247 }
cbabu116b73f2019-12-10 17:56:32 +0530248 }
249}
250
npujarec5762e2020-01-01 14:08:48 +0530251func (a *adapter) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700252 // Stop leadership tracking
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700253 a.halted = true
cuilin20187b2a8c32019-03-26 19:52:28 -0700254
255 // send exit signal
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700256 a.exitChannel <- 0
cuilin20187b2a8c32019-03-26 19:52:28 -0700257
khenaidooefff76e2021-12-15 16:51:30 -0500258 // Stop all grpc processing
259 if err := a.oltAdapter.Stop(ctx); err != nil {
260 logger.Errorw(ctx, "failure-stopping-olt-adapter-service", log.Fields{"error": err, "adapter": a.config.AdapterName})
261 }
262 if err := a.oltInterAdapter.Stop(ctx); err != nil {
263 logger.Errorw(ctx, "failure-stopping-olt-inter-adapter-service", log.Fields{"error": err, "adapter": a.config.AdapterName})
264 }
265
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 // Cleanup - applies only if we had a kvClient
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 if a.kvClient != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700268 // Release all reservations
npujarec5762e2020-01-01 14:08:48 +0530269 if err := a.kvClient.ReleaseAllReservations(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Infow(ctx, "fail-to-release-all-reservations", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700271 }
272 // Close the DB connection
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700273 go a.kvClient.Close(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700274 }
275
khenaidoo106c61a2021-08-11 18:05:46 -0400276 if a.eventProxy != nil {
277 a.eventProxy.Stop()
Scott Bakere701b862020-02-20 16:19:16 -0800278 }
279
khenaidoo106c61a2021-08-11 18:05:46 -0400280 if a.kafkaClient != nil {
281 a.kafkaClient.Stop(ctx)
282 }
283
284 // Stop core client
285 if a.coreClient != nil {
286 a.coreClient.Stop(ctx)
287 }
288
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700289 logger.Info(ctx, "main-stop-processing-complete")
290
khenaidoo106c61a2021-08-11 18:05:46 -0400291 // TODO: Stop child devices connections
292
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 // TODO: More cleanup
294}
295
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296func newKVClient(ctx context.Context, storeType, address string, timeout time.Duration) (kvstore.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700297
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 switch storeType {
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 case "etcd":
Neha Sharma96b7bf22020-06-15 10:37:32 +0000301 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
cuilin20187b2a8c32019-03-26 19:52:28 -0700302 }
303 return nil, errors.New("unsupported-kv-store")
304}
305
Neha Sharma96b7bf22020-06-15 10:37:32 +0000306func newKafkaClient(ctx context.Context, clientType, address string) (kafka.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700307
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308 logger.Infow(ctx, "common-client-type", log.Fields{"client": clientType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700309 switch clientType {
310 case "sarama":
311 return kafka.NewSaramaClient(
Neha Sharma3f221ae2020-04-29 19:02:12 +0000312 kafka.Address(address),
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 kafka.ProducerReturnOnErrors(true),
314 kafka.ProducerReturnOnSuccess(true),
315 kafka.ProducerMaxRetries(6),
Abhilash S.L3b494632019-07-16 15:51:09 +0530316 kafka.ProducerRetryBackoff(time.Millisecond*30),
317 kafka.MetadatMaxRetries(15)), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700318 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319
cuilin20187b2a8c32019-03-26 19:52:28 -0700320 return nil, errors.New("unsupported-client-type")
321}
322
Neha Sharma96b7bf22020-06-15 10:37:32 +0000323func (a *adapter) setKVClient(ctx context.Context) error {
324 client, err := newKVClient(ctx, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 if err != nil {
326 a.kvClient = nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700327 return err
328 }
329 a.kvClient = client
divyadesaia37f78b2020-02-07 12:41:22 +0000330
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 return nil
332}
333
khenaidoo106c61a2021-08-11 18:05:46 -0400334// startGRPCService creates the grpc service handlers, registers it to the grpc server and starts the server
335func (a *adapter) startGRPCService(ctx context.Context, server *vgrpc.GrpcServer, serviceName string) {
336 logger.Infow(ctx, "starting-grpc-service", log.Fields{"service": serviceName})
337
338 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
339 logger.Infow(ctx, "grpc-service-started", log.Fields{"service": serviceName})
340
341 server.Start(ctx)
342 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusStopped)
cuilin20187b2a8c32019-03-26 19:52:28 -0700343}
344
khenaidoodc2116e2021-10-19 17:33:19 -0400345func (a *adapter) addAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler adapter_service.AdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400346 logger.Info(ctx, "adding-adapter-service")
347
348 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400349 adapter_service.RegisterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400350 })
351}
352
khenaidoodc2116e2021-10-19 17:33:19 -0400353func (a *adapter) addOltInterAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler olt_inter_adapter_service.OltInterAdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400354 logger.Info(ctx, "adding-olt-inter-adapter-service")
355
356 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400357 olt_inter_adapter_service.RegisterOltInterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400358 })
359}
360
361func (a *adapter) startOpenOLT(ctx context.Context, cc *vgrpc.Client, ep eventif.EventProxy,
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800362 cfg *config.AdapterFlags, cm *conf.ConfigManager) (*ac.OpenOLT, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Info(ctx, "starting-open-olt")
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 var err error
khenaidoo106c61a2021-08-11 18:05:46 -0400365 sOLT := ac.NewOpenOLT(ctx, cc, ep, cfg, cm)
cuilin20187b2a8c32019-03-26 19:52:28 -0700366
367 if err = sOLT.Start(ctx); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700368 return nil, err
369 }
370
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Info(ctx, "open-olt-started")
cuilin20187b2a8c32019-03-26 19:52:28 -0700372 return sOLT, nil
373}
374
khenaidooefff76e2021-12-15 16:51:30 -0500375func (a *adapter) startOpenOLTInterAdapter(ctx context.Context, oo *ac.OpenOLT) (*ac.OpenOLTInterAdapter, error) {
376 logger.Info(ctx, "starting-open-olt-inter-adapter")
377 var err error
378 sOLTInterAdapter := ac.NewOpenOLTInterAdapter(oo)
379
380 if err = sOLTInterAdapter.Start(ctx); err != nil {
381 return nil, err
382 }
383
384 logger.Info(ctx, "open-olt-inter-adapter-started")
385 return sOLTInterAdapter, nil
386}
387
khenaidoo106c61a2021-08-11 18:05:46 -0400388func (a *adapter) registerWithCore(ctx context.Context, serviceName string, retries int) error {
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700389 adapterID := fmt.Sprintf("openolt_%d", a.config.CurrentReplica)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000390 logger.Infow(ctx, "registering-with-core", log.Fields{
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700391 "adapterID": adapterID,
392 "currentReplica": a.config.CurrentReplica,
393 "totalReplicas": a.config.TotalReplicas,
394 })
395 adapterDescription := &voltha.Adapter{
396 Id: adapterID, // Unique name for the device type
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400397 Vendor: "VOLTHA OpenOLT",
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700398 Version: version.VersionInfo.Version,
khenaidoo106c61a2021-08-11 18:05:46 -0400399 // The Endpoint refers to the address this service is listening on.
400 Endpoint: a.config.AdapterEndpoint,
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700401 Type: "openolt",
402 CurrentReplica: int32(a.config.CurrentReplica),
403 TotalReplicas: int32(a.config.TotalReplicas),
404 }
405 types := []*voltha.DeviceType{{
406 Id: "openolt",
khenaidoo106c61a2021-08-11 18:05:46 -0400407 AdapterType: "openolt", // Type of the adapter that handles device type
408 Adapter: "openolt", // Deprecated attribute
Girish Gowdru0c588b22019-04-23 23:24:56 -0400409 AcceptsBulkFlowUpdate: false, // Currently openolt adapter does not support bulk flow handling
410 AcceptsAddRemoveFlowUpdates: true}}
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 deviceTypes := &voltha.DeviceTypes{Items: types}
412 count := 0
413 for {
khenaidoo106c61a2021-08-11 18:05:46 -0400414 gClient, err := a.coreClient.GetCoreServiceClient()
415 if gClient != nil {
khenaidoodc2116e2021-10-19 17:33:19 -0400416 if _, err = gClient.RegisterAdapter(log.WithSpanFromContext(context.TODO(), ctx), &ca.AdapterRegistration{
khenaidoo106c61a2021-08-11 18:05:46 -0400417 Adapter: adapterDescription,
418 DTypes: deviceTypes}); err == nil {
419 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700420 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700421 }
khenaidoo106c61a2021-08-11 18:05:46 -0400422 logger.Warnw(ctx, "registering-with-core-failed", log.Fields{"endpoint": a.config.CoreEndpoint, "error": err, "count": count, "gclient": gClient})
423 if retries == count {
424 return err
425 }
426 count++
427 // Take a nap before retrying
428 time.Sleep(2 * time.Second)
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 }
khenaidoo106c61a2021-08-11 18:05:46 -0400430 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000431 logger.Info(ctx, "registered-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700432 return nil
433}
434
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435func waitForExit(ctx context.Context) int {
cuilin20187b2a8c32019-03-26 19:52:28 -0700436 signalChannel := make(chan os.Signal, 1)
437 signal.Notify(signalChannel,
438 syscall.SIGHUP,
439 syscall.SIGINT,
440 syscall.SIGTERM,
441 syscall.SIGQUIT)
442
443 exitChannel := make(chan int)
444
445 go func() {
446 s := <-signalChannel
447 switch s {
448 case syscall.SIGHUP,
449 syscall.SIGINT,
450 syscall.SIGTERM,
451 syscall.SIGQUIT:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000452 logger.Infow(ctx, "closing-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700453 exitChannel <- 0
454 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 logger.Infow(ctx, "unexpected-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700456 exitChannel <- 1
457 }
458 }()
459
460 code := <-exitChannel
461 return code
462}
463
464func printBanner() {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 fmt.Println(` ____ ____ _ _______ `)
466 fmt.Println(` / _ \ / __ \| | |__ __|`)
467 fmt.Println(` | | | |_ __ ___ _ __ | | | | | | | `)
468 fmt.Println(` | | | | '_ \ / _ \ '_ \ | | | | | | | `)
469 fmt.Println(` | |__| | |_) | __/ | | || |__| | |____| | `)
470 fmt.Println(` \____/| .__/ \___|_| |_| \____/|______|_| `)
471 fmt.Println(` | | `)
472 fmt.Println(` |_| `)
473 fmt.Println(` `)
cuilin20187b2a8c32019-03-26 19:52:28 -0700474}
475
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400476func printVersion() {
477 fmt.Println("VOLTHA OpenOLT Adapter")
478 fmt.Println(version.VersionInfo.String(" "))
479}
480
cuilin20187b2a8c32019-03-26 19:52:28 -0700481func main() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 ctx := context.Background()
cuilin20187b2a8c32019-03-26 19:52:28 -0700483 start := time.Now()
484
485 cf := config.NewAdapterFlags()
486 cf.ParseCommandArguments()
487
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 // Setup logging
cuilin20187b2a8c32019-03-26 19:52:28 -0700489
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000490 logLevel, err := log.StringToLogLevel(cf.LogLevel)
491 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000492 logger.Fatalf(ctx, "Cannot setup logging, %s", err)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000493 }
Rohan Agrawal2488f192020-01-31 09:26:55 +0000494
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 // Setup default logger - applies for packages that do not have specific logger set
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000496 if _, err := log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000497 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700498 }
499
500 // Update all loggers (provisionned via init) with a common field
Hardik Windlassb9c869b2019-10-10 08:34:32 +0000501 if err := log.UpdateAllLoggers(log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000502 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700503 }
504
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000505 log.SetAllLogLevel(logLevel)
Rohan Agrawal93bced32020-02-11 10:16:01 +0000506
Matteo Scandolo8f2b9572020-02-28 15:35:23 -0800507 realMain()
508
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509 defer func() {
510 err := log.CleanUp()
511 if err != nil {
512 logger.Errorw(context.Background(), "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
513 }
514 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700515
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400516 // Print version / build information and exit
517 if cf.DisplayVersionOnly {
518 printVersion()
519 return
520 }
521
cuilin20187b2a8c32019-03-26 19:52:28 -0700522 // Print banner if specified
523 if cf.Banner {
524 printBanner()
525 }
526
Neha Sharma96b7bf22020-06-15 10:37:32 +0000527 logger.Infow(ctx, "config", log.Fields{"config": *cf})
cuilin20187b2a8c32019-03-26 19:52:28 -0700528
529 ctx, cancel := context.WithCancel(context.Background())
530 defer cancel()
531
532 ad := newAdapter(cf)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000533
534 p := &probe.Probe{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 go p.ListenAndServe(ctx, ad.config.ProbeAddress)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000536
537 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
538
Girish Kumar935f7af2020-08-18 11:59:42 +0000539 closer, err := log.GetGlobalLFM().InitTracingAndLogCorrelation(cf.TraceEnabled, cf.TraceAgentAddress, cf.LogCorrelationEnabled)
Girish Kumar11e15972020-06-15 14:51:10 +0000540 if err != nil {
541 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
542 } else {
543 defer log.TerminateTracing(closer)
544 }
545
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000546 go ad.start(probeCtx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700547
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 code := waitForExit(ctx)
549 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
cuilin20187b2a8c32019-03-26 19:52:28 -0700550
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700551 // Use context with cancel as etcd-client stop could take more time sometimes to stop slowing down container shutdown.
552 ctxWithCancel, cancelFunc := context.WithCancel(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700553 // Cleanup before leaving
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700554 ad.stop(ctxWithCancel)
555 // Will halt any long-running stop routine gracefully
556 cancelFunc()
cuilin20187b2a8c32019-03-26 19:52:28 -0700557
558 elapsed := time.Since(start)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000559 logger.Infow(ctx, "run-time", log.Fields{"instanceId": ad.config.InstanceID, "time": elapsed / time.Second})
cuilin20187b2a8c32019-03-26 19:52:28 -0700560}