blob: 031651ff008678d2ba52c511f06298df909a188d [file] [log] [blame]
cuilin20187b2a8c32019-03-26 19:52:28 -07001/*
cbabu116b73f2019-12-10 17:56:32 +05302* Copyright 2018-present Open Networking Foundation
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"
kdarapu381c6902019-07-31 18:23:16 +053024 "os"
25 "os/signal"
kdarapu381c6902019-07-31 18:23:16 +053026 "syscall"
27 "time"
28
khenaidoo106c61a2021-08-11 18:05:46 -040029 "github.com/golang/protobuf/ptypes/empty"
30 conf "github.com/opencord/voltha-lib-go/v7/pkg/config"
31 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
32 "github.com/opencord/voltha-lib-go/v7/pkg/events"
33 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
34 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
35 "github.com/opencord/voltha-lib-go/v7/pkg/kafka"
36 "github.com/opencord/voltha-lib-go/v7/pkg/log"
37 "github.com/opencord/voltha-lib-go/v7/pkg/probe"
38 "github.com/opencord/voltha-lib-go/v7/pkg/version"
Scott Bakerdbd960e2020-02-28 08:57:51 -080039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
40 ac "github.com/opencord/voltha-openolt-adapter/internal/pkg/core"
khenaidoodc2116e2021-10-19 17:33:19 -040041 "github.com/opencord/voltha-protos/v5/go/adapter_service"
42 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
43 "github.com/opencord/voltha-protos/v5/go/core_service"
44 "github.com/opencord/voltha-protos/v5/go/health"
45 "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 {
khenaidoo106c61a2021-08-11 18:05:46 -040058 instanceID string
59 config *config.AdapterFlags
60 grpcServer *vgrpc.GrpcServer
61 oltAdapter *ac.OpenOLT
62 kafkaClient kafka.Client
63 kvClient kvstore.Client
64 coreClient *vgrpc.Client
65 eventProxy eventif.EventProxy
66 halted bool
67 exitChannel chan int
cuilin20187b2a8c32019-03-26 19:52:28 -070068}
69
cuilin20187b2a8c32019-03-26 19:52:28 -070070func newAdapter(cf *config.AdapterFlags) *adapter {
71 var a adapter
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 a.instanceID = cf.InstanceID
cuilin20187b2a8c32019-03-26 19:52:28 -070073 a.config = cf
74 a.halted = false
75 a.exitChannel = make(chan int, 1)
cuilin20187b2a8c32019-03-26 19:52:28 -070076 return &a
77}
78
79func (a *adapter) start(ctx context.Context) {
Neha Sharma96b7bf22020-06-15 10:37:32 +000080 logger.Info(ctx, "Starting Core Adapter components")
cuilin20187b2a8c32019-03-26 19:52:28 -070081 var err error
82
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000083 var p *probe.Probe
84 if value := ctx.Value(probe.ProbeContextKey); value != nil {
85 if _, ok := value.(*probe.Probe); ok {
86 p = value.(*probe.Probe)
87 p.RegisterService(
Neha Sharma96b7bf22020-06-15 10:37:32 +000088 ctx,
khenaidoo106c61a2021-08-11 18:05:46 -040089 clusterMessagingService,
90 kvService,
91 oltAdapterService,
92 coreService,
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000093 )
94 }
95 }
96
cuilin20187b2a8c32019-03-26 19:52:28 -070097 // Setup KV Client
Neha Sharma96b7bf22020-06-15 10:37:32 +000098 logger.Debugw(ctx, "create-kv-client", log.Fields{"kvstore": a.config.KVStoreType})
99 if err = a.setKVClient(ctx); err != nil {
100 logger.Fatalw(ctx, "error-setting-kv-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700101 }
102
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000103 if p != nil {
khenaidoo106c61a2021-08-11 18:05:46 -0400104 p.UpdateStatus(ctx, kvService, probe.ServiceStatusRunning)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000105 }
106
divyadesaia37f78b2020-02-07 12:41:22 +0000107 // Setup Log Config
Neha Sharma96b7bf22020-06-15 10:37:32 +0000108 cm := conf.NewConfigManager(ctx, a.kvClient, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800109
divyadesaid26f6b12020-03-19 06:30:28 +0000110 go conf.StartLogLevelConfigProcessing(cm, ctx)
Girish Kumar935f7af2020-08-18 11:59:42 +0000111 go conf.StartLogFeaturesConfigProcessing(cm, ctx)
divyadesaia37f78b2020-02-07 12:41:22 +0000112
cuilin20187b2a8c32019-03-26 19:52:28 -0700113 // Setup Kafka Client
khenaidoo106c61a2021-08-11 18:05:46 -0400114 if a.kafkaClient, err = newKafkaClient(ctx, "sarama", a.config.KafkaClusterAddress); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000115 logger.Fatalw(ctx, "Unsupported-common-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700116 }
117
khenaidoo106c61a2021-08-11 18:05:46 -0400118 // Start kafka communication with the broker
119 if err := kafka.StartAndWaitUntilKafkaConnectionIsUp(ctx, a.kafkaClient, a.config.HeartbeatCheckInterval, clusterMessagingService); err != nil {
120 logger.Fatal(ctx, "unable-to-connect-to-kafka")
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000121 }
122
Devmalya Paulfb990a52019-07-09 10:01:49 -0400123 // Create the event proxy to post events to KAFKA
Himani Chawlacd407802020-12-10 12:08:59 +0530124 a.eventProxy = events.NewEventProxy(events.MsgClient(a.kafkaClient), events.MsgTopic(kafka.Topic{Name: a.config.EventTopic}))
khenaidoo106c61a2021-08-11 18:05:46 -0400125 go func() {
126 if err := a.eventProxy.Start(); err != nil {
127 logger.Fatalw(ctx, "event-proxy-cannot-start", log.Fields{"error": err})
128 }
129 }()
130
131 // Create the Core client to handle requests to the Core. Note that the coreClient is an interface and needs to be
132 // cast to the appropriate grpc client by invoking GetCoreGrpcClient on the a.coreClient
133 if a.coreClient, err = vgrpc.NewClient(a.config.CoreEndpoint,
134 a.coreRestarted,
135 vgrpc.ActivityCheck(true)); err != nil {
136 logger.Fatal(ctx, "grpc-client-not-created")
137 }
138 // Start the core grpc client
139 go a.coreClient.Start(ctx, setAndTestCoreServiceHandler)
Devmalya Paulfb990a52019-07-09 10:01:49 -0400140
cuilin20187b2a8c32019-03-26 19:52:28 -0700141 // Create the open OLT adapter
khenaidoo106c61a2021-08-11 18:05:46 -0400142 if a.oltAdapter, err = a.startOpenOLT(ctx, a.coreClient, a.eventProxy, a.config, cm); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000143 logger.Fatalw(ctx, "error-starting-openolt", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700144 }
145
khenaidoo106c61a2021-08-11 18:05:46 -0400146 // Create and start the grpc server
147 a.grpcServer = vgrpc.NewGrpcServer(a.config.GrpcAddress, nil, false, p)
148
149 //Register the adapter service
150 a.addAdapterService(ctx, a.grpcServer, a.oltAdapter)
151
152 //Register the olt inter-adapter service
153 a.addOltInterAdapterService(ctx, a.grpcServer, a.oltAdapter)
154
155 // Start the grpc server
156 go a.startGRPCService(ctx, a.grpcServer, oltAdapterService)
cuilin20187b2a8c32019-03-26 19:52:28 -0700157
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158 // Register this adapter to the Core - retries indefinitely
khenaidoo106c61a2021-08-11 18:05:46 -0400159 if err = a.registerWithCore(ctx, coreService, -1); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000160 logger.Fatal(ctx, "error-registering-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700161 }
cbabu95f21522019-11-13 14:25:18 +0100162
cbabu116b73f2019-12-10 17:56:32 +0530163 // check the readiness and liveliness and update the probe status
164 a.checkServicesReadiness(ctx)
cbabu95f21522019-11-13 14:25:18 +0100165}
166
khenaidoo106c61a2021-08-11 18:05:46 -0400167// TODO: Any action the adapter needs to do following a Core restart?
168func (a *adapter) coreRestarted(ctx context.Context, endPoint string) error {
169 logger.Errorw(ctx, "core-restarted", log.Fields{"endpoint": endPoint})
170 return nil
171}
172
173// setAndTestCoreServiceHandler is used to test whether the remote gRPC service is up
174func setAndTestCoreServiceHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
khenaidoodc2116e2021-10-19 17:33:19 -0400175 svc := core_service.NewCoreServiceClient(conn)
176 if h, err := svc.GetHealthStatus(ctx, &empty.Empty{}); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -0400177 return nil
178 }
179 return svc
180}
181
cbabu95f21522019-11-13 14:25:18 +0100182/**
183This function checks the liveliness and readiness of the kakfa and kv-client services
184and update the status in the probe.
185*/
cbabu116b73f2019-12-10 17:56:32 +0530186func (a *adapter) checkServicesReadiness(ctx context.Context) {
187 // checks the kafka readiness
khenaidoo106c61a2021-08-11 18:05:46 -0400188 go kafka.MonitorKafkaReadiness(ctx, a.kafkaClient, a.config.LiveProbeInterval, a.config.NotLiveProbeInterval, clusterMessagingService)
cbabu116b73f2019-12-10 17:56:32 +0530189
190 // checks the kv-store readiness
191 go a.checkKvStoreReadiness(ctx)
192}
193
194/**
195This function checks the liveliness and readiness of the kv-store service
196and update the status in the probe.
197*/
198func (a *adapter) checkKvStoreReadiness(ctx context.Context) {
199 // dividing the live probe interval by 2 to get updated status every 30s
200 timeout := a.config.LiveProbeInterval / 2
201 kvStoreChannel := make(chan bool, 1)
202
203 // Default false to check the liveliness.
204 kvStoreChannel <- false
cbabu95f21522019-11-13 14:25:18 +0100205 for {
cbabu116b73f2019-12-10 17:56:32 +0530206 timeoutTimer := time.NewTimer(timeout)
207 select {
208 case liveliness := <-kvStoreChannel:
209 if !liveliness {
210 // kv-store not reachable or down, updating the status to not ready state
khenaidoo106c61a2021-08-11 18:05:46 -0400211 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusNotReady)
cbabu116b73f2019-12-10 17:56:32 +0530212 timeout = a.config.NotLiveProbeInterval
213 } else {
214 // kv-store is reachable , updating the status to running state
khenaidoo106c61a2021-08-11 18:05:46 -0400215 probe.UpdateStatusFromContext(ctx, kvService, probe.ServiceStatusRunning)
cbabu116b73f2019-12-10 17:56:32 +0530216 timeout = a.config.LiveProbeInterval / 2
217 }
218 // Check if the timer has expired or not
219 if !timeoutTimer.Stop() {
220 <-timeoutTimer.C
221 }
222 case <-timeoutTimer.C:
Girish Kumarbeadc112020-02-26 18:41:02 +0000223 // Check the status of the kv-store. Use timeout of 2 seconds to avoid forever blocking
Neha Sharma96b7bf22020-06-15 10:37:32 +0000224 logger.Info(ctx, "kv-store liveliness-recheck")
Girish Kumarbeadc112020-02-26 18:41:02 +0000225 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
226
227 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
228 // Cleanup cancel func resources
229 cancelFunc()
cbabu95f21522019-11-13 14:25:18 +0100230 }
cbabu116b73f2019-12-10 17:56:32 +0530231 }
232}
233
npujarec5762e2020-01-01 14:08:48 +0530234func (a *adapter) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700235 // Stop leadership tracking
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700236 a.halted = true
cuilin20187b2a8c32019-03-26 19:52:28 -0700237
238 // send exit signal
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 a.exitChannel <- 0
cuilin20187b2a8c32019-03-26 19:52:28 -0700240
241 // Cleanup - applies only if we had a kvClient
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700242 if a.kvClient != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700243 // Release all reservations
npujarec5762e2020-01-01 14:08:48 +0530244 if err := a.kvClient.ReleaseAllReservations(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000245 logger.Infow(ctx, "fail-to-release-all-reservations", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700246 }
247 // Close the DB connection
Neha Sharma96b7bf22020-06-15 10:37:32 +0000248 a.kvClient.Close(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700249 }
250
khenaidoo106c61a2021-08-11 18:05:46 -0400251 if a.eventProxy != nil {
252 a.eventProxy.Stop()
Scott Bakere701b862020-02-20 16:19:16 -0800253 }
254
khenaidoo106c61a2021-08-11 18:05:46 -0400255 if a.kafkaClient != nil {
256 a.kafkaClient.Stop(ctx)
257 }
258
259 // Stop core client
260 if a.coreClient != nil {
261 a.coreClient.Stop(ctx)
262 }
263
264 // TODO: Stop child devices connections
265
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 // TODO: More cleanup
267}
268
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269func newKVClient(ctx context.Context, storeType, address string, timeout time.Duration) (kvstore.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700270
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700272 switch storeType {
cuilin20187b2a8c32019-03-26 19:52:28 -0700273 case "etcd":
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
cuilin20187b2a8c32019-03-26 19:52:28 -0700275 }
276 return nil, errors.New("unsupported-kv-store")
277}
278
Neha Sharma96b7bf22020-06-15 10:37:32 +0000279func newKafkaClient(ctx context.Context, clientType, address string) (kafka.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700280
Neha Sharma96b7bf22020-06-15 10:37:32 +0000281 logger.Infow(ctx, "common-client-type", log.Fields{"client": clientType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 switch clientType {
283 case "sarama":
284 return kafka.NewSaramaClient(
Neha Sharma3f221ae2020-04-29 19:02:12 +0000285 kafka.Address(address),
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 kafka.ProducerReturnOnErrors(true),
287 kafka.ProducerReturnOnSuccess(true),
288 kafka.ProducerMaxRetries(6),
Abhilash S.L3b494632019-07-16 15:51:09 +0530289 kafka.ProducerRetryBackoff(time.Millisecond*30),
290 kafka.MetadatMaxRetries(15)), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700292
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 return nil, errors.New("unsupported-client-type")
294}
295
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296func (a *adapter) setKVClient(ctx context.Context) error {
297 client, err := newKVClient(ctx, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
cuilin20187b2a8c32019-03-26 19:52:28 -0700298 if err != nil {
299 a.kvClient = nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 return err
301 }
302 a.kvClient = client
divyadesaia37f78b2020-02-07 12:41:22 +0000303
cuilin20187b2a8c32019-03-26 19:52:28 -0700304 return nil
305}
306
khenaidoo106c61a2021-08-11 18:05:46 -0400307// startGRPCService creates the grpc service handlers, registers it to the grpc server and starts the server
308func (a *adapter) startGRPCService(ctx context.Context, server *vgrpc.GrpcServer, serviceName string) {
309 logger.Infow(ctx, "starting-grpc-service", log.Fields{"service": serviceName})
310
311 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
312 logger.Infow(ctx, "grpc-service-started", log.Fields{"service": serviceName})
313
314 server.Start(ctx)
315 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusStopped)
cuilin20187b2a8c32019-03-26 19:52:28 -0700316}
317
khenaidoodc2116e2021-10-19 17:33:19 -0400318func (a *adapter) addAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler adapter_service.AdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400319 logger.Info(ctx, "adding-adapter-service")
320
321 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400322 adapter_service.RegisterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400323 })
324}
325
khenaidoodc2116e2021-10-19 17:33:19 -0400326func (a *adapter) addOltInterAdapterService(ctx context.Context, server *vgrpc.GrpcServer, handler olt_inter_adapter_service.OltInterAdapterServiceServer) {
khenaidoo106c61a2021-08-11 18:05:46 -0400327 logger.Info(ctx, "adding-olt-inter-adapter-service")
328
329 server.AddService(func(gs *grpc.Server) {
khenaidoodc2116e2021-10-19 17:33:19 -0400330 olt_inter_adapter_service.RegisterOltInterAdapterServiceServer(gs, handler)
khenaidoo106c61a2021-08-11 18:05:46 -0400331 })
332}
333
334func (a *adapter) startOpenOLT(ctx context.Context, cc *vgrpc.Client, ep eventif.EventProxy,
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800335 cfg *config.AdapterFlags, cm *conf.ConfigManager) (*ac.OpenOLT, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Info(ctx, "starting-open-olt")
cuilin20187b2a8c32019-03-26 19:52:28 -0700337 var err error
khenaidoo106c61a2021-08-11 18:05:46 -0400338 sOLT := ac.NewOpenOLT(ctx, cc, ep, cfg, cm)
cuilin20187b2a8c32019-03-26 19:52:28 -0700339
340 if err = sOLT.Start(ctx); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700341 return nil, err
342 }
343
Neha Sharma96b7bf22020-06-15 10:37:32 +0000344 logger.Info(ctx, "open-olt-started")
cuilin20187b2a8c32019-03-26 19:52:28 -0700345 return sOLT, nil
346}
347
khenaidoo106c61a2021-08-11 18:05:46 -0400348func (a *adapter) registerWithCore(ctx context.Context, serviceName string, retries int) error {
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700349 adapterID := fmt.Sprintf("openolt_%d", a.config.CurrentReplica)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000350 logger.Infow(ctx, "registering-with-core", log.Fields{
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700351 "adapterID": adapterID,
352 "currentReplica": a.config.CurrentReplica,
353 "totalReplicas": a.config.TotalReplicas,
354 })
355 adapterDescription := &voltha.Adapter{
356 Id: adapterID, // Unique name for the device type
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400357 Vendor: "VOLTHA OpenOLT",
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700358 Version: version.VersionInfo.Version,
khenaidoo106c61a2021-08-11 18:05:46 -0400359 // The Endpoint refers to the address this service is listening on.
360 Endpoint: a.config.AdapterEndpoint,
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700361 Type: "openolt",
362 CurrentReplica: int32(a.config.CurrentReplica),
363 TotalReplicas: int32(a.config.TotalReplicas),
364 }
365 types := []*voltha.DeviceType{{
366 Id: "openolt",
khenaidoo106c61a2021-08-11 18:05:46 -0400367 AdapterType: "openolt", // Type of the adapter that handles device type
368 Adapter: "openolt", // Deprecated attribute
Girish Gowdru0c588b22019-04-23 23:24:56 -0400369 AcceptsBulkFlowUpdate: false, // Currently openolt adapter does not support bulk flow handling
370 AcceptsAddRemoveFlowUpdates: true}}
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 deviceTypes := &voltha.DeviceTypes{Items: types}
372 count := 0
373 for {
khenaidoo106c61a2021-08-11 18:05:46 -0400374 gClient, err := a.coreClient.GetCoreServiceClient()
375 if gClient != nil {
khenaidoodc2116e2021-10-19 17:33:19 -0400376 if _, err = gClient.RegisterAdapter(log.WithSpanFromContext(context.TODO(), ctx), &ca.AdapterRegistration{
khenaidoo106c61a2021-08-11 18:05:46 -0400377 Adapter: adapterDescription,
378 DTypes: deviceTypes}); err == nil {
379 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700380 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700381 }
khenaidoo106c61a2021-08-11 18:05:46 -0400382 logger.Warnw(ctx, "registering-with-core-failed", log.Fields{"endpoint": a.config.CoreEndpoint, "error": err, "count": count, "gclient": gClient})
383 if retries == count {
384 return err
385 }
386 count++
387 // Take a nap before retrying
388 time.Sleep(2 * time.Second)
cuilin20187b2a8c32019-03-26 19:52:28 -0700389 }
khenaidoo106c61a2021-08-11 18:05:46 -0400390 probe.UpdateStatusFromContext(ctx, serviceName, probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000391 logger.Info(ctx, "registered-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700392 return nil
393}
394
Neha Sharma96b7bf22020-06-15 10:37:32 +0000395func waitForExit(ctx context.Context) int {
cuilin20187b2a8c32019-03-26 19:52:28 -0700396 signalChannel := make(chan os.Signal, 1)
397 signal.Notify(signalChannel,
398 syscall.SIGHUP,
399 syscall.SIGINT,
400 syscall.SIGTERM,
401 syscall.SIGQUIT)
402
403 exitChannel := make(chan int)
404
405 go func() {
406 s := <-signalChannel
407 switch s {
408 case syscall.SIGHUP,
409 syscall.SIGINT,
410 syscall.SIGTERM,
411 syscall.SIGQUIT:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000412 logger.Infow(ctx, "closing-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 exitChannel <- 0
414 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000415 logger.Infow(ctx, "unexpected-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700416 exitChannel <- 1
417 }
418 }()
419
420 code := <-exitChannel
421 return code
422}
423
424func printBanner() {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800425 fmt.Println(` ____ ____ _ _______ `)
426 fmt.Println(` / _ \ / __ \| | |__ __|`)
427 fmt.Println(` | | | |_ __ ___ _ __ | | | | | | | `)
428 fmt.Println(` | | | | '_ \ / _ \ '_ \ | | | | | | | `)
429 fmt.Println(` | |__| | |_) | __/ | | || |__| | |____| | `)
430 fmt.Println(` \____/| .__/ \___|_| |_| \____/|______|_| `)
431 fmt.Println(` | | `)
432 fmt.Println(` |_| `)
433 fmt.Println(` `)
cuilin20187b2a8c32019-03-26 19:52:28 -0700434}
435
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400436func printVersion() {
437 fmt.Println("VOLTHA OpenOLT Adapter")
438 fmt.Println(version.VersionInfo.String(" "))
439}
440
cuilin20187b2a8c32019-03-26 19:52:28 -0700441func main() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 ctx := context.Background()
cuilin20187b2a8c32019-03-26 19:52:28 -0700443 start := time.Now()
444
445 cf := config.NewAdapterFlags()
446 cf.ParseCommandArguments()
447
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700448 // Setup logging
cuilin20187b2a8c32019-03-26 19:52:28 -0700449
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000450 logLevel, err := log.StringToLogLevel(cf.LogLevel)
451 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000452 logger.Fatalf(ctx, "Cannot setup logging, %s", err)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000453 }
Rohan Agrawal2488f192020-01-31 09:26:55 +0000454
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 // Setup default logger - applies for packages that do not have specific logger set
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000456 if _, err := log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000457 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700458 }
459
460 // Update all loggers (provisionned via init) with a common field
Hardik Windlassb9c869b2019-10-10 08:34:32 +0000461 if err := log.UpdateAllLoggers(log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000462 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700463 }
464
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000465 log.SetAllLogLevel(logLevel)
Rohan Agrawal93bced32020-02-11 10:16:01 +0000466
Matteo Scandolo8f2b9572020-02-28 15:35:23 -0800467 realMain()
468
Kent Hagermane6ff1012020-07-14 15:07:53 -0400469 defer func() {
470 err := log.CleanUp()
471 if err != nil {
472 logger.Errorw(context.Background(), "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
473 }
474 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700475
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400476 // Print version / build information and exit
477 if cf.DisplayVersionOnly {
478 printVersion()
479 return
480 }
481
cuilin20187b2a8c32019-03-26 19:52:28 -0700482 // Print banner if specified
483 if cf.Banner {
484 printBanner()
485 }
486
Neha Sharma96b7bf22020-06-15 10:37:32 +0000487 logger.Infow(ctx, "config", log.Fields{"config": *cf})
cuilin20187b2a8c32019-03-26 19:52:28 -0700488
489 ctx, cancel := context.WithCancel(context.Background())
490 defer cancel()
491
492 ad := newAdapter(cf)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000493
494 p := &probe.Probe{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000495 go p.ListenAndServe(ctx, ad.config.ProbeAddress)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000496
497 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
498
Girish Kumar935f7af2020-08-18 11:59:42 +0000499 closer, err := log.GetGlobalLFM().InitTracingAndLogCorrelation(cf.TraceEnabled, cf.TraceAgentAddress, cf.LogCorrelationEnabled)
Girish Kumar11e15972020-06-15 14:51:10 +0000500 if err != nil {
501 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
502 } else {
503 defer log.TerminateTracing(closer)
504 }
505
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000506 go ad.start(probeCtx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700507
Neha Sharma96b7bf22020-06-15 10:37:32 +0000508 code := waitForExit(ctx)
509 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
cuilin20187b2a8c32019-03-26 19:52:28 -0700510
511 // Cleanup before leaving
npujarec5762e2020-01-01 14:08:48 +0530512 ad.stop(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700513
514 elapsed := time.Since(start)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000515 logger.Infow(ctx, "run-time", log.Fields{"instanceId": ad.config.InstanceID, "time": elapsed / time.Second})
cuilin20187b2a8c32019-03-26 19:52:28 -0700516}