blob: fbe7880f409d5bc8bf43a1f15d91a1c20410a2de [file] [log] [blame]
cuilin20187b2a8c32019-03-26 19:52:28 -07001/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002* Copyright 2018-2024 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
Joey Armstrong87b55f72023-06-27 12:12:53 -040017// Package main invokes the application
cuilin20187b2a8c32019-03-26 19:52:28 -070018package main
19
20import (
21 "context"
22 "errors"
23 "fmt"
kdarapu381c6902019-07-31 18:23:16 +053024 "os"
25 "os/signal"
kdarapu381c6902019-07-31 18:23:16 +053026 "syscall"
27 "time"
28
Abhay Kumar9bcfeb22024-07-12 09:14:25 +053029 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
30 codes "google.golang.org/grpc/codes"
31
khenaidoo106c61a2021-08-11 18:05:46 -040032 conf "github.com/opencord/voltha-lib-go/v7/pkg/config"
33 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
34 "github.com/opencord/voltha-lib-go/v7/pkg/events"
35 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
36 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
37 "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
38 "github.com/opencord/voltha-lib-go/v7/pkg/log"
39 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
40 "github.com/opencord/voltha-lib-go/v7/pkg/version"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
42 ac "github.com/opencord/voltha-openolt-adapter/internal/pkg/core"
khenaidoodc2116e2021-10-19 17:33:19 -040043 "github.com/opencord/voltha-protos/v5/go/adapter_service"
44 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
45 "github.com/opencord/voltha-protos/v5/go/core_service"
khenaidoodc2116e2021-10-19 17:33:19 -040046 "github.com/opencord/voltha-protos/v5/go/olt_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-protos/v5/go/voltha"
48 "google.golang.org/grpc"
49)
50
51const (
52 clusterMessagingService = "cluster-message-service"
53 oltAdapterService = "olt-adapter-service"
54 kvService = "kv-service"
55 coreService = "core-service"
Akash Kankanala041a2122024-10-16 15:49:22 +053056 etcdStoreName = "etcd"
cuilin20187b2a8c32019-03-26 19:52:28 -070057)
58
59type adapter struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053060 kafkaClient kafka.Client
61 kvClient kvstore.Client
62 eventProxy eventif.EventProxy
khenaidooefff76e2021-12-15 16:51:30 -050063 config *config.AdapterFlags
64 grpcServer *vgrpc.GrpcServer
65 oltAdapter *ac.OpenOLT
66 oltInterAdapter *ac.OpenOLTInterAdapter
khenaidooefff76e2021-12-15 16:51:30 -050067 coreClient *vgrpc.Client
khenaidooefff76e2021-12-15 16:51:30 -050068 exitChannel chan int
Akash Kankanala041a2122024-10-16 15:49:22 +053069 instanceID string
70 halted bool
cuilin20187b2a8c32019-03-26 19:52:28 -070071}
72
cuilin20187b2a8c32019-03-26 19:52:28 -070073func newAdapter(cf *config.AdapterFlags) *adapter {
74 var a adapter
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 a.instanceID = cf.InstanceID
cuilin20187b2a8c32019-03-26 19:52:28 -070076 a.config = cf
77 a.halted = false
78 a.exitChannel = make(chan int, 1)
cuilin20187b2a8c32019-03-26 19:52:28 -070079 return &a
80}
81
82func (a *adapter) start(ctx context.Context) {
Neha Sharma96b7bf22020-06-15 10:37:32 +000083 logger.Info(ctx, "Starting Core Adapter components")
cuilin20187b2a8c32019-03-26 19:52:28 -070084 var err error
85
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000086 var p *probe.Probe
87 if value := ctx.Value(probe.ProbeContextKey); value != nil {
88 if _, ok := value.(*probe.Probe); ok {
89 p = value.(*probe.Probe)
90 p.RegisterService(
Neha Sharma96b7bf22020-06-15 10:37:32 +000091 ctx,
khenaidoo106c61a2021-08-11 18:05:46 -040092 clusterMessagingService,
93 kvService,
94 oltAdapterService,
95 coreService,
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000096 )
97 }
98 }
99
cuilin20187b2a8c32019-03-26 19:52:28 -0700100 // Setup KV Client
Neha Sharma96b7bf22020-06-15 10:37:32 +0000101 logger.Debugw(ctx, "create-kv-client", log.Fields{"kvstore": a.config.KVStoreType})
102 if err = a.setKVClient(ctx); err != nil {
103 logger.Fatalw(ctx, "error-setting-kv-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700104 }
105
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000106 if p != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400107 p.UpdateStatus(ctx, kvService, probe.ServiceStatusRunning)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000108 }
109
divyadesaia37f78b2020-02-07 12:41:22 +0000110 // Setup Log Config
Neha Sharma96b7bf22020-06-15 10:37:32 +0000111 cm := conf.NewConfigManager(ctx, a.kvClient, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800112
divyadesaid26f6b12020-03-19 06:30:28 +0000113 go conf.StartLogLevelConfigProcessing(cm, ctx)
Girish Kumar935f7af2020-08-18 11:59:42 +0000114 go conf.StartLogFeaturesConfigProcessing(cm, ctx)
divyadesaia37f78b2020-02-07 12:41:22 +0000115
cuilin20187b2a8c32019-03-26 19:52:28 -0700116 // Setup Kafka Client
khenaidoo106c61a2021-08-11 18:05:46 -0400117 if a.kafkaClient, err = newKafkaClient(ctx, "sarama", a.config.KafkaClusterAddress); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000118 logger.Fatalw(ctx, "Unsupported-common-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700119 }
120
khenaidoo106c61a2021-08-11 18:05:46 -0400121 // Start kafka communication with the broker
Akash Kankanala041a2122024-10-16 15:49:22 +0530122 if err = kafka.StartAndWaitUntilKafkaConnectionIsUp(ctx, a.kafkaClient, a.config.HeartbeatCheckInterval, clusterMessagingService); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400123 logger.Fatal(ctx, "unable-to-connect-to-kafka")
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000124 }
125
Devmalya Paulfb990a52019-07-09 10:01:49 -0400126 // Create the event proxy to post events to KAFKA
Himani Chawlacd407802020-12-10 12:08:59 +0530127 a.eventProxy = events.NewEventProxy(events.MsgClient(a.kafkaClient), events.MsgTopic(kafka.Topic{Name: a.config.EventTopic}))
khenaidoo106c61a2021-08-11 18:05:46 -0400128 go func() {
Akash Kankanala041a2122024-10-16 15:49:22 +0530129 if err = a.eventProxy.Start(); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400130 logger.Fatalw(ctx, "event-proxy-cannot-start", log.Fields{"error": err})
131 }
132 }()
133
134 // Create the Core client to handle requests to the Core. Note that the coreClient is an interface and needs to be
135 // cast to the appropriate grpc client by invoking GetCoreGrpcClient on the a.coreClient
khenaidoo27e7ac92021-12-08 14:43:09 -0500136 if a.coreClient, err = vgrpc.NewClient(
137 a.config.AdapterEndpoint,
138 a.config.CoreEndpoint,
khenaidooefff76e2021-12-15 16:51:30 -0500139 "core_service.CoreService",
khenaidoo27e7ac92021-12-08 14:43:09 -0500140 a.coreRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400141 logger.Fatal(ctx, "grpc-client-not-created")
142 }
143 // Start the core grpc client
nikesh.krishnan6dd882b2023-03-14 10:02:41 +0530144 retryCodes := []codes.Code{
145 codes.Unavailable, // server is currently unavailable
146 codes.DeadlineExceeded, // deadline for the operation was exceeded
147 }
nikesh.krishnan97e74d22023-06-28 13:54:01 +0530148 // the backoff function sets the wait time bw each grpc retries, if not set it will take the deafault value of 50ms which is too low, the jitter sets the rpc retry wait time to be in a range of[PerRPCRetryTimeout-0.2, PerRPCRetryTimeout+0.2]
149 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(a.config.PerRPCRetryTimeout, 0.2))
150 grpcRetryOptions := grpc_retry.UnaryClientInterceptor(grpc_retry.WithMax(a.config.MaxRetries), grpc_retry.WithPerRetryTimeout(a.config.PerRPCRetryTimeout), grpc_retry.WithCodes(retryCodes...), backoffCtxOption)
nikesh.krishnan6dd882b2023-03-14 10:02:41 +0530151 logger.Debug(ctx, "Configuration values", log.Fields{"RETRY": a.config.MaxRetries, "TIMEOUT": a.config.PerRPCRetryTimeout})
152 go a.coreClient.Start(ctx, getCoreServiceClientHandler, grpcRetryOptions)
Devmalya Paulfb990a52019-07-09 10:01:49 -0400153
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 // Create the open OLT adapter
khenaidoo106c61a2021-08-11 18:05:46 -0400155 if a.oltAdapter, err = a.startOpenOLT(ctx, a.coreClient, a.eventProxy, a.config, cm); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000156 logger.Fatalw(ctx, "error-starting-openolt", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700157 }
158
khenaidooefff76e2021-12-15 16:51:30 -0500159 // Create the open OLT Inter adapter adapter
160 if a.oltInterAdapter, err = a.startOpenOLTInterAdapter(ctx, a.oltAdapter); err != nil {
161 logger.Fatalw(ctx, "error-starting-openolt-inter-adapter", log.Fields{"error": err})
162 }
163
khenaidoo106c61a2021-08-11 18:05:46 -0400164 // Create and start the grpc server
165 a.grpcServer = vgrpc.NewGrpcServer(a.config.GrpcAddress, nil, false, p)
166
Akash Kankanala041a2122024-10-16 15:49:22 +0530167 // Register the adapter service
khenaidoo106c61a2021-08-11 18:05:46 -0400168 a.addAdapterService(ctx, a.grpcServer, a.oltAdapter)
169
Akash Kankanala041a2122024-10-16 15:49:22 +0530170 // Register the olt inter-adapter service
khenaidooefff76e2021-12-15 16:51:30 -0500171 a.addOltInterAdapterService(ctx, a.grpcServer, a.oltInterAdapter)
khenaidoo106c61a2021-08-11 18:05:46 -0400172
173 // Start the grpc server
174 go a.startGRPCService(ctx, a.grpcServer, oltAdapterService)
cuilin20187b2a8c32019-03-26 19:52:28 -0700175
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700176 // Register this adapter to the Core - retries indefinitely
khenaidoo106c61a2021-08-11 18:05:46 -0400177 if err = a.registerWithCore(ctx, coreService, -1); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000178 logger.Fatal(ctx, "error-registering-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700179 }
cbabu95f21522019-11-13 14:25:18 +0100180
cbabu116b73f2019-12-10 17:56:32 +0530181 // check the readiness and liveliness and update the probe status
182 a.checkServicesReadiness(ctx)
cbabu95f21522019-11-13 14:25:18 +0100183}
184
khenaidoo106c61a2021-08-11 18:05:46 -0400185// TODO: Any action the adapter needs to do following a Core restart?
186func (a *adapter) coreRestarted(ctx context.Context, endPoint string) error {
187 logger.Errorw(ctx, "core-restarted", log.Fields{"endpoint": endPoint})
188 return nil
189}
190
khenaidooefff76e2021-12-15 16:51:30 -0500191// getCoreServiceClientHandler is used to test whether the remote gRPC service is up
192func getCoreServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
193 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400194 return nil
195 }
khenaidooefff76e2021-12-15 16:51:30 -0500196 return core_service.NewCoreServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -0400197}
198
Joey Armstrong87b55f72023-06-27 12:12:53 -0400199/*
200*
cbabu95f21522019-11-13 14:25:18 +0100201This function checks the liveliness and readiness of the kakfa and kv-client services
202and update the status in the probe.
203*/
cbabu116b73f2019-12-10 17:56:32 +0530204func (a *adapter) checkServicesReadiness(ctx context.Context) {
205 // checks the kafka readiness
khenaidoo106c61a2021-08-11 18:05:46 -0400206 go kafka.MonitorKafkaReadiness(ctx, a.kafkaClient, a.config.LiveProbeInterval, a.config.NotLiveProbeInterval, clusterMessagingService)
cbabu116b73f2019-12-10 17:56:32 +0530207
208 // checks the kv-store readiness
209 go a.checkKvStoreReadiness(ctx)
210}
211
Joey Armstrong87b55f72023-06-27 12:12:53 -0400212/*
213*
cbabu116b73f2019-12-10 17:56:32 +0530214This function checks the liveliness and readiness of the kv-store service
215and update the status in the probe.
216*/
217func (a *adapter) checkKvStoreReadiness(ctx context.Context) {
218 // dividing the live probe interval by 2 to get updated status every 30s
219 timeout := a.config.LiveProbeInterval / 2
220 kvStoreChannel := make(chan bool, 1)
221
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700222 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
223 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
224 cancelFunc()
225
cbabu95f21522019-11-13 14:25:18 +0100226 for {
cbabu116b73f2019-12-10 17:56:32 +0530227 timeoutTimer := time.NewTimer(timeout)
228 select {
229 case liveliness := <-kvStoreChannel:
230 if !liveliness {
231 // kv-store not reachable or down, updating the status to not ready state
khenaidoo106c61a2021-08-11 18:05:46 -0400232 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusNotReady)
cbabu116b73f2019-12-10 17:56:32 +0530233 timeout = a.config.NotLiveProbeInterval
234 } else {
235 // kv-store is reachable , updating the status to running state
khenaidoo106c61a2021-08-11 18:05:46 -0400236 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusRunning)
cbabu116b73f2019-12-10 17:56:32 +0530237 timeout = a.config.LiveProbeInterval / 2
238 }
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700239
cbabu116b73f2019-12-10 17:56:32 +0530240 // Check if the timer has expired or not
241 if !timeoutTimer.Stop() {
242 <-timeoutTimer.C
243 }
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700244
cbabu116b73f2019-12-10 17:56:32 +0530245 case <-timeoutTimer.C:
Girish Kumarbeadc112020-02-26 18:41:02 +0000246 // Check the status of the kv-store. Use timeout of 2 seconds to avoid forever blocking
Neha Sharma96b7bf22020-06-15 10:37:32 +0000247 logger.Info(ctx, "kv-store liveliness-recheck")
Girish Kumarbeadc112020-02-26 18:41:02 +0000248 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
249
250 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
251 // Cleanup cancel func resources
252 cancelFunc()
cbabu95f21522019-11-13 14:25:18 +0100253 }
cbabu116b73f2019-12-10 17:56:32 +0530254 }
255}
256
npujarec5762e2020-01-01 14:08:48 +0530257func (a *adapter) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 // Stop leadership tracking
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700259 a.halted = true
cuilin20187b2a8c32019-03-26 19:52:28 -0700260
261 // send exit signal
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700262 a.exitChannel <- 0
cuilin20187b2a8c32019-03-26 19:52:28 -0700263
khenaidooefff76e2021-12-15 16:51:30 -0500264 // Stop all grpc processing
265 if err := a.oltAdapter.Stop(ctx); err != nil {
266 logger.Errorw(ctx, "failure-stopping-olt-adapter-service", log.Fields{"error": err, "adapter": a.config.AdapterName})
267 }
268 if err := a.oltInterAdapter.Stop(ctx); err != nil {
269 logger.Errorw(ctx, "failure-stopping-olt-inter-adapter-service", log.Fields{"error": err, "adapter": a.config.AdapterName})
270 }
271
cuilin20187b2a8c32019-03-26 19:52:28 -0700272 // Cleanup - applies only if we had a kvClient
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700273 if a.kvClient != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700274 // Release all reservations
npujarec5762e2020-01-01 14:08:48 +0530275 if err := a.kvClient.ReleaseAllReservations(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Infow(ctx, "fail-to-release-all-reservations", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700277 }
278 // Close the DB connection
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700279 go a.kvClient.Close(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700280 }
281
khenaidoo106c61a2021-08-11 18:05:46 -0400282 if a.eventProxy != nil {
283 a.eventProxy.Stop()
Scott Bakere701b862020-02-20 16:19:16 -0800284 }
285
khenaidoo106c61a2021-08-11 18:05:46 -0400286 if a.kafkaClient != nil {
287 a.kafkaClient.Stop(ctx)
288 }
289
290 // Stop core client
291 if a.coreClient != nil {
292 a.coreClient.Stop(ctx)
293 }
294
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700295 logger.Info(ctx, "main-stop-processing-complete")
296
khenaidoo106c61a2021-08-11 18:05:46 -0400297 // TODO: Stop child devices connections
298
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 // TODO: More cleanup
300}
301
Neha Sharma96b7bf22020-06-15 10:37:32 +0000302func newKVClient(ctx context.Context, storeType, address string, timeout time.Duration) (kvstore.Client, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700304 switch storeType {
Akash Kankanala041a2122024-10-16 15:49:22 +0530305 case etcdStoreName:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000306 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530307 case "redis":
308 return kvstore.NewRedisClient(address, timeout, false)
309 case "redis-sentinel":
310 return kvstore.NewRedisClient(address, timeout, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 }
312 return nil, errors.New("unsupported-kv-store")
313}
314
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315func newKafkaClient(ctx context.Context, clientType, address string) (kafka.Client, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000316 logger.Infow(ctx, "common-client-type", log.Fields{"client": clientType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700317 switch clientType {
318 case "sarama":
319 return kafka.NewSaramaClient(
Neha Sharma3f221ae2020-04-29 19:02:12 +0000320 kafka.Address(address),
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 kafka.ProducerReturnOnErrors(true),
322 kafka.ProducerReturnOnSuccess(true),
323 kafka.ProducerMaxRetries(6),
Abhilash S.L3b494632019-07-16 15:51:09 +0530324 kafka.ProducerRetryBackoff(time.Millisecond*30),
325 kafka.MetadatMaxRetries(15)), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700326 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700327
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 return nil, errors.New("unsupported-client-type")
329}
330
Neha Sharma96b7bf22020-06-15 10:37:32 +0000331func (a *adapter) setKVClient(ctx context.Context) error {
332 client, err := newKVClient(ctx, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
cuilin20187b2a8c32019-03-26 19:52:28 -0700333 if err != nil {
334 a.kvClient = nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700335 return err
336 }
337 a.kvClient = client
divyadesaia37f78b2020-02-07 12:41:22 +0000338
cuilin20187b2a8c32019-03-26 19:52:28 -0700339 return nil
340}
341
khenaidoo106c61a2021-08-11 18:05:46 -0400342// startGRPCService creates the grpc service handlers, registers it to the grpc server and starts the server
343func (a *adapter) startGRPCService(ctx context.Context, server *vgrpc.GrpcServer, serviceName string) {
344 logger.Infow(ctx, "starting-grpc-service", log.Fields{"service": serviceName})
345
346 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
347 logger.Infow(ctx, "grpc-service-started", log.Fields{"service": serviceName})
348
349 server.Start(ctx)
350 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusStopped)
cuilin20187b2a8c32019-03-26 19:52:28 -0700351}
352
khenaidoodc2116e2021-10-19 17:33:19 -0400353func (a *adapter) addAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler adapter_service.AdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400354 logger.Info(ctx, "adding-adapter-service")
355
356 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400357 adapter_service.RegisterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400358 })
359}
360
khenaidoodc2116e2021-10-19 17:33:19 -0400361func (a *adapter) addOltInterAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler olt_inter_adapter_service.OltInterAdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400362 logger.Info(ctx, "adding-olt-inter-adapter-service")
363
364 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400365 olt_inter_adapter_service.RegisterOltInterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400366 })
367}
368
369func (a *adapter) startOpenOLT(ctx context.Context, cc *vgrpc.Client, ep eventif.EventProxy,
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800370 cfg *config.AdapterFlags, cm *conf.ConfigManager) (*ac.OpenOLT, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Info(ctx, "starting-open-olt")
cuilin20187b2a8c32019-03-26 19:52:28 -0700372 var err error
khenaidoo106c61a2021-08-11 18:05:46 -0400373 sOLT := ac.NewOpenOLT(ctx, cc, ep, cfg, cm)
cuilin20187b2a8c32019-03-26 19:52:28 -0700374
375 if err = sOLT.Start(ctx); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700376 return nil, err
377 }
378
Neha Sharma96b7bf22020-06-15 10:37:32 +0000379 logger.Info(ctx, "open-olt-started")
cuilin20187b2a8c32019-03-26 19:52:28 -0700380 return sOLT, nil
381}
382
khenaidooefff76e2021-12-15 16:51:30 -0500383func (a *adapter) startOpenOLTInterAdapter(ctx context.Context, oo *ac.OpenOLT) (*ac.OpenOLTInterAdapter, error) {
384 logger.Info(ctx, "starting-open-olt-inter-adapter")
385 var err error
386 sOLTInterAdapter := ac.NewOpenOLTInterAdapter(oo)
387
388 if err = sOLTInterAdapter.Start(ctx); err != nil {
389 return nil, err
390 }
391
392 logger.Info(ctx, "open-olt-inter-adapter-started")
393 return sOLTInterAdapter, nil
394}
395
khenaidoo106c61a2021-08-11 18:05:46 -0400396func (a *adapter) registerWithCore(ctx context.Context, serviceName string, retries int) error {
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700397 adapterID := fmt.Sprintf("openolt_%d", a.config.CurrentReplica)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000398 logger.Infow(ctx, "registering-with-core", log.Fields{
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700399 "adapterID": adapterID,
400 "currentReplica": a.config.CurrentReplica,
401 "totalReplicas": a.config.TotalReplicas,
402 })
403 adapterDescription := &voltha.Adapter{
404 Id: adapterID, // Unique name for the device type
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400405 Vendor: "VOLTHA OpenOLT",
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700406 Version: version.VersionInfo.Version,
khenaidoo106c61a2021-08-11 18:05:46 -0400407 // The Endpoint refers to the address this service is listening on.
408 Endpoint: a.config.AdapterEndpoint,
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700409 Type: "openolt",
410 CurrentReplica: int32(a.config.CurrentReplica),
411 TotalReplicas: int32(a.config.TotalReplicas),
412 }
413 types := []*voltha.DeviceType{{
414 Id: "openolt",
khenaidoo106c61a2021-08-11 18:05:46 -0400415 AdapterType: "openolt", // Type of the adapter that handles device type
416 Adapter: "openolt", // Deprecated attribute
Girish Gowdru0c588b22019-04-23 23:24:56 -0400417 AcceptsBulkFlowUpdate: false, // Currently openolt adapter does not support bulk flow handling
418 AcceptsAddRemoveFlowUpdates: true}}
cuilin20187b2a8c32019-03-26 19:52:28 -0700419 deviceTypes := &voltha.DeviceTypes{Items: types}
420 count := 0
421 for {
khenaidoo106c61a2021-08-11 18:05:46 -0400422 gClient, err := a.coreClient.GetCoreServiceClient()
423 if gClient != nil {
khenaidoodc2116e2021-10-19 17:33:19 -0400424 if _, err = gClient.RegisterAdapter(log.WithSpanFromContext(context.TODO(), ctx), &ca.AdapterRegistration{
khenaidoo106c61a2021-08-11 18:05:46 -0400425 Adapter: adapterDescription,
426 DTypes: deviceTypes}); err == nil {
427 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700428 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 }
khenaidoo106c61a2021-08-11 18:05:46 -0400430 logger.Warnw(ctx, "registering-with-core-failed", log.Fields{"endpoint": a.config.CoreEndpoint, "error": err, "count": count, "gclient": gClient})
431 if retries == count {
432 return err
433 }
434 count++
435 // Take a nap before retrying
436 time.Sleep(2 * time.Second)
cuilin20187b2a8c32019-03-26 19:52:28 -0700437 }
khenaidoo106c61a2021-08-11 18:05:46 -0400438 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000439 logger.Info(ctx, "registered-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700440 return nil
441}
442
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443func waitForExit(ctx context.Context) int {
cuilin20187b2a8c32019-03-26 19:52:28 -0700444 signalChannel := make(chan os.Signal, 1)
445 signal.Notify(signalChannel,
446 syscall.SIGHUP,
447 syscall.SIGINT,
448 syscall.SIGTERM,
449 syscall.SIGQUIT)
450
451 exitChannel := make(chan int)
452
453 go func() {
454 s := <-signalChannel
455 switch s {
456 case syscall.SIGHUP,
457 syscall.SIGINT,
458 syscall.SIGTERM,
459 syscall.SIGQUIT:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Infow(ctx, "closing-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700461 exitChannel <- 0
462 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000463 logger.Infow(ctx, "unexpected-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700464 exitChannel <- 1
465 }
466 }()
467
468 code := <-exitChannel
469 return code
470}
471
472func printBanner() {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800473 fmt.Println(` ____ ____ _ _______ `)
474 fmt.Println(` / _ \ / __ \| | |__ __|`)
475 fmt.Println(` | | | |_ __ ___ _ __ | | | | | | | `)
476 fmt.Println(` | | | | '_ \ / _ \ '_ \ | | | | | | | `)
477 fmt.Println(` | |__| | |_) | __/ | | || |__| | |____| | `)
478 fmt.Println(` \____/| .__/ \___|_| |_| \____/|______|_| `)
479 fmt.Println(` | | `)
480 fmt.Println(` |_| `)
481 fmt.Println(` `)
cuilin20187b2a8c32019-03-26 19:52:28 -0700482}
483
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400484func printVersion() {
485 fmt.Println("VOLTHA OpenOLT Adapter")
486 fmt.Println(version.VersionInfo.String(" "))
487}
488
cuilin20187b2a8c32019-03-26 19:52:28 -0700489func main() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 ctx := context.Background()
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 start := time.Now()
492
493 cf := config.NewAdapterFlags()
494 cf.ParseCommandArguments()
495
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700496 // Setup logging
cuilin20187b2a8c32019-03-26 19:52:28 -0700497
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000498 logLevel, err := log.StringToLogLevel(cf.LogLevel)
499 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 logger.Fatalf(ctx, "Cannot setup logging, %s", err)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000501 }
Rohan Agrawal2488f192020-01-31 09:26:55 +0000502
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 // Setup default logger - applies for packages that do not have specific logger set
Akash Kankanala041a2122024-10-16 15:49:22 +0530504 if _, err = log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000505 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700506 }
507
508 // Update all loggers (provisionned via init) with a common field
Akash Kankanala041a2122024-10-16 15:49:22 +0530509 if err = log.UpdateAllLoggers(log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000510 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700511 }
512
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000513 log.SetAllLogLevel(logLevel)
Rohan Agrawal93bced32020-02-11 10:16:01 +0000514
Matteo Scandolo8f2b9572020-02-28 15:35:23 -0800515 realMain()
516
Kent Hagermane6ff1012020-07-14 15:07:53 -0400517 defer func() {
Akash Kankanala041a2122024-10-16 15:49:22 +0530518 err = log.CleanUp()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400519 if err != nil {
520 logger.Errorw(context.Background(), "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
521 }
522 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700523
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400524 // Print version / build information and exit
525 if cf.DisplayVersionOnly {
526 printVersion()
527 return
528 }
529
cuilin20187b2a8c32019-03-26 19:52:28 -0700530 // Print banner if specified
531 if cf.Banner {
532 printBanner()
533 }
534
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 logger.Infow(ctx, "config", log.Fields{"config": *cf})
cuilin20187b2a8c32019-03-26 19:52:28 -0700536
537 ctx, cancel := context.WithCancel(context.Background())
538 defer cancel()
539
540 ad := newAdapter(cf)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000541
542 p := &probe.Probe{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000543 go p.ListenAndServe(ctx, ad.config.ProbeAddress)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000544
545 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
546
Girish Kumar935f7af2020-08-18 11:59:42 +0000547 closer, err := log.GetGlobalLFM().InitTracingAndLogCorrelation(cf.TraceEnabled, cf.TraceAgentAddress, cf.LogCorrelationEnabled)
Girish Kumar11e15972020-06-15 14:51:10 +0000548 if err != nil {
549 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
550 } else {
551 defer log.TerminateTracing(closer)
552 }
553
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000554 go ad.start(probeCtx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700555
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 code := waitForExit(ctx)
557 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
cuilin20187b2a8c32019-03-26 19:52:28 -0700558
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700559 // Use context with cancel as etcd-client stop could take more time sometimes to stop slowing down container shutdown.
560 ctxWithCancel, cancelFunc := context.WithCancel(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700561 // Cleanup before leaving
Girish Gowdra4b48fa42022-06-01 18:10:08 -0700562 ad.stop(ctxWithCancel)
563 // Will halt any long-running stop routine gracefully
564 cancelFunc()
cuilin20187b2a8c32019-03-26 19:52:28 -0700565
566 elapsed := time.Since(start)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000567 logger.Infow(ctx, "run-time", log.Fields{"instanceId": ad.config.InstanceID, "time": elapsed / time.Second})
cuilin20187b2a8c32019-03-26 19:52:28 -0700568}
Joey Armstrong87b55f72023-06-27 12:12:53 -0400569
570// [EOF]