blob: b4fe6dd90537fd28bf2a3a5a5704da49a088fb21 [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
Girish Gowdra4c3d4602021-07-22 16:33:37 -070029 "github.com/opencord/voltha-lib-go/v6/pkg/adapters"
30 "github.com/opencord/voltha-lib-go/v6/pkg/adapters/adapterif"
31 com "github.com/opencord/voltha-lib-go/v6/pkg/adapters/common"
32 conf "github.com/opencord/voltha-lib-go/v6/pkg/config"
33 "github.com/opencord/voltha-lib-go/v6/pkg/db/kvstore"
34 "github.com/opencord/voltha-lib-go/v6/pkg/events"
35 "github.com/opencord/voltha-lib-go/v6/pkg/events/eventif"
36 "github.com/opencord/voltha-lib-go/v6/pkg/kafka"
37 "github.com/opencord/voltha-lib-go/v6/pkg/log"
38 "github.com/opencord/voltha-lib-go/v6/pkg/probe"
39 "github.com/opencord/voltha-lib-go/v6/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"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070042 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
43 "github.com/opencord/voltha-protos/v4/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070044)
45
46type adapter struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070047 instanceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070048 config *config.AdapterFlags
49 iAdapter adapters.IAdapter
50 kafkaClient kafka.Client
51 kvClient kvstore.Client
npujarec5762e2020-01-01 14:08:48 +053052 kip kafka.InterContainerProxy
kdarapu381c6902019-07-31 18:23:16 +053053 coreProxy adapterif.CoreProxy
54 adapterProxy adapterif.AdapterProxy
Himani Chawlacd407802020-12-10 12:08:59 +053055 eventProxy eventif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070056 halted bool
57 exitChannel chan int
58 receiverChannels []<-chan *ic.InterContainerMessage
59}
60
cuilin20187b2a8c32019-03-26 19:52:28 -070061func newAdapter(cf *config.AdapterFlags) *adapter {
62 var a adapter
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063 a.instanceID = cf.InstanceID
cuilin20187b2a8c32019-03-26 19:52:28 -070064 a.config = cf
65 a.halted = false
66 a.exitChannel = make(chan int, 1)
67 a.receiverChannels = make([]<-chan *ic.InterContainerMessage, 0)
68 return &a
69}
70
71func (a *adapter) start(ctx context.Context) {
Neha Sharma96b7bf22020-06-15 10:37:32 +000072 logger.Info(ctx, "Starting Core Adapter components")
cuilin20187b2a8c32019-03-26 19:52:28 -070073 var err error
74
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000075 var p *probe.Probe
76 if value := ctx.Value(probe.ProbeContextKey); value != nil {
77 if _, ok := value.(*probe.Probe); ok {
78 p = value.(*probe.Probe)
79 p.RegisterService(
Neha Sharma96b7bf22020-06-15 10:37:32 +000080 ctx,
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000081 "message-bus",
82 "kv-store",
83 "container-proxy",
84 "core-request-handler",
85 "register-with-core",
86 )
87 }
88 }
89
cuilin20187b2a8c32019-03-26 19:52:28 -070090 // Setup KV Client
Neha Sharma96b7bf22020-06-15 10:37:32 +000091 logger.Debugw(ctx, "create-kv-client", log.Fields{"kvstore": a.config.KVStoreType})
92 if err = a.setKVClient(ctx); err != nil {
93 logger.Fatalw(ctx, "error-setting-kv-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -070094 }
95
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000096 if p != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +000097 p.UpdateStatus(ctx, "kv-store", probe.ServiceStatusRunning)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +000098 }
99
divyadesaia37f78b2020-02-07 12:41:22 +0000100 // Setup Log Config
Neha Sharma96b7bf22020-06-15 10:37:32 +0000101 cm := conf.NewConfigManager(ctx, a.kvClient, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800102
divyadesaid26f6b12020-03-19 06:30:28 +0000103 go conf.StartLogLevelConfigProcessing(cm, ctx)
Girish Kumar935f7af2020-08-18 11:59:42 +0000104 go conf.StartLogFeaturesConfigProcessing(cm, ctx)
divyadesaia37f78b2020-02-07 12:41:22 +0000105
cuilin20187b2a8c32019-03-26 19:52:28 -0700106 // Setup Kafka Client
Neha Sharma96b7bf22020-06-15 10:37:32 +0000107 if a.kafkaClient, err = newKafkaClient(ctx, "sarama", a.config.KafkaAdapterAddress); err != nil {
108 logger.Fatalw(ctx, "Unsupported-common-client", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700109 }
110
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000111 if p != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000112 p.UpdateStatus(ctx, "message-bus", probe.ServiceStatusRunning)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000113 }
114
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700115 // setup endpointManager
116
cuilin20187b2a8c32019-03-26 19:52:28 -0700117 // Start the common InterContainer Proxy - retries indefinitely
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000118 if a.kip, err = a.startInterContainerProxy(ctx, -1); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000119 logger.Fatal(ctx, "error-starting-inter-container-proxy")
cuilin20187b2a8c32019-03-26 19:52:28 -0700120 }
121
122 // Create the core proxy to handle requests to the Core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000123 a.coreProxy = com.NewCoreProxy(ctx, a.kip, a.config.Topic, a.config.CoreTopic)
cuilin20187b2a8c32019-03-26 19:52:28 -0700124
125 // Create the adaptor proxy to handle request between olt and onu
Matteo Scandolo46654682020-08-05 11:46:37 -0700126 a.adapterProxy = com.NewAdapterProxy(ctx, a.kip, a.config.CoreTopic, cm.Backend)
cuilin20187b2a8c32019-03-26 19:52:28 -0700127
Devmalya Paulfb990a52019-07-09 10:01:49 -0400128 // Create the event proxy to post events to KAFKA
Himani Chawlacd407802020-12-10 12:08:59 +0530129 a.eventProxy = events.NewEventProxy(events.MsgClient(a.kafkaClient), events.MsgTopic(kafka.Topic{Name: a.config.EventTopic}))
Devmalya Paulfb990a52019-07-09 10:01:49 -0400130
cuilin20187b2a8c32019-03-26 19:52:28 -0700131 // Create the open OLT adapter
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800132 if a.iAdapter, err = a.startOpenOLT(ctx, a.kip, a.coreProxy, a.adapterProxy, a.eventProxy, a.config, cm); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000133 logger.Fatalw(ctx, "error-starting-openolt", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700134 }
135
136 // Register the core request handler
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000137 if err = a.setupRequestHandler(ctx, a.instanceID, a.iAdapter); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000138 logger.Fatalw(ctx, "error-setting-core-request-handler", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700139 }
140
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700141 // Register this adapter to the Core - retries indefinitely
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000142 if err = a.registerWithCore(ctx, -1); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000143 logger.Fatal(ctx, "error-registering-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700144 }
cbabu95f21522019-11-13 14:25:18 +0100145
cbabu116b73f2019-12-10 17:56:32 +0530146 // check the readiness and liveliness and update the probe status
147 a.checkServicesReadiness(ctx)
cbabu95f21522019-11-13 14:25:18 +0100148}
149
150/**
151This function checks the liveliness and readiness of the kakfa and kv-client services
152and update the status in the probe.
153*/
cbabu116b73f2019-12-10 17:56:32 +0530154func (a *adapter) checkServicesReadiness(ctx context.Context) {
155 // checks the kafka readiness
156 go a.checkKafkaReadiness(ctx)
157
158 // checks the kv-store readiness
159 go a.checkKvStoreReadiness(ctx)
160}
161
162/**
163This function checks the liveliness and readiness of the kv-store service
164and update the status in the probe.
165*/
166func (a *adapter) checkKvStoreReadiness(ctx context.Context) {
167 // dividing the live probe interval by 2 to get updated status every 30s
168 timeout := a.config.LiveProbeInterval / 2
169 kvStoreChannel := make(chan bool, 1)
170
171 // Default false to check the liveliness.
172 kvStoreChannel <- false
cbabu95f21522019-11-13 14:25:18 +0100173 for {
cbabu116b73f2019-12-10 17:56:32 +0530174 timeoutTimer := time.NewTimer(timeout)
175 select {
176 case liveliness := <-kvStoreChannel:
177 if !liveliness {
178 // kv-store not reachable or down, updating the status to not ready state
179 probe.UpdateStatusFromContext(ctx, "kv-store", probe.ServiceStatusNotReady)
180 timeout = a.config.NotLiveProbeInterval
181 } else {
182 // kv-store is reachable , updating the status to running state
183 probe.UpdateStatusFromContext(ctx, "kv-store", probe.ServiceStatusRunning)
184 timeout = a.config.LiveProbeInterval / 2
185 }
186 // Check if the timer has expired or not
187 if !timeoutTimer.Stop() {
188 <-timeoutTimer.C
189 }
190 case <-timeoutTimer.C:
Girish Kumarbeadc112020-02-26 18:41:02 +0000191 // Check the status of the kv-store. Use timeout of 2 seconds to avoid forever blocking
Neha Sharma96b7bf22020-06-15 10:37:32 +0000192 logger.Info(ctx, "kv-store liveliness-recheck")
Girish Kumarbeadc112020-02-26 18:41:02 +0000193 timeoutCtx, cancelFunc := context.WithTimeout(ctx, 2*time.Second)
194
195 kvStoreChannel <- a.kvClient.IsConnectionUp(timeoutCtx)
196 // Cleanup cancel func resources
197 cancelFunc()
cbabu95f21522019-11-13 14:25:18 +0100198 }
cbabu116b73f2019-12-10 17:56:32 +0530199 }
200}
201
202/**
203This function checks the liveliness and readiness of the kafka service
204and update the status in the probe.
205*/
206func (a *adapter) checkKafkaReadiness(ctx context.Context) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000207 livelinessChannel := a.kafkaClient.EnableLivenessChannel(ctx, true)
208 healthinessChannel := a.kafkaClient.EnableHealthinessChannel(ctx, true)
cbabu116b73f2019-12-10 17:56:32 +0530209 timeout := a.config.LiveProbeInterval
Scott Bakere701b862020-02-20 16:19:16 -0800210 failed := false
cbabu116b73f2019-12-10 17:56:32 +0530211 for {
212 timeoutTimer := time.NewTimer(timeout)
213
214 select {
Scott Baker86fce9a2019-12-12 09:47:17 -0800215 case healthiness := <-healthinessChannel:
216 if !healthiness {
Scott Bakere701b862020-02-20 16:19:16 -0800217 // This will eventually cause K8s to restart the container, and will do
218 // so in a way that allows cleanup to continue, rather than an immediate
219 // panic and exit here.
220 probe.UpdateStatusFromContext(ctx, "message-bus", probe.ServiceStatusFailed)
221 failed = true
222 }
223 // Check if the timer has expired or not
224 if !timeoutTimer.Stop() {
225 <-timeoutTimer.C
Scott Baker86fce9a2019-12-12 09:47:17 -0800226 }
cbabu116b73f2019-12-10 17:56:32 +0530227 case liveliness := <-livelinessChannel:
Scott Bakere701b862020-02-20 16:19:16 -0800228 if failed {
229 // Failures of the message bus are permanent and can't ever be recovered from,
230 // so make sure we never inadvertently reset a failed state back to unready.
231 } else if !liveliness {
cbabu116b73f2019-12-10 17:56:32 +0530232 // kafka not reachable or down, updating the status to not ready state
233 probe.UpdateStatusFromContext(ctx, "message-bus", probe.ServiceStatusNotReady)
234 timeout = a.config.NotLiveProbeInterval
235 } else {
236 // kafka is reachable , updating the status to running state
237 probe.UpdateStatusFromContext(ctx, "message-bus", probe.ServiceStatusRunning)
238 timeout = a.config.LiveProbeInterval
239 }
240 // Check if the timer has expired or not
241 if !timeoutTimer.Stop() {
242 <-timeoutTimer.C
243 }
244 case <-timeoutTimer.C:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000245 logger.Info(ctx, "kafka-proxy-liveness-recheck")
cbabu116b73f2019-12-10 17:56:32 +0530246 // send the liveness probe in a goroutine; we don't want to deadlock ourselves as
247 // the liveness probe may wait (and block) writing to our channel.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000248 err := a.kafkaClient.SendLiveness(ctx)
cbabu116b73f2019-12-10 17:56:32 +0530249 if err != nil {
250 // Catch possible error case if sending liveness after Sarama has been stopped.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000251 logger.Warnw(ctx, "error-kafka-send-liveness", log.Fields{"error": err})
cbabu116b73f2019-12-10 17:56:32 +0530252 }
cbabu95f21522019-11-13 14:25:18 +0100253 }
cbabu95f21522019-11-13 14:25:18 +0100254 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700255}
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
264 // Cleanup - applies only if we had a kvClient
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 if a.kvClient != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 // Release all reservations
npujarec5762e2020-01-01 14:08:48 +0530267 if err := a.kvClient.ReleaseAllReservations(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000268 logger.Infow(ctx, "fail-to-release-all-reservations", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700269 }
270 // Close the DB connection
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 a.kvClient.Close(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700272 }
273
Scott Bakere701b862020-02-20 16:19:16 -0800274 if a.kip != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000275 a.kip.Stop(ctx)
Scott Bakere701b862020-02-20 16:19:16 -0800276 }
277
cuilin20187b2a8c32019-03-26 19:52:28 -0700278 // TODO: More cleanup
279}
280
Neha Sharma96b7bf22020-06-15 10:37:32 +0000281func newKVClient(ctx context.Context, storeType, address string, timeout time.Duration) (kvstore.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700282
Neha Sharma96b7bf22020-06-15 10:37:32 +0000283 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700284 switch storeType {
cuilin20187b2a8c32019-03-26 19:52:28 -0700285 case "etcd":
Neha Sharma96b7bf22020-06-15 10:37:32 +0000286 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
cuilin20187b2a8c32019-03-26 19:52:28 -0700287 }
288 return nil, errors.New("unsupported-kv-store")
289}
290
Neha Sharma96b7bf22020-06-15 10:37:32 +0000291func newKafkaClient(ctx context.Context, clientType, address string) (kafka.Client, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700292
Neha Sharma96b7bf22020-06-15 10:37:32 +0000293 logger.Infow(ctx, "common-client-type", log.Fields{"client": clientType})
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 switch clientType {
295 case "sarama":
296 return kafka.NewSaramaClient(
Neha Sharma3f221ae2020-04-29 19:02:12 +0000297 kafka.Address(address),
cuilin20187b2a8c32019-03-26 19:52:28 -0700298 kafka.ProducerReturnOnErrors(true),
299 kafka.ProducerReturnOnSuccess(true),
300 kafka.ProducerMaxRetries(6),
Abhilash S.L3b494632019-07-16 15:51:09 +0530301 kafka.ProducerRetryBackoff(time.Millisecond*30),
302 kafka.MetadatMaxRetries(15)), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700303 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700304
cuilin20187b2a8c32019-03-26 19:52:28 -0700305 return nil, errors.New("unsupported-client-type")
306}
307
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308func (a *adapter) setKVClient(ctx context.Context) error {
309 client, err := newKVClient(ctx, a.config.KVStoreType, a.config.KVStoreAddress, a.config.KVStoreTimeout)
cuilin20187b2a8c32019-03-26 19:52:28 -0700310 if err != nil {
311 a.kvClient = nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700312 return err
313 }
314 a.kvClient = client
divyadesaia37f78b2020-02-07 12:41:22 +0000315
cuilin20187b2a8c32019-03-26 19:52:28 -0700316 return nil
317}
318
npujarec5762e2020-01-01 14:08:48 +0530319func (a *adapter) startInterContainerProxy(ctx context.Context, retries int) (kafka.InterContainerProxy, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Infow(ctx, "starting-intercontainer-messaging-proxy", log.Fields{"address": a.config.KafkaAdapterAddress,
Neha Sharma3f221ae2020-04-29 19:02:12 +0000321 "topic": a.config.Topic})
cuilin20187b2a8c32019-03-26 19:52:28 -0700322 var err error
npujarec5762e2020-01-01 14:08:48 +0530323 kip := kafka.NewInterContainerProxy(
Neha Sharma3f221ae2020-04-29 19:02:12 +0000324 kafka.InterContainerAddress(a.config.KafkaAdapterAddress),
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 kafka.MsgClient(a.kafkaClient),
npujarec5762e2020-01-01 14:08:48 +0530326 kafka.DefaultTopic(&kafka.Topic{Name: a.config.Topic}))
cuilin20187b2a8c32019-03-26 19:52:28 -0700327 count := 0
328 for {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000329 if err = kip.Start(ctx); err != nil {
330 logger.Warnw(ctx, "error-starting-messaging-proxy", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 if retries == count {
332 return nil, err
333 }
334 count = +1
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700335 // Take a nap before retrying
cuilin20187b2a8c32019-03-26 19:52:28 -0700336 time.Sleep(2 * time.Second)
337 } else {
338 break
339 }
340 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000341 probe.UpdateStatusFromContext(ctx, "container-proxy", probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Info(ctx, "common-messaging-proxy-created")
cuilin20187b2a8c32019-03-26 19:52:28 -0700343 return kip, nil
344}
345
npujarec5762e2020-01-01 14:08:48 +0530346func (a *adapter) startOpenOLT(ctx context.Context, kip kafka.InterContainerProxy,
Himani Chawlacd407802020-12-10 12:08:59 +0530347 cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep eventif.EventProxy,
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800348 cfg *config.AdapterFlags, cm *conf.ConfigManager) (*ac.OpenOLT, error) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000349 logger.Info(ctx, "starting-open-olt")
cuilin20187b2a8c32019-03-26 19:52:28 -0700350 var err error
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800351 sOLT := ac.NewOpenOLT(ctx, a.kip, cp, ap, ep, cfg, cm)
cuilin20187b2a8c32019-03-26 19:52:28 -0700352
353 if err = sOLT.Start(ctx); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700354 return nil, err
355 }
356
Neha Sharma96b7bf22020-06-15 10:37:32 +0000357 logger.Info(ctx, "open-olt-started")
cuilin20187b2a8c32019-03-26 19:52:28 -0700358 return sOLT, nil
359}
360
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000361func (a *adapter) setupRequestHandler(ctx context.Context, coreInstanceID string, iadapter adapters.IAdapter) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000362 logger.Info(ctx, "setting-request-handler")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700363 requestProxy := com.NewRequestHandlerProxy(coreInstanceID, iadapter, a.coreProxy)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000364 if err := a.kip.SubscribeWithRequestHandlerInterface(ctx, kafka.Topic{Name: a.config.Topic}, requestProxy); err != nil {
cuilin20187b2a8c32019-03-26 19:52:28 -0700365 return err
366
367 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000368 probe.UpdateStatusFromContext(ctx, "core-request-handler", probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000369 logger.Info(ctx, "request-handler-setup-done")
cuilin20187b2a8c32019-03-26 19:52:28 -0700370 return nil
371}
372
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000373func (a *adapter) registerWithCore(ctx context.Context, retries int) error {
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700374 adapterID := fmt.Sprintf("openolt_%d", a.config.CurrentReplica)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000375 logger.Infow(ctx, "registering-with-core", log.Fields{
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700376 "adapterID": adapterID,
377 "currentReplica": a.config.CurrentReplica,
378 "totalReplicas": a.config.TotalReplicas,
379 })
380 adapterDescription := &voltha.Adapter{
381 Id: adapterID, // Unique name for the device type
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400382 Vendor: "VOLTHA OpenOLT",
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700383 Version: version.VersionInfo.Version,
384 // TODO once we'll be ready to support multiple versions of the OpenOLT adapter
385 // the Endpoint will have to change to `openolt_<currentReplica`>
serkant.uluderya5e3528d2020-05-22 19:31:07 -0700386 Endpoint: a.config.Topic,
Matteo Scandolo3ad5d2b2020-04-02 17:02:04 -0700387 Type: "openolt",
388 CurrentReplica: int32(a.config.CurrentReplica),
389 TotalReplicas: int32(a.config.TotalReplicas),
390 }
391 types := []*voltha.DeviceType{{
392 Id: "openolt",
393 Adapter: "openolt", // Type of the adapter that handles device type
Girish Gowdru0c588b22019-04-23 23:24:56 -0400394 AcceptsBulkFlowUpdate: false, // Currently openolt adapter does not support bulk flow handling
395 AcceptsAddRemoveFlowUpdates: true}}
cuilin20187b2a8c32019-03-26 19:52:28 -0700396 deviceTypes := &voltha.DeviceTypes{Items: types}
397 count := 0
398 for {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000399 if err := a.coreProxy.RegisterAdapter(log.WithSpanFromContext(context.TODO(), ctx), adapterDescription, deviceTypes); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000400 logger.Warnw(ctx, "registering-with-core-failed", log.Fields{"error": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700401 if retries == count {
402 return err
403 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700404 count++
405 // Take a nap before retrying
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 time.Sleep(2 * time.Second)
407 } else {
408 break
409 }
410 }
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000411 probe.UpdateStatusFromContext(ctx, "register-with-core", probe.ServiceStatusRunning)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000412 logger.Info(ctx, "registered-with-core")
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 return nil
414}
415
Neha Sharma96b7bf22020-06-15 10:37:32 +0000416func waitForExit(ctx context.Context) int {
cuilin20187b2a8c32019-03-26 19:52:28 -0700417 signalChannel := make(chan os.Signal, 1)
418 signal.Notify(signalChannel,
419 syscall.SIGHUP,
420 syscall.SIGINT,
421 syscall.SIGTERM,
422 syscall.SIGQUIT)
423
424 exitChannel := make(chan int)
425
426 go func() {
427 s := <-signalChannel
428 switch s {
429 case syscall.SIGHUP,
430 syscall.SIGINT,
431 syscall.SIGTERM,
432 syscall.SIGQUIT:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 logger.Infow(ctx, "closing-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700434 exitChannel <- 0
435 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000436 logger.Infow(ctx, "unexpected-signal-received", log.Fields{"signal": s})
cuilin20187b2a8c32019-03-26 19:52:28 -0700437 exitChannel <- 1
438 }
439 }()
440
441 code := <-exitChannel
442 return code
443}
444
445func printBanner() {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 fmt.Println(` ____ ____ _ _______ `)
447 fmt.Println(` / _ \ / __ \| | |__ __|`)
448 fmt.Println(` | | | |_ __ ___ _ __ | | | | | | | `)
449 fmt.Println(` | | | | '_ \ / _ \ '_ \ | | | | | | | `)
450 fmt.Println(` | |__| | |_) | __/ | | || |__| | |____| | `)
451 fmt.Println(` \____/| .__/ \___|_| |_| \____/|______|_| `)
452 fmt.Println(` | | `)
453 fmt.Println(` |_| `)
454 fmt.Println(` `)
cuilin20187b2a8c32019-03-26 19:52:28 -0700455}
456
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400457func printVersion() {
458 fmt.Println("VOLTHA OpenOLT Adapter")
459 fmt.Println(version.VersionInfo.String(" "))
460}
461
cuilin20187b2a8c32019-03-26 19:52:28 -0700462func main() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000463 ctx := context.Background()
cuilin20187b2a8c32019-03-26 19:52:28 -0700464 start := time.Now()
465
466 cf := config.NewAdapterFlags()
467 cf.ParseCommandArguments()
468
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 // Setup logging
cuilin20187b2a8c32019-03-26 19:52:28 -0700470
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000471 logLevel, err := log.StringToLogLevel(cf.LogLevel)
472 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 logger.Fatalf(ctx, "Cannot setup logging, %s", err)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000474 }
Rohan Agrawal2488f192020-01-31 09:26:55 +0000475
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700476 // Setup default logger - applies for packages that do not have specific logger set
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000477 if _, err := log.SetDefaultLogger(log.JSON, logLevel, log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000478 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700479 }
480
481 // Update all loggers (provisionned via init) with a common field
Hardik Windlassb9c869b2019-10-10 08:34:32 +0000482 if err := log.UpdateAllLoggers(log.Fields{"instanceId": cf.InstanceID}); err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000483 logger.With(log.Fields{"error": err}).Fatal(ctx, "Cannot setup logging")
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 }
485
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000486 log.SetAllLogLevel(logLevel)
Rohan Agrawal93bced32020-02-11 10:16:01 +0000487
Matteo Scandolo8f2b9572020-02-28 15:35:23 -0800488 realMain()
489
Kent Hagermane6ff1012020-07-14 15:07:53 -0400490 defer func() {
491 err := log.CleanUp()
492 if err != nil {
493 logger.Errorw(context.Background(), "unable-to-flush-any-buffered-log-entries", log.Fields{"error": err})
494 }
495 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700496
Matt Jeanneretf880eb62019-07-16 20:08:03 -0400497 // Print version / build information and exit
498 if cf.DisplayVersionOnly {
499 printVersion()
500 return
501 }
502
cuilin20187b2a8c32019-03-26 19:52:28 -0700503 // Print banner if specified
504 if cf.Banner {
505 printBanner()
506 }
507
Neha Sharma96b7bf22020-06-15 10:37:32 +0000508 logger.Infow(ctx, "config", log.Fields{"config": *cf})
cuilin20187b2a8c32019-03-26 19:52:28 -0700509
510 ctx, cancel := context.WithCancel(context.Background())
511 defer cancel()
512
513 ad := newAdapter(cf)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000514
515 p := &probe.Probe{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000516 go p.ListenAndServe(ctx, ad.config.ProbeAddress)
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000517
518 probeCtx := context.WithValue(ctx, probe.ProbeContextKey, p)
519
Girish Kumar935f7af2020-08-18 11:59:42 +0000520 closer, err := log.GetGlobalLFM().InitTracingAndLogCorrelation(cf.TraceEnabled, cf.TraceAgentAddress, cf.LogCorrelationEnabled)
Girish Kumar11e15972020-06-15 14:51:10 +0000521 if err != nil {
522 logger.Warnw(ctx, "unable-to-initialize-tracing-and-log-correlation-module", log.Fields{"error": err})
523 } else {
524 defer log.TerminateTracing(closer)
525 }
526
Rohan Agrawal828bf4e2019-10-22 10:13:19 +0000527 go ad.start(probeCtx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700528
Neha Sharma96b7bf22020-06-15 10:37:32 +0000529 code := waitForExit(ctx)
530 logger.Infow(ctx, "received-a-closing-signal", log.Fields{"code": code})
cuilin20187b2a8c32019-03-26 19:52:28 -0700531
532 // Cleanup before leaving
npujarec5762e2020-01-01 14:08:48 +0530533 ad.stop(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700534
535 elapsed := time.Since(start)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000536 logger.Infow(ctx, "run-time", log.Fields{"instanceId": ad.config.InstanceID, "time": elapsed / time.Second})
cuilin20187b2a8c32019-03-26 19:52:28 -0700537}